summaryrefslogtreecommitdiffstats
path: root/net/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'net/proxy')
-rw-r--r--net/proxy/proxy_config.cc98
-rw-r--r--net/proxy/proxy_config.h66
-rw-r--r--net/proxy/proxy_config_service_android.cc23
-rw-r--r--net/proxy/proxy_config_service_common_unittest.cc41
-rw-r--r--net/proxy/proxy_config_service_ios.cc5
-rw-r--r--net/proxy/proxy_config_service_linux.cc27
-rw-r--r--net/proxy/proxy_config_service_mac.cc9
-rw-r--r--net/proxy/proxy_config_unittest.cc138
-rw-r--r--net/proxy/proxy_info.cc10
-rw-r--r--net/proxy/proxy_info.h7
-rw-r--r--net/proxy/proxy_list.cc11
-rw-r--r--net/proxy/proxy_list.h6
12 files changed, 313 insertions, 128 deletions
diff --git a/net/proxy/proxy_config.cc b/net/proxy/proxy_config.cc
index 022e732..91122dd 100644
--- a/net/proxy/proxy_config.cc
+++ b/net/proxy/proxy_config.cc
@@ -14,12 +14,23 @@ namespace net {
namespace {
-// If |proxy| is valid, sets it in |dict| under the key |name|.
-void AddProxyToValue(const char* name,
- const ProxyServer& proxy,
- base::DictionaryValue* dict) {
- if (proxy.is_valid())
- dict->SetString(name, proxy.ToURI());
+// If |proxies| is non-empty, sets it in |dict| under the key |name|.
+void AddProxyListToValue(const char* name,
+ const ProxyList& proxies,
+ base::DictionaryValue* dict) {
+ if (!proxies.IsEmpty())
+ dict->SetString(name, proxies.ToPacString());
+}
+
+// Split the |uri_list| on commas and add each entry to |proxy_list| in turn.
+void AddProxyURIListToProxyList(std::string uri_list,
+ ProxyList* proxy_list,
+ ProxyServer::Scheme default_scheme) {
+ base::StringTokenizer proxy_uri_list(uri_list, ",");
+ while (proxy_uri_list.GetNext()) {
+ proxy_list->AddProxyServer(
+ ProxyServer::FromURI(proxy_uri_list.token(), default_scheme));
+ }
}
} // namespace
@@ -48,13 +59,13 @@ void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) const {
switch (type) {
case ProxyRules::TYPE_SINGLE_PROXY: {
- result->UseProxyServer(single_proxy);
+ result->UseProxyList(single_proxies);
return;
}
case ProxyRules::TYPE_PROXY_PER_SCHEME: {
- const ProxyServer* entry = MapUrlSchemeToProxy(url.scheme());
+ const ProxyList* entry = MapUrlSchemeToProxyList(url.scheme());
if (entry) {
- result->UseProxyServer(*entry);
+ result->UseProxyList(*entry);
} else {
// We failed to find a matching proxy server for the current URL
// scheme. Default to direct.
@@ -73,11 +84,11 @@ void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) const {
void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
// Reset.
type = TYPE_NO_RULES;
- single_proxy = ProxyServer();
- proxy_for_http = ProxyServer();
- proxy_for_https = ProxyServer();
- proxy_for_ftp = ProxyServer();
- fallback_proxy = ProxyServer();
+ single_proxies = ProxyList();
+ proxies_for_http = ProxyList();
+ proxies_for_https = ProxyList();
+ proxies_for_ftp = ProxyList();
+ fallback_proxies = ProxyList();
base::StringTokenizer proxy_server_list(proxy_rules, ";");
while (proxy_server_list.GetNext()) {
@@ -93,8 +104,9 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
if (!proxy_server_for_scheme.GetNext()) {
if (type == TYPE_PROXY_PER_SCHEME)
continue; // Unexpected.
- single_proxy = ProxyServer::FromURI(url_scheme,
- ProxyServer::SCHEME_HTTP);
+ AddProxyURIListToProxyList(url_scheme,
+ &single_proxies,
+ ProxyServer::SCHEME_HTTP);
type = TYPE_SINGLE_PROXY;
return;
}
@@ -104,7 +116,7 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
// Add it to the per-scheme mappings (if supported scheme).
type = TYPE_PROXY_PER_SCHEME;
- ProxyServer* entry = MapUrlSchemeToProxyNoFallback(url_scheme);
+ ProxyList* entry = MapUrlSchemeToProxyListNoFallback(url_scheme);
ProxyServer::Scheme default_scheme = ProxyServer::SCHEME_HTTP;
// socks=XXX is inconsistent with the other formats, since "socks"
@@ -112,49 +124,52 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
// it to the SOCKS proxy server XXX".
if (url_scheme == "socks") {
DCHECK(!entry);
- entry = &fallback_proxy;
+ entry = &fallback_proxies;
+ // Note that here 'socks' is understood to be SOCKS4, even though
+ // 'socks' maps to SOCKS5 in ProxyServer::GetSchemeFromURIInternal.
default_scheme = ProxyServer::SCHEME_SOCKS4;
}
if (entry) {
- *entry = ProxyServer::FromURI(proxy_server_for_scheme.token(),
- default_scheme);
+ AddProxyURIListToProxyList(proxy_server_for_scheme.token(),
+ entry,
+ default_scheme);
}
}
}
}
-const ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxy(
+const ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyList(
const std::string& url_scheme) const {
- const ProxyServer* proxy_server =
- const_cast<ProxyRules*>(this)->MapUrlSchemeToProxyNoFallback(url_scheme);
- if (proxy_server && proxy_server->is_valid())
- return proxy_server;
- if (fallback_proxy.is_valid())
- return &fallback_proxy;
+ const ProxyList* proxy_server_list = const_cast<ProxyRules*>(this)->
+ MapUrlSchemeToProxyListNoFallback(url_scheme);
+ if (proxy_server_list && !proxy_server_list->IsEmpty())
+ return proxy_server_list;
+ if (!fallback_proxies.IsEmpty())
+ return &fallback_proxies;
return NULL; // No mapping for this scheme. Use direct.
}
bool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const {
return type == other.type &&
- single_proxy == other.single_proxy &&
- proxy_for_http == other.proxy_for_http &&
- proxy_for_https == other.proxy_for_https &&
- proxy_for_ftp == other.proxy_for_ftp &&
- fallback_proxy == other.fallback_proxy &&
+ single_proxies.Equals(other.single_proxies) &&
+ proxies_for_http.Equals(other.proxies_for_http) &&
+ proxies_for_https.Equals(other.proxies_for_https) &&
+ proxies_for_ftp.Equals(other.proxies_for_ftp) &&
+ fallback_proxies.Equals(other.fallback_proxies) &&
bypass_rules.Equals(other.bypass_rules) &&
reverse_bypass == other.reverse_bypass;
}
-ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
+ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyListNoFallback(
const std::string& scheme) {
DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type);
if (scheme == "http")
- return &proxy_for_http;
+ return &proxies_for_http;
if (scheme == "https")
- return &proxy_for_https;
+ return &proxies_for_https;
if (scheme == "ftp")
- return &proxy_for_ftp;
+ return &proxies_for_ftp;
return NULL; // No mapping for this scheme.
}
@@ -219,14 +234,15 @@ base::Value* ProxyConfig::ToValue() const {
if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) {
switch (proxy_rules_.type) {
case ProxyRules::TYPE_SINGLE_PROXY:
- AddProxyToValue("single_proxy", proxy_rules_.single_proxy, dict);
+ AddProxyListToValue("single_proxies",
+ proxy_rules_.single_proxies, dict);
break;
case ProxyRules::TYPE_PROXY_PER_SCHEME: {
base::DictionaryValue* dict2 = new base::DictionaryValue();
- AddProxyToValue("http", proxy_rules_.proxy_for_http, dict2);
- AddProxyToValue("https", proxy_rules_.proxy_for_https, dict2);
- AddProxyToValue("ftp", proxy_rules_.proxy_for_ftp, dict2);
- AddProxyToValue("fallback", proxy_rules_.fallback_proxy, dict2);
+ AddProxyListToValue("http", proxy_rules_.proxies_for_http, dict2);
+ AddProxyListToValue("https", proxy_rules_.proxies_for_https, dict2);
+ AddProxyListToValue("ftp", proxy_rules_.proxies_for_ftp, dict2);
+ AddProxyListToValue("fallback", proxy_rules_.fallback_proxies, dict2);
dict->Set("proxy_per_scheme", dict2);
break;
}
diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h
index 29619df..289aaee 100644
--- a/net/proxy/proxy_config.h
+++ b/net/proxy/proxy_config.h
@@ -11,6 +11,7 @@
#include "net/base/net_export.h"
#include "net/proxy/proxy_bypass_rules.h"
#include "net/proxy/proxy_config_source.h"
+#include "net/proxy/proxy_list.h"
#include "net/proxy/proxy_server.h"
namespace base {
@@ -36,6 +37,8 @@ class NET_EXPORT ProxyConfig {
public:
// ProxyRules describes the "manual" proxy settings.
// TODO(eroman): Turn this into a class.
+ // TODO(marq): Update the enum names; "TYPE_SINGLE_PROXY" really means
+ // the same set of proxies are used for all requests.
struct NET_EXPORT ProxyRules {
enum Type {
TYPE_NO_RULES,
@@ -52,31 +55,63 @@ class NET_EXPORT ProxyConfig {
return type == TYPE_NO_RULES;
}
- // Sets |result| with the proxy to use for |url| based on the current rules.
+ // Sets |result| with the proxies to use for |url| based on the current
+ // rules.
void Apply(const GURL& url, ProxyInfo* result) const;
// Parses the rules from a string, indicating which proxies to use.
//
// proxy-uri = [<proxy-scheme>"://"]<proxy-host>[":"<proxy-port>]
//
- // If the proxy to use depends on the scheme of the URL, can instead specify
- // a semicolon separated list of:
+ // proxy-uri-list = <proxy-uri>[","<proxy-uri-list>]
//
- // <url-scheme>"="<proxy-uri>
+ // url-scheme = "http" | "https" | "ftp" | "socks"
+ //
+ // scheme-proxies = [<url-scheme>"="]<proxy-uri-list>
+ //
+ // proxy-rules = scheme-proxies[";"<scheme-proxies>]
+ //
+ // Thus, the proxy-rules string should be a semicolon-separated list of
+ // ordered proxies that apply to a particular URL scheme. Unless specified,
+ // the proxy scheme for proxy-uris is assumed to be http.
+ //
+ // Some special cases:
+ // * If the scheme is omitted from the first proxy list, that list applies
+ // to all URL schemes and subsequent lists are ignored.
+ // * If a scheme is omitted from any proxy list after a list where a scheme
+ // has been provided, the list without a scheme is ignored.
+ // * If the url-scheme is set to 'socks', that sets a fallback list that
+ // to all otherwise unspecified url-schemes, however the default proxy-
+ // scheme for proxy urls in the 'socks' list is understood to be
+ // socks4:// if unspecified.
//
// For example:
// "http=foopy:80;ftp=foopy2" -- use HTTP proxy "foopy:80" for http://
// URLs, and HTTP proxy "foopy2:80" for
// ftp:// URLs.
// "foopy:80" -- use HTTP proxy "foopy:80" for all URLs.
+ // "foopy:80,bar,direct://" -- use HTTP proxy "foopy:80" for all URLs,
+ // failing over to "bar" if "foopy:80" is
+ // unavailable, and after that using no
+ // proxy.
// "socks4://foopy" -- use SOCKS v4 proxy "foopy:1080" for all
// URLs.
+ // "http=foop,socks5://bar.com -- use HTTP proxy "foopy" for http URLs,
+ // and fail over to the SOCKS5 proxy
+ // "bar.com" if "foop" is unavailable.
+ // "http=foopy,direct:// -- use HTTP proxy "foopy" for http URLs,
+ // and use no proxy if "foopy" is
+ // unavailable.
+ // "http=foopy;socks=foopy2 -- use HTTP proxy "foopy" for http URLs,
+ // and use socks4://foopy2 for all other
+ // URLs.
void ParseFromString(const std::string& proxy_rules);
- // Returns one of {&proxy_for_http, &proxy_for_https, &proxy_for_ftp,
- // &fallback_proxy}, or NULL if there is no proxy to use.
+ // Returns one of {&proxies_for_http, &proxies_for_https, &proxies_for_ftp,
+ // &fallback_proxies}, or NULL if there is no proxy to use.
// Should only call this if the type is TYPE_PROXY_PER_SCHEME.
- const ProxyServer* MapUrlSchemeToProxy(const std::string& url_scheme) const;
+ const ProxyList* MapUrlSchemeToProxyList(
+ const std::string& url_scheme) const;
// Returns true if |*this| describes the same configuration as |other|.
bool Equals(const ProxyRules& other) const;
@@ -90,21 +125,22 @@ class NET_EXPORT ProxyConfig {
Type type;
// Set if |type| is TYPE_SINGLE_PROXY.
- ProxyServer single_proxy;
+ ProxyList single_proxies;
// Set if |type| is TYPE_PROXY_PER_SCHEME.
- ProxyServer proxy_for_http;
- ProxyServer proxy_for_https;
- ProxyServer proxy_for_ftp;
+ ProxyList proxies_for_http;
+ ProxyList proxies_for_https;
+ ProxyList proxies_for_ftp;
- // Used when there isn't a more specific per-scheme proxy server.
- ProxyServer fallback_proxy;
+ // Used when a fallback has been defined and the url to be proxied doesn't
+ // match any of the standard schemes.
+ ProxyList fallback_proxies;
private:
- // Returns one of {&proxy_for_http, &proxy_for_https, &proxy_for_ftp}
+ // Returns one of {&proxies_for_http, &proxies_for_https, &proxies_for_ftp}
// or NULL if it is a scheme that we don't have a mapping
// for. Should only call this if the type is TYPE_PROXY_PER_SCHEME.
- ProxyServer* MapUrlSchemeToProxyNoFallback(const std::string& scheme);
+ ProxyList* MapUrlSchemeToProxyListNoFallback(const std::string& scheme);
};
typedef int ID;
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc
index 70c639e..a5d8ba2 100644
--- a/net/proxy/proxy_config_service_android.cc
+++ b/net/proxy/proxy_config_service_android.cc
@@ -124,21 +124,22 @@ bool GetProxyRules(const GetPropertyCallback& get_property,
// On the opposite, Java spec suggests to use HTTPS port (443) by default (the
// default value of https.proxyPort).
rules->type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- rules->proxy_for_http = LookupProxy("http", get_property,
- ProxyServer::SCHEME_HTTP);
- rules->proxy_for_https = LookupProxy("https", get_property,
- ProxyServer::SCHEME_HTTP);
- rules->proxy_for_ftp = LookupProxy("ftp", get_property,
- ProxyServer::SCHEME_HTTP);
- rules->fallback_proxy = LookupSocksProxy(get_property);
+ rules->proxies_for_http.SetSingleProxyServer(
+ LookupProxy("http", get_property, ProxyServer::SCHEME_HTTP));
+ rules->proxies_for_https.SetSingleProxyServer(
+ LookupProxy("https", get_property, ProxyServer::SCHEME_HTTP));
+ rules->proxies_for_ftp.SetSingleProxyServer(
+ LookupProxy("ftp", get_property, ProxyServer::SCHEME_HTTP));
+ rules->fallback_proxies.SetSingleProxyServer(LookupSocksProxy(get_property));
rules->bypass_rules.Clear();
AddBypassRules("ftp", get_property, &rules->bypass_rules);
AddBypassRules("http", get_property, &rules->bypass_rules);
AddBypassRules("https", get_property, &rules->bypass_rules);
- return rules->proxy_for_http.is_valid() ||
- rules->proxy_for_https.is_valid() ||
- rules->proxy_for_ftp.is_valid() ||
- rules->fallback_proxy.is_valid();
+ // We know a proxy was found if not all of the proxy lists are empty.
+ return !(rules->proxies_for_http.IsEmpty() &&
+ rules->proxies_for_https.IsEmpty() &&
+ rules->proxies_for_ftp.IsEmpty() &&
+ rules->fallback_proxies.IsEmpty());
};
void GetLatestProxyConfigInternal(const GetPropertyCallback& get_property,
diff --git a/net/proxy/proxy_config_service_common_unittest.cc b/net/proxy/proxy_config_service_common_unittest.cc
index 429abc5..3835bb1 100644
--- a/net/proxy/proxy_config_service_common_unittest.cc
+++ b/net/proxy/proxy_config_service_common_unittest.cc
@@ -15,14 +15,37 @@ namespace net {
namespace {
-// Helper to verify that |expected_proxy| matches |actual_proxy|. If it does
-// not, then |*did_fail| is set to true, and |*failure_details| is filled with
-// a description of the failure.
+// Helper to verify that |expected_proxy| matches the first proxy conatined in
+// |actual_proxies|, and that |actual_proxies| contains exactly one proxy. If
+// either condition is untrue, then |*did_fail| is set to true, and
+// |*failure_details| is filled with a description of the failure.
void MatchesProxyServerHelper(const char* failure_message,
const char* expected_proxy,
- const ProxyServer& actual_proxy,
+ const ProxyList& actual_proxies,
::testing::AssertionResult* failure_details,
bool* did_fail) {
+ // If |expected_proxy| is empty, then we expect |actual_proxies| to be so as
+ // well.
+ if (strlen(expected_proxy) == 0) {
+ if (!actual_proxies.IsEmpty()) {
+ *did_fail = true;
+ *failure_details
+ << failure_message << ". Was expecting no proxies but got "
+ << actual_proxies.size() << ".";
+ }
+ return;
+ }
+
+ // Otherwise we check that |actual_proxies| holds a single matching proxy.
+ if (actual_proxies.size() != 1) {
+ *did_fail = true;
+ *failure_details
+ << failure_message << ". Was expecting exactly one proxy but got "
+ << actual_proxies.size() << ".";
+ return;
+ }
+
+ ProxyServer actual_proxy = actual_proxies.Get();
std::string actual_proxy_string;
if (actual_proxy.is_valid())
actual_proxy_string = actual_proxy.ToURI();
@@ -81,13 +104,15 @@ ProxyRulesExpectation::ProxyRulesExpectation(
}
MatchesProxyServerHelper("Bad single_proxy", single_proxy,
- rules.single_proxy, &failure_details, &failed);
+ rules.single_proxies, &failure_details, &failed);
MatchesProxyServerHelper("Bad proxy_for_http", proxy_for_http,
- rules.proxy_for_http, &failure_details, &failed);
+ rules.proxies_for_http, &failure_details,
+ &failed);
MatchesProxyServerHelper("Bad proxy_for_https", proxy_for_https,
- rules.proxy_for_https, &failure_details, &failed);
+ rules.proxies_for_https, &failure_details,
+ &failed);
MatchesProxyServerHelper("Bad fallback_proxy", fallback_proxy,
- rules.fallback_proxy, &failure_details, &failed);
+ rules.fallback_proxies, &failure_details, &failed);
std::string actual_flattened_bypass = FlattenProxyBypass(rules.bypass_rules);
if (std::string(flattened_bypass_rules) != actual_flattened_bypass) {
diff --git a/net/proxy/proxy_config_service_ios.cc b/net/proxy/proxy_config_service_ios.cc
index fdeb1bb..6a9d2d3 100644
--- a/net/proxy/proxy_config_service_ios.cc
+++ b/net/proxy/proxy_config_service_ios.cc
@@ -78,10 +78,11 @@ void GetCurrentProxyConfig(ProxyConfig* config) {
if (proxy_server.is_valid()) {
config->proxy_rules().type =
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- config->proxy_rules().proxy_for_http = proxy_server;
+ config->proxy_rules().proxies_for_http.SetSingleProxyServer(proxy_server);
// Desktop Safari applies the HTTP proxy to http:// URLs only, but
// Mobile Safari applies the HTTP proxy to https:// URLs as well.
- config->proxy_rules().proxy_for_https = proxy_server;
+ config->proxy_rules().proxies_for_https.SetSingleProxyServer(
+ proxy_server);
}
}
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
index 523a55e..b1dda52 100644
--- a/net/proxy/proxy_config_service_linux.cc
+++ b/net/proxy/proxy_config_service_linux.cc
@@ -137,11 +137,11 @@ bool ProxyConfigServiceLinux::Delegate::GetConfigFromEnv(ProxyConfig* config) {
ProxyServer proxy_server;
if (GetProxyFromEnvVar("all_proxy", &proxy_server)) {
config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
- config->proxy_rules().single_proxy = proxy_server;
+ config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_server);
} else {
bool have_http = GetProxyFromEnvVar("http_proxy", &proxy_server);
if (have_http)
- config->proxy_rules().proxy_for_http = proxy_server;
+ config->proxy_rules().proxies_for_http.SetSingleProxyServer(proxy_server);
// It would be tempting to let http_proxy apply for all protocols
// if https_proxy and ftp_proxy are not defined. Googling turns up
// several documents that mention only http_proxy. But then the
@@ -149,10 +149,11 @@ bool ProxyConfigServiceLinux::Delegate::GetConfigFromEnv(ProxyConfig* config) {
// like other apps do this. So we will refrain.
bool have_https = GetProxyFromEnvVar("https_proxy", &proxy_server);
if (have_https)
- config->proxy_rules().proxy_for_https = proxy_server;
+ config->proxy_rules().proxies_for_https.
+ SetSingleProxyServer(proxy_server);
bool have_ftp = GetProxyFromEnvVar("ftp_proxy", &proxy_server);
if (have_ftp)
- config->proxy_rules().proxy_for_ftp = proxy_server;
+ config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(proxy_server);
if (have_http || have_https || have_ftp) {
// mustn't change type unless some rules are actually set.
config->proxy_rules().type =
@@ -170,7 +171,7 @@ bool ProxyConfigServiceLinux::Delegate::GetConfigFromEnv(ProxyConfig* config) {
scheme = ProxyServer::SCHEME_SOCKS4;
if (GetProxyFromEnvVarForScheme("SOCKS_SERVER", scheme, &proxy_server)) {
config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
- config->proxy_rules().single_proxy = proxy_server;
+ config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_server);
}
}
// Look for the proxy bypass list.
@@ -1445,21 +1446,23 @@ bool ProxyConfigServiceLinux::Delegate::GetConfigFromSettings(
if (proxy_for_http.is_valid()) {
// Use the http proxy for all schemes.
config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
- config->proxy_rules().single_proxy = proxy_for_http;
+ config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_for_http);
}
} else if (num_proxies_specified > 0) {
if (socks_proxy.is_valid() && num_proxies_specified == 1) {
// If the only proxy specified was for SOCKS, use it for all schemes.
config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
- config->proxy_rules().single_proxy = socks_proxy;
+ config->proxy_rules().single_proxies.SetSingleProxyServer(socks_proxy);
} else {
- // Otherwise use the indicate proxies per-scheme.
+ // Otherwise use the indicated proxies per-scheme.
config->proxy_rules().type =
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- config->proxy_rules().proxy_for_http = proxy_for_http;
- config->proxy_rules().proxy_for_https = proxy_for_https;
- config->proxy_rules().proxy_for_ftp = proxy_for_ftp;
- config->proxy_rules().fallback_proxy = socks_proxy;
+ config->proxy_rules().proxies_for_http.
+ SetSingleProxyServer(proxy_for_http);
+ config->proxy_rules().proxies_for_https.
+ SetSingleProxyServer(proxy_for_https);
+ config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(proxy_for_ftp);
+ config->proxy_rules().fallback_proxies.SetSingleProxyServer(socks_proxy);
}
}
diff --git a/net/proxy/proxy_config_service_mac.cc b/net/proxy/proxy_config_service_mac.cc
index b4099d8..6994ffd 100644
--- a/net/proxy/proxy_config_service_mac.cc
+++ b/net/proxy/proxy_config_service_mac.cc
@@ -80,7 +80,7 @@ void GetCurrentProxyConfig(ProxyConfig* config) {
if (proxy_server.is_valid()) {
config->proxy_rules().type =
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- config->proxy_rules().proxy_for_ftp = proxy_server;
+ config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(proxy_server);
}
}
if (GetBoolFromDictionary(config_dict.get(),
@@ -94,7 +94,7 @@ void GetCurrentProxyConfig(ProxyConfig* config) {
if (proxy_server.is_valid()) {
config->proxy_rules().type =
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- config->proxy_rules().proxy_for_http = proxy_server;
+ config->proxy_rules().proxies_for_http.SetSingleProxyServer(proxy_server);
}
}
if (GetBoolFromDictionary(config_dict.get(),
@@ -108,7 +108,8 @@ void GetCurrentProxyConfig(ProxyConfig* config) {
if (proxy_server.is_valid()) {
config->proxy_rules().type =
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- config->proxy_rules().proxy_for_https = proxy_server;
+ config->proxy_rules().proxies_for_https.
+ SetSingleProxyServer(proxy_server);
}
}
if (GetBoolFromDictionary(config_dict.get(),
@@ -122,7 +123,7 @@ void GetCurrentProxyConfig(ProxyConfig* config) {
if (proxy_server.is_valid()) {
config->proxy_rules().type =
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
- config->proxy_rules().fallback_proxy = proxy_server;
+ config->proxy_rules().fallback_proxies.SetSingleProxyServer(proxy_server);
}
}
diff --git a/net/proxy/proxy_config_unittest.cc b/net/proxy/proxy_config_unittest.cc
index 47ea689..4b041b3 100644
--- a/net/proxy/proxy_config_unittest.cc
+++ b/net/proxy/proxy_config_unittest.cc
@@ -11,11 +11,11 @@ namespace net {
namespace {
void ExpectProxyServerEquals(const char* expectation,
- const ProxyServer& proxy_server) {
+ const ProxyList& proxy_servers) {
if (expectation == NULL) {
- EXPECT_FALSE(proxy_server.is_valid());
+ EXPECT_TRUE(proxy_servers.IsEmpty());
} else {
- EXPECT_EQ(expectation, proxy_server.ToURI());
+ EXPECT_EQ(expectation, proxy_servers.ToPacString());
}
}
@@ -51,21 +51,21 @@ TEST(ProxyConfigTest, Equals) {
// Test |ProxyConfig::proxy_rules|.
config2.proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
- config2.proxy_rules().single_proxy =
- ProxyServer::FromURI("myproxy:80", ProxyServer::SCHEME_HTTP);
+ config2.proxy_rules().single_proxies.SetSingleProxyServer(
+ ProxyServer::FromURI("myproxy:80", ProxyServer::SCHEME_HTTP));
EXPECT_FALSE(config1.Equals(config2));
EXPECT_FALSE(config2.Equals(config1));
config1.proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
- config1.proxy_rules().single_proxy =
- ProxyServer::FromURI("myproxy:100", ProxyServer::SCHEME_HTTP);
+ config1.proxy_rules().single_proxies.SetSingleProxyServer(
+ ProxyServer::FromURI("myproxy:100", ProxyServer::SCHEME_HTTP));
EXPECT_FALSE(config1.Equals(config2));
EXPECT_FALSE(config2.Equals(config1));
- config1.proxy_rules().single_proxy =
- ProxyServer::FromURI("myproxy", ProxyServer::SCHEME_HTTP);
+ config1.proxy_rules().single_proxies.SetSingleProxyServer(
+ ProxyServer::FromURI("myproxy", ProxyServer::SCHEME_HTTP));
EXPECT_TRUE(config1.Equals(config2));
EXPECT_TRUE(config2.Equals(config1));
@@ -100,6 +100,7 @@ TEST(ProxyConfigTest, ParseProxyRules) {
const char* proxy_rules;
ProxyConfig::ProxyRules::Type type;
+ // These will be PAC-stle strings, eg 'PROXY foo.com'
const char* single_proxy;
const char* proxy_for_http;
const char* proxy_for_https;
@@ -111,7 +112,19 @@ TEST(ProxyConfigTest, ParseProxyRules) {
"myproxy:80",
ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
- "myproxy:80",
+ "PROXY myproxy:80",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ // Multiple HTTP proxies for all schemes.
+ {
+ "myproxy:80,https://myotherproxy",
+
+ ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
+ "PROXY myproxy:80;HTTPS myotherproxy:443",
NULL,
NULL,
NULL,
@@ -124,7 +137,7 @@ TEST(ProxyConfigTest, ParseProxyRules) {
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
NULL,
- "myproxy:80",
+ "PROXY myproxy:80",
NULL,
NULL,
NULL,
@@ -137,8 +150,8 @@ TEST(ProxyConfigTest, ParseProxyRules) {
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
NULL,
NULL,
- "socks4://foopy:1080",
- "ftp-proxy:80",
+ "SOCKS foopy:1080",
+ "PROXY ftp-proxy:80",
NULL,
},
@@ -149,7 +162,7 @@ TEST(ProxyConfigTest, ParseProxyRules) {
"foopy ; ftp=ftp-proxy",
ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
- "foopy:80",
+ "PROXY foopy:80",
NULL,
NULL,
NULL,
@@ -166,19 +179,55 @@ TEST(ProxyConfigTest, ParseProxyRules) {
NULL,
NULL,
NULL,
- "ftp-proxy:80",
+ "PROXY ftp-proxy:80",
NULL,
},
- // Include duplicate entries -- last one wins.
+ // Include a list of entries for a single scheme.
{
- "ftp=ftp1 ; ftp=ftp2 ; ftp=ftp3",
+ "ftp=ftp1,ftp2,ftp3",
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
NULL,
NULL,
NULL,
- "ftp3:80",
+ "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
+ NULL,
+ },
+
+ // Include multiple entries for the same scheme -- they accumulate.
+ {
+ "http=http1,http2; http=http3",
+
+ ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ NULL,
+ "PROXY http1:80;PROXY http2:80;PROXY http3:80",
+ NULL,
+ NULL,
+ NULL,
+ },
+
+ // Include lists of entries for multiple schemes.
+ {
+ "ftp=ftp1,ftp2,ftp3 ; http=http1,http2; ",
+
+ ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ NULL,
+ "PROXY http1:80;PROXY http2:80",
+ NULL,
+ "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
+ NULL,
+ },
+
+ // Include non-default proxy schemes.
+ {
+ "http=https://secure_proxy; ftp=socks4://socks_proxy; https=socks://foo",
+
+ ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ NULL,
+ "HTTPS secure_proxy:443",
+ "SOCKS5 foo:1080",
+ "SOCKS socks_proxy:1080",
NULL,
},
@@ -191,7 +240,7 @@ TEST(ProxyConfigTest, ParseProxyRules) {
NULL,
NULL,
NULL,
- "socks4://foopy:1080",
+ "SOCKS foopy:1080",
},
// SOCKS proxy present along with other proxies too
@@ -200,10 +249,10 @@ TEST(ProxyConfigTest, ParseProxyRules) {
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
NULL,
- "httpproxy:80",
- "httpsproxy:80",
- "ftpproxy:80",
- "socks4://foopy:1080",
+ "PROXY httpproxy:80",
+ "PROXY httpsproxy:80",
+ "PROXY ftpproxy:80",
+ "SOCKS foopy:1080",
},
// SOCKS proxy (with modifier) present along with some proxies
@@ -213,10 +262,10 @@ TEST(ProxyConfigTest, ParseProxyRules) {
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
NULL,
- "httpproxy:80",
- "httpsproxy:80",
+ "PROXY httpproxy:80",
+ "PROXY httpsproxy:80",
NULL,
- "socks5://foopy:1080",
+ "SOCKS5 foopy:1080",
},
// Include unsupported schemes -- they are discarded.
@@ -226,10 +275,35 @@ TEST(ProxyConfigTest, ParseProxyRules) {
ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
NULL,
NULL,
- "myhttpsproxy:80",
+ "PROXY myhttpsproxy:80",
+ NULL,
+ NULL,
+ },
+
+ // direct:// as first option for a scheme.
+ {
+ "http=direct://,myhttpproxy; https=direct://",
+
+ ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ NULL,
+ "DIRECT;PROXY myhttpproxy:80",
+ "DIRECT",
+ NULL,
+ NULL,
+ },
+
+ // direct:// as a second option for a scheme.
+ {
+ "http=myhttpproxy,direct://",
+
+ ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ NULL,
+ "PROXY myhttpproxy:80;DIRECT",
+ NULL,
NULL,
NULL,
},
+
};
ProxyConfig config;
@@ -239,15 +313,15 @@ TEST(ProxyConfigTest, ParseProxyRules) {
EXPECT_EQ(tests[i].type, config.proxy_rules().type);
ExpectProxyServerEquals(tests[i].single_proxy,
- config.proxy_rules().single_proxy);
+ config.proxy_rules().single_proxies);
ExpectProxyServerEquals(tests[i].proxy_for_http,
- config.proxy_rules().proxy_for_http);
+ config.proxy_rules().proxies_for_http);
ExpectProxyServerEquals(tests[i].proxy_for_https,
- config.proxy_rules().proxy_for_https);
+ config.proxy_rules().proxies_for_https);
ExpectProxyServerEquals(tests[i].proxy_for_ftp,
- config.proxy_rules().proxy_for_ftp);
+ config.proxy_rules().proxies_for_ftp);
ExpectProxyServerEquals(tests[i].fallback_proxy,
- config.proxy_rules().fallback_proxy);
+ config.proxy_rules().fallback_proxies);
}
}
diff --git a/net/proxy/proxy_info.cc b/net/proxy/proxy_info.cc
index dd68820..b6fcc867 100644
--- a/net/proxy/proxy_info.cc
+++ b/net/proxy/proxy_info.cc
@@ -49,6 +49,16 @@ void ProxyInfo::UseProxyServer(const ProxyServer& proxy_server) {
proxy_list_.SetSingleProxyServer(proxy_server);
}
+void ProxyInfo::UsePacString(const std::string& pac_string) {
+ Reset();
+ proxy_list_.SetFromPacString(pac_string);
+}
+
+void ProxyInfo::UseProxyList(const ProxyList& proxy_list) {
+ Reset();
+ proxy_list_ = proxy_list;
+}
+
std::string ProxyInfo::ToPacString() const {
return proxy_list_.ToPacString();
}
diff --git a/net/proxy/proxy_info.h b/net/proxy/proxy_info.h
index cea21e2..877e404 100644
--- a/net/proxy/proxy_info.h
+++ b/net/proxy/proxy_info.h
@@ -44,9 +44,10 @@ class NET_EXPORT ProxyInfo {
void UseProxyServer(const ProxyServer& proxy_server);
// Parses from the given PAC result.
- void UsePacString(const std::string& pac_string) {
- proxy_list_.SetFromPacString(pac_string);
- }
+ void UsePacString(const std::string& pac_string);
+
+ // Use the proxies from the given list.
+ void UseProxyList(const ProxyList& proxy_list);
// Returns true if this proxy info specifies a direct connection.
bool is_direct() const {
diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc
index 1b2ecc7..4a49501 100644
--- a/net/proxy/proxy_list.cc
+++ b/net/proxy/proxy_list.cc
@@ -35,6 +35,10 @@ void ProxyList::Set(const std::string& proxy_uri_list) {
void ProxyList::SetSingleProxyServer(const ProxyServer& proxy_server) {
proxies_.clear();
+ AddProxyServer(proxy_server);
+}
+
+void ProxyList::AddProxyServer(const ProxyServer& proxy_server) {
if (proxy_server.is_valid())
proxies_.push_back(proxy_server);
}
@@ -110,6 +114,13 @@ size_t ProxyList::size() const {
return proxies_.size();
}
+// Returns true if |*this| lists the same proxies as |other|.
+bool ProxyList::Equals(const ProxyList& other) const {
+ if (size() != other.size())
+ return false;
+ return proxies_ == other.proxies_;
+}
+
const ProxyServer& ProxyList::Get() const {
DCHECK(!proxies_.empty());
return proxies_[0];
diff --git a/net/proxy/proxy_list.h b/net/proxy/proxy_list.h
index 209dd67..70208a1 100644
--- a/net/proxy/proxy_list.h
+++ b/net/proxy/proxy_list.h
@@ -31,6 +31,9 @@ class NET_EXPORT_PRIVATE ProxyList {
// Set the proxy list to a single entry, |proxy_server|.
void SetSingleProxyServer(const ProxyServer& proxy_server);
+ // Append a single proxy server to the end of the proxy list.
+ void AddProxyServer(const ProxyServer& proxy_server);
+
// De-prioritizes the proxies that we have cached as not working, by moving
// them to the end of the fallback list.
void DeprioritizeBadProxies(const ProxyRetryInfoMap& proxy_retry_info);
@@ -52,6 +55,9 @@ class NET_EXPORT_PRIVATE ProxyList {
// Returns the number of proxy servers in this list.
size_t size() const;
+ // Returns true if |*this| lists the same proxies as |other|.
+ bool Equals(const ProxyList& other) const;
+
// Returns the first proxy server in the list. It is only valid to call
// this if !IsEmpty().
const ProxyServer& Get() const;