Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / netwerk / base / ProxyConfig.h
blob2deb1dd2a1f3b182a7f69073ad05d3240ef469ce
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_netwerk_base_proxy_config_h
7 #define mozilla_netwerk_base_proxy_config_h
9 #include <map>
11 #include "nsCRT.h"
12 #include "nsString.h"
13 #include "nsTArray.h"
15 // NOTE: This file is inspired by Chromium's code.
16 // https://source.chromium.org/chromium/chromium/src/+/main:net/proxy_resolution/proxy_config.h.
18 namespace mozilla {
19 namespace net {
21 // ProxyServer stores the {type, host, port} of a proxy server.
22 // ProxyServer is immutable.
23 class ProxyServer final {
24 public:
25 enum class ProxyType {
26 DIRECT = 0,
27 HTTP,
28 HTTPS,
29 SOCKS,
30 SOCKS4,
31 SOCKS5,
32 FTP,
33 // DEFAULT is a special type used on windows only.
34 DEFAULT
37 ProxyServer() = default;
39 ProxyServer(ProxyType aType, const nsACString& aHost, int32_t aPort)
40 : mType(aType), mHost(aHost), mPort(aPort) {}
42 const nsCString& Host() const { return mHost; }
44 int32_t Port() const { return mPort; }
46 ProxyType Type() const { return mType; }
48 void ToHostAndPortStr(nsACString& aOutput) {
49 aOutput.Truncate();
50 if (mType == ProxyType::DIRECT) {
51 return;
54 aOutput.Assign(mHost);
55 if (mPort != -1) {
56 aOutput.Append(':');
57 aOutput.AppendInt(mPort);
61 bool operator==(const ProxyServer& aOther) const {
62 return mType == aOther.mType && mHost == aOther.mHost &&
63 mPort == aOther.mPort;
66 bool operator!=(const ProxyServer& aOther) const {
67 return !(*this == aOther);
70 private:
71 ProxyType mType{ProxyType::DIRECT};
72 nsCString mHost;
73 int32_t mPort{-1};
76 // This class includes the information about proxy configuration.
77 // It contains enabled proxy servers, exception list, and the url of PAC
78 // script.
79 class ProxyConfig {
80 public:
81 struct ProxyRules {
82 ProxyRules() = default;
83 ~ProxyRules() = default;
85 std::map<ProxyServer::ProxyType, ProxyServer> mProxyServers;
88 struct ProxyBypassRules {
89 ProxyBypassRules() = default;
90 ~ProxyBypassRules() = default;
92 CopyableTArray<nsCString> mExceptions;
95 ProxyConfig() = default;
96 ProxyConfig(const ProxyConfig& config);
97 ~ProxyConfig() = default;
99 ProxyRules& Rules() { return mRules; }
101 const ProxyRules& Rules() const { return mRules; }
103 ProxyBypassRules& ByPassRules() { return mBypassRules; }
105 const ProxyBypassRules& ByPassRules() const { return mBypassRules; }
107 void SetPACUrl(const nsACString& aUrl) { mPACUrl = aUrl; }
109 const nsCString& PACUrl() const { return mPACUrl; }
111 static ProxyServer::ProxyType ToProxyType(const char* aType) {
112 if (!aType) {
113 return ProxyServer::ProxyType::DIRECT;
116 if (nsCRT::strcasecmp(aType, "http") == 0) {
117 return ProxyServer::ProxyType::HTTP;
119 if (nsCRT::strcasecmp(aType, "https") == 0) {
120 return ProxyServer::ProxyType::HTTPS;
122 if (nsCRT::strcasecmp(aType, "socks") == 0) {
123 return ProxyServer::ProxyType::SOCKS;
125 if (nsCRT::strcasecmp(aType, "socks4") == 0) {
126 return ProxyServer::ProxyType::SOCKS4;
128 if (nsCRT::strcasecmp(aType, "socks5") == 0) {
129 return ProxyServer::ProxyType::SOCKS5;
131 if (nsCRT::strcasecmp(aType, "ftp") == 0) {
132 return ProxyServer::ProxyType::FTP;
135 return ProxyServer::ProxyType::DIRECT;
138 static void SetProxyResult(const char* aType, const nsACString& aHostPort,
139 nsACString& aResult) {
140 aResult.AssignASCII(aType);
141 aResult.Append(' ');
142 aResult.Append(aHostPort);
145 static void SetProxyResultDirect(nsACString& aResult) {
146 // For whatever reason, a proxy is not to be used.
147 aResult.AssignLiteral("DIRECT");
150 static void ProxyStrToResult(const nsACString& aSpecificProxy,
151 const nsACString& aDefaultProxy,
152 const nsACString& aSocksProxy,
153 nsACString& aResult) {
154 if (!aSpecificProxy.IsEmpty()) {
155 SetProxyResult("PROXY", aSpecificProxy,
156 aResult); // Protocol-specific proxy.
157 } else if (!aDefaultProxy.IsEmpty()) {
158 SetProxyResult("PROXY", aDefaultProxy, aResult); // Default proxy.
159 } else if (!aSocksProxy.IsEmpty()) {
160 SetProxyResult("SOCKS", aSocksProxy, aResult); // SOCKS proxy.
161 } else {
162 SetProxyResultDirect(aResult); // Direct connection.
166 void GetProxyString(const nsACString& aScheme, nsACString& aResult) {
167 SetProxyResultDirect(aResult);
169 nsAutoCString specificProxy;
170 nsAutoCString defaultProxy;
171 nsAutoCString socksProxy;
172 nsAutoCString prefix;
173 ToLowerCase(aScheme, prefix);
174 ProxyServer::ProxyType type = ProxyConfig::ToProxyType(prefix.get());
175 for (auto& [key, value] : mRules.mProxyServers) {
176 // Break the loop if we found a specific proxy.
177 if (key == type) {
178 value.ToHostAndPortStr(specificProxy);
179 break;
180 } else if (key == ProxyServer::ProxyType::DEFAULT) {
181 value.ToHostAndPortStr(defaultProxy);
182 } else if (key == ProxyServer::ProxyType::SOCKS) {
183 value.ToHostAndPortStr(socksProxy);
187 ProxyStrToResult(specificProxy, defaultProxy, socksProxy, aResult);
190 private:
191 nsCString mPACUrl;
192 ProxyRules mRules;
193 ProxyBypassRules mBypassRules;
196 } // namespace net
197 } // namespace mozilla
199 #endif // mozilla_netwerk_base_proxy_config_h