diff options
-rw-r--r-- | net/net.gyp | 1 | ||||
-rw-r--r-- | net/proxy/proxy_config.cc | 54 | ||||
-rw-r--r-- | net/proxy/proxy_config.h | 72 | ||||
-rw-r--r-- | net/proxy/proxy_config_service_fixed.h | 3 | ||||
-rw-r--r-- | net/proxy/proxy_config_service_win.cc | 7 | ||||
-rw-r--r-- | net/proxy/proxy_config_service_win_unittest.cc | 115 | ||||
-rw-r--r-- | net/proxy/proxy_config_unittest.cc | 199 | ||||
-rw-r--r-- | net/proxy/proxy_info.cc | 4 | ||||
-rw-r--r-- | net/proxy/proxy_info.h | 3 | ||||
-rw-r--r-- | net/proxy/proxy_list.cc | 6 | ||||
-rw-r--r-- | net/proxy/proxy_list.h | 3 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_mac.cc | 16 | ||||
-rw-r--r-- | net/proxy/proxy_server.h | 6 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 70 | ||||
-rw-r--r-- | net/proxy/proxy_service.h | 5 | ||||
-rw-r--r-- | net/proxy/proxy_service_unittest.cc | 6 |
16 files changed, 466 insertions, 104 deletions
diff --git a/net/net.gyp b/net/net.gyp index e7ed8bd..ca972fc 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -427,6 +427,7 @@ 'http/http_util_unittest.cc', 'http/http_vary_data_unittest.cc', 'proxy/proxy_config_service_win_unittest.cc', + 'proxy/proxy_config_unittest.cc', 'proxy/proxy_list_unittest.cc', 'proxy/proxy_resolver_v8_unittest.cc', 'proxy/proxy_script_fetcher_unittest.cc', diff --git a/net/proxy/proxy_config.cc b/net/proxy/proxy_config.cc index fb30124..07c1d50 100644 --- a/net/proxy/proxy_config.cc +++ b/net/proxy/proxy_config.cc @@ -4,6 +4,9 @@ #include "net/proxy/proxy_config.h" +#include "base/string_tokenizer.h" +#include "base/string_util.h" + namespace net { // static @@ -25,4 +28,55 @@ bool ProxyConfig::Equals(const ProxyConfig& other) const { proxy_bypass_local_names == other.proxy_bypass_local_names; } +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(); + + StringTokenizer proxy_server_list(proxy_rules, ";"); + while (proxy_server_list.GetNext()) { + StringTokenizer proxy_server_for_scheme( + proxy_server_list.token_begin(), proxy_server_list.token_end(), "="); + + while (proxy_server_for_scheme.GetNext()) { + std::string url_scheme = proxy_server_for_scheme.token(); + + // If we fail to get the proxy server here, it means that + // this is a regular proxy server configuration, i.e. proxies + // are not configured per protocol. + if (!proxy_server_for_scheme.GetNext()) { + if (type == TYPE_PROXY_PER_SCHEME) + continue; // Unexpected. + single_proxy = ProxyServer::FromURI(url_scheme); + type = TYPE_SINGLE_PROXY; + return; + } + + // Trim whitespace off the url scheme. + TrimWhitespaceASCII(url_scheme, TRIM_ALL, &url_scheme); + + // Add it to the per-scheme mappings (if supported scheme). + type = TYPE_PROXY_PER_SCHEME; + if (const ProxyServer* entry = MapSchemeToProxy(url_scheme)) + *const_cast<ProxyServer*>(entry) = + ProxyServer::FromURI(proxy_server_for_scheme.token()); + } + } +} + +const ProxyServer* ProxyConfig::ProxyRules::MapSchemeToProxy( + const std::string& scheme) const { + DCHECK(type == TYPE_PROXY_PER_SCHEME); + if (scheme == "http") + return &proxy_for_http; + if (scheme == "https") + return &proxy_for_https; + if (scheme == "ftp") + return &proxy_for_ftp; + return NULL; // No mapping for this scheme. +} + } // namespace net diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h index 5377ed7..5fca8fe 100644 --- a/net/proxy/proxy_config.h +++ b/net/proxy/proxy_config.h @@ -9,6 +9,7 @@ #include <vector> #include "googleurl/src/gurl.h" +#include "net/proxy/proxy_server.h" namespace net { @@ -32,22 +33,61 @@ class ProxyConfig { // If non-empty, indicates the URL of the proxy auto-config file to use. GURL pac_url; - // If non-empty, indicates the proxy server to use, given by: - // - // 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: - // - // <url-scheme>"="<proxy-uri> - // - // 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. - // "socks4://foopy" -- use SOCKS v4 proxy "foopy:1080" for all - // URLs. - std::string proxy_rules; + struct ProxyRules { + enum Type { + TYPE_NO_RULES, + TYPE_SINGLE_PROXY, + TYPE_PROXY_PER_SCHEME, + }; + + ProxyRules() : type(TYPE_NO_RULES) {} + + bool empty() const { + return type == TYPE_NO_RULES; + } + + // 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: + // + // <url-scheme>"="<proxy-uri> + // + // 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. + // "socks4://foopy" -- use SOCKS v4 proxy "foopy:1080" for all + // URLs. + void ParseFromString(const std::string& proxy_rules); + + // Returns one of {&proxy_for_http, &proxy_for_https, &proxy_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. + const ProxyServer* MapSchemeToProxy(const std::string& scheme) const; + + bool operator==(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; + } + + Type type; + + // Set if |type| is TYPE_SINGLE_PROXY. + ProxyServer single_proxy; + + // Set if |type| is TYPE_PROXY_PER_SCHEME. + ProxyServer proxy_for_http; + ProxyServer proxy_for_https; + ProxyServer proxy_for_ftp; + }; + + ProxyRules proxy_rules; // Indicates a list of hosts that should bypass any proxy configuration. For // these hosts, a direct connection should always be used. diff --git a/net/proxy/proxy_config_service_fixed.h b/net/proxy/proxy_config_service_fixed.h index e36ccc0..dfa9351 100644 --- a/net/proxy/proxy_config_service_fixed.h +++ b/net/proxy/proxy_config_service_fixed.h @@ -16,7 +16,8 @@ class ProxyConfigServiceFixed : public ProxyConfigService { // ProxyConfigService methods: virtual int GetProxyConfig(ProxyConfig* config) { - config->proxy_rules = pi_.proxy_server().ToURI(); + config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config->proxy_rules.single_proxy = pi_.proxy_server(); return OK; } diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc index ab02c66..30c4adb 100644 --- a/net/proxy/proxy_config_service_win.cc +++ b/net/proxy/proxy_config_service_win.cc @@ -44,8 +44,11 @@ void ProxyConfigServiceWin::SetFromIEConfig( const WINHTTP_CURRENT_USER_IE_PROXY_CONFIG& ie_config) { if (ie_config.fAutoDetect) config->auto_detect = true; - if (ie_config.lpszProxy) - config->proxy_rules = WideToASCII(ie_config.lpszProxy); + if (ie_config.lpszProxy) { + // lpszProxy may be a single proxy, or a proxy per scheme. The format + // is compatible with ProxyConfig::ProxyRules's string format. + config->proxy_rules.ParseFromString(WideToASCII(ie_config.lpszProxy)); + } if (ie_config.lpszProxyBypass) { std::string proxy_bypass = WideToASCII(ie_config.lpszProxyBypass); diff --git a/net/proxy/proxy_config_service_win_unittest.cc b/net/proxy/proxy_config_service_win_unittest.cc index 8d88eb3..f77ac16 100644 --- a/net/proxy/proxy_config_service_win_unittest.cc +++ b/net/proxy/proxy_config_service_win_unittest.cc @@ -10,6 +10,34 @@ namespace net { +static ProxyConfig::ProxyRules MakeProxyRules( + ProxyConfig::ProxyRules::Type type, + const char* single_proxy, + const char* proxy_for_http, + const char* proxy_for_https, + const char* proxy_for_ftp) { + ProxyConfig::ProxyRules rules; + rules.type = type; + rules.single_proxy = ProxyServer::FromURI(single_proxy); + rules.proxy_for_http = ProxyServer::FromURI(proxy_for_http); + rules.proxy_for_https = ProxyServer::FromURI(proxy_for_https); + rules.proxy_for_ftp = ProxyServer::FromURI(proxy_for_ftp); + return rules; +} + +static ProxyConfig::ProxyRules MakeSingleProxyRules(const char* single_proxy) { + return MakeProxyRules(ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + single_proxy, "", "", ""); +} + +static ProxyConfig::ProxyRules MakeProxyPerSchemeRules( + const char* proxy_http, + const char* proxy_https, + const char* proxy_ftp) { + return MakeProxyRules(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + "", proxy_http, proxy_https, proxy_ftp); +} + TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { const struct { // Input. @@ -18,7 +46,7 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { // Expected outputs (fields of the ProxyConfig). bool auto_detect; GURL pac_url; - const char* proxy_rules; + ProxyConfig::ProxyRules proxy_rules; const char* proxy_bypass_list; // newline separated bool bypass_local_names; } tests[] = { @@ -32,11 +60,11 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { }, // Expected result. - true, // auto_detect - GURL(), // pac_url - "", // proxy_rules - "", // proxy_bypass_list - false, // bypass_local_names + true, // auto_detect + GURL(), // pac_url + ProxyConfig::ProxyRules(), // proxy_rules + "", // proxy_bypass_list + false, // bypass_local_names }, // Valid PAC url @@ -51,7 +79,7 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { // Expected result. false, // auto_detect GURL("http://wpad/wpad.dat"), // pac_url - "", // proxy_rules + ProxyConfig::ProxyRules(), // proxy_rules "", // proxy_bypass_list false, // bypass_local_names }, @@ -66,11 +94,11 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { }, // Expected result. - false, // auto_detect - GURL(), // pac_url - "", // proxy_rules - "", // proxy_bypass_list - false, // bypass_local_names + false, // auto_detect + GURL(), // pac_url + ProxyConfig::ProxyRules(), // proxy_rules + "", // proxy_bypass_list + false, // bypass_local_names }, // Single-host in proxy list. @@ -83,11 +111,28 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { }, // Expected result. - false, // auto_detect - GURL(), // pac_url - "www.google.com", // proxy_rules - "", // proxy_bypass_list - false, // bypass_local_names + false, // auto_detect + GURL(), // pac_url + MakeSingleProxyRules("www.google.com"), // proxy_rules + "", // proxy_bypass_list + false, // bypass_local_names + }, + + // Per-scheme proxy rules. + { + { // Input. + FALSE, // fAutoDetect + NULL, // lpszAutoConfigUrl + L"http=www.google.com:80;https=www.foo.com:110", // lpszProxy + NULL, // lpszProxy_bypass + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + MakeProxyPerSchemeRules("www.google.com:80", "www.foo.com:110", ""), + "", // proxy_bypass_list + false, // bypass_local_names }, // Bypass local names. @@ -96,14 +141,14 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { TRUE, // fAutoDetect NULL, // lpszAutoConfigUrl NULL, // lpszProxy - L"<local>", // lpszProxy_bypass + L"<local>", // lpszProxy_bypass }, - true, // auto_detect - GURL(), // pac_url - "", // proxy_rules - "", // proxy_bypass_list - true, // bypass_local_names + true, // auto_detect + GURL(), // pac_url + ProxyConfig::ProxyRules(), // proxy_rules + "", // proxy_bypass_list + true, // bypass_local_names }, // Bypass "google.com" and local names, using semicolon as delimeter @@ -113,15 +158,15 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { TRUE, // fAutoDetect NULL, // lpszAutoConfigUrl NULL, // lpszProxy - L"<local> ; google.com", // lpszProxy_bypass + L"<local> ; google.com", // lpszProxy_bypass }, // Expected result. - true, // auto_detect - GURL(), // pac_url - "", // proxy_rules - "google.com\n", // proxy_bypass_list - true, // bypass_local_names + true, // auto_detect + GURL(), // pac_url + ProxyConfig::ProxyRules(), // proxy_rules + "google.com\n", // proxy_bypass_list + true, // bypass_local_names }, // Bypass "foo.com" and "google.com", using lines as delimeter. @@ -134,11 +179,11 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { }, // Expected result. - true, // auto_detect - GURL(), // pac_url - "", // proxy_rules - "foo.com\ngoogle.com\n", // proxy_bypass_list - false, // bypass_local_names + true, // auto_detect + GURL(), // pac_url + ProxyConfig::ProxyRules(), // proxy_rules + "foo.com\ngoogle.com\n", // proxy_bypass_list + false, // bypass_local_names }, }; @@ -159,7 +204,7 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) { EXPECT_EQ(tests[i].proxy_bypass_list, flattened_proxy_bypass); EXPECT_EQ(tests[i].bypass_local_names, config.proxy_bypass_local_names); - EXPECT_EQ(tests[i].proxy_rules, config.proxy_rules); + EXPECT_TRUE(tests[i].proxy_rules == config.proxy_rules); } } diff --git a/net/proxy/proxy_config_unittest.cc b/net/proxy/proxy_config_unittest.cc new file mode 100644 index 0000000..9e50e3b --- /dev/null +++ b/net/proxy/proxy_config_unittest.cc @@ -0,0 +1,199 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/proxy/proxy_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +static void ExpectProxyServerEquals(const char* expectation, + const net::ProxyServer& proxy_server) { + if (expectation == NULL) { + EXPECT_FALSE(proxy_server.is_valid()); + } else { + EXPECT_EQ(expectation, proxy_server.ToURI()); + } +} +} + +TEST(ProxyConfigTest, Equals) { + // Test |ProxyConfig::auto_detect|. + + net::ProxyConfig config1; + config1.auto_detect = true; + + net::ProxyConfig config2; + config2.auto_detect = false; + + EXPECT_FALSE(config1.Equals(config2)); + EXPECT_FALSE(config2.Equals(config1)); + + config2.auto_detect = true; + + EXPECT_TRUE(config1.Equals(config2)); + EXPECT_TRUE(config2.Equals(config1)); + + // Test |ProxyConfig::pac_url|. + + config2.pac_url = GURL("http://wpad/wpad.dat"); + + EXPECT_FALSE(config1.Equals(config2)); + EXPECT_FALSE(config2.Equals(config1)); + + config1.pac_url = GURL("http://wpad/wpad.dat"); + + EXPECT_TRUE(config1.Equals(config2)); + EXPECT_TRUE(config2.Equals(config1)); + + // Test |ProxyConfig::proxy_rules|. + + config2.proxy_rules.type = net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config2.proxy_rules.single_proxy = net::ProxyServer::FromURI("myproxy:80"); + + EXPECT_FALSE(config1.Equals(config2)); + EXPECT_FALSE(config2.Equals(config1)); + + config1.proxy_rules.type = net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config1.proxy_rules.single_proxy = net::ProxyServer::FromURI("myproxy:100"); + + EXPECT_FALSE(config1.Equals(config2)); + EXPECT_FALSE(config2.Equals(config1)); + + config1.proxy_rules.single_proxy = net::ProxyServer::FromURI("myproxy"); + + EXPECT_TRUE(config1.Equals(config2)); + EXPECT_TRUE(config2.Equals(config1)); + + // Test |ProxyConfig::proxy_bypass|. + + config2.proxy_bypass.push_back("*.google.com"); + + EXPECT_FALSE(config1.Equals(config2)); + EXPECT_FALSE(config2.Equals(config1)); + + config1.proxy_bypass.push_back("*.google.com"); + + EXPECT_TRUE(config1.Equals(config2)); + EXPECT_TRUE(config2.Equals(config1)); + + // Test |ProxyConfig::proxy_bypass_local_names|. + + config1.proxy_bypass_local_names = true; + + EXPECT_FALSE(config1.Equals(config2)); + EXPECT_FALSE(config2.Equals(config1)); + + config2.proxy_bypass_local_names = true; + + EXPECT_TRUE(config1.Equals(config2)); + EXPECT_TRUE(config2.Equals(config1)); +} + +TEST(ProxyConfigTest, ParseProxyRules) { + const struct { + const char* proxy_rules; + + net::ProxyConfig::ProxyRules::Type type; + const char* single_proxy; + const char* proxy_for_http; + const char* proxy_for_https; + const char* proxy_for_ftp; + } tests[] = { + // One HTTP proxy for all schemes. + { + "myproxy:80", + + net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + "myproxy:80", + NULL, + NULL, + NULL, + }, + + // Only specify a proxy server for "http://" urls. + { + "http=myproxy:80", + + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + NULL, + "myproxy:80", + NULL, + NULL, + }, + + // Specify an HTTP proxy for "ftp://" and a SOCKS proxy for "https://" urls. + { + "ftp=ftp-proxy ; https=socks4://foopy", + + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + NULL, + NULL, + "socks4://foopy:1080", + "ftp-proxy:80", + }, + + // Give a scheme-specific proxy as well as a non-scheme specific. + // The first entry "foopy" takes precedance marking this list as + // TYPE_SINGLE_PROXY. + { + "foopy ; ftp=ftp-proxy", + + net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + "foopy:80", + NULL, + NULL, + NULL, + }, + + // Give a scheme-specific proxy as well as a non-scheme specific. + // The first entry "ftp=ftp-proxy" takes precedance marking this list as + // TYPE_PROXY_PER_SCHEME. + { + "ftp=ftp-proxy ; foopy", + + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + NULL, + NULL, + NULL, + "ftp-proxy:80", + }, + + // Include duplicate entries -- last one wins. + { + "ftp=ftp1 ; ftp=ftp2 ; ftp=ftp3", + + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + NULL, + NULL, + NULL, + "ftp3:80", + }, + + // Include unsupported schemes -- they are discarded. + { + "crazy=foopy ; foo=bar ; https=myhttpsproxy", + + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + NULL, + NULL, + "myhttpsproxy:80", + NULL, + }, + }; + + net::ProxyConfig config; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + config.proxy_rules.ParseFromString(tests[i].proxy_rules); + + EXPECT_EQ(tests[i].type, config.proxy_rules.type); + ExpectProxyServerEquals(tests[i].single_proxy, + config.proxy_rules.single_proxy); + ExpectProxyServerEquals(tests[i].proxy_for_http, + config.proxy_rules.proxy_for_http); + ExpectProxyServerEquals(tests[i].proxy_for_https, + config.proxy_rules.proxy_for_https); + ExpectProxyServerEquals(tests[i].proxy_for_ftp, + config.proxy_rules.proxy_for_ftp); + } +} diff --git a/net/proxy/proxy_info.cc b/net/proxy/proxy_info.cc index 59734cf..98ca42f 100644 --- a/net/proxy/proxy_info.cc +++ b/net/proxy/proxy_info.cc @@ -23,6 +23,10 @@ void ProxyInfo::UseNamedProxy(const std::string& proxy_uri_list) { proxy_list_.Set(proxy_uri_list); } +void ProxyInfo::UseProxyServer(const ProxyServer& proxy_server) { + proxy_list_.SetSingleProxyServer(proxy_server); +} + std::string ProxyInfo::ToPacString() { return proxy_list_.ToPacString(); } diff --git a/net/proxy/proxy_info.h b/net/proxy/proxy_info.h index db9422d..5a386ae 100644 --- a/net/proxy/proxy_info.h +++ b/net/proxy/proxy_info.h @@ -34,6 +34,9 @@ class ProxyInfo { // It is OK to have LWS between entries. void UseNamedProxy(const std::string& proxy_uri_list); + // Set the proxy list to a single entry, |proxy_server|. + void UseProxyServer(const ProxyServer& proxy_server); + // Parse from the given PAC result. void UsePacString(const std::string& pac_string) { proxy_list_.SetFromPacString(pac_string); diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc index 36ac113..e390bbc 100644 --- a/net/proxy/proxy_list.cc +++ b/net/proxy/proxy_list.cc @@ -25,6 +25,12 @@ void ProxyList::Set(const std::string& proxy_uri_list) { } } +void ProxyList::SetSingleProxyServer(const ProxyServer& proxy_server) { + proxies_.clear(); + if (proxy_server.is_valid()) + proxies_.push_back(proxy_server); +} + void ProxyList::RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info) { std::vector<ProxyServer> new_proxy_list; std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); diff --git a/net/proxy/proxy_list.h b/net/proxy/proxy_list.h index b2b0976..884dec9 100644 --- a/net/proxy/proxy_list.h +++ b/net/proxy/proxy_list.h @@ -22,6 +22,9 @@ class ProxyList { // delimited by a semicolon. void Set(const std::string& proxy_uri_list); + // Set the proxy list to a single entry, |proxy_server|. + void SetSingleProxyServer(const ProxyServer& proxy_server); + // Remove all proxies known to be bad from the proxy list. void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info); diff --git a/net/proxy/proxy_resolver_mac.cc b/net/proxy/proxy_resolver_mac.cc index 48f0302..f8906bb 100644 --- a/net/proxy/proxy_resolver_mac.cc +++ b/net/proxy/proxy_resolver_mac.cc @@ -176,8 +176,8 @@ int ProxyConfigServiceMac::GetProxyConfig(ProxyConfig* config) { kSCPropNetProxiesFTPProxy, kSCPropNetProxiesFTPPort); if (proxy_server.is_valid()) { - config->proxy_rules += "ftp="; - config->proxy_rules += proxy_server.ToURI(); + config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + config->proxy_rules.proxy_for_ftp = proxy_server; } } if (GetBoolFromDictionary(config_dict.get(), @@ -189,10 +189,8 @@ int ProxyConfigServiceMac::GetProxyConfig(ProxyConfig* config) { kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort); if (proxy_server.is_valid()) { - if (!config->proxy_rules.empty()) - config->proxy_rules += ";"; - config->proxy_rules += "http="; - config->proxy_rules += proxy_server.ToURI(); + config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + config->proxy_rules.proxy_for_http = proxy_server; } } if (GetBoolFromDictionary(config_dict.get(), @@ -204,10 +202,8 @@ int ProxyConfigServiceMac::GetProxyConfig(ProxyConfig* config) { kSCPropNetProxiesHTTPSProxy, kSCPropNetProxiesHTTPSPort); if (proxy_server.is_valid()) { - if (!config->proxy_rules.empty()) - config->proxy_rules += ";"; - config->proxy_rules += "https="; - config->proxy_rules += proxy_server.ToURI(); + config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + config->proxy_rules.proxy_for_https = proxy_server; } } diff --git a/net/proxy/proxy_server.h b/net/proxy/proxy_server.h index b51e54f..0cf792c 100644 --- a/net/proxy/proxy_server.h +++ b/net/proxy/proxy_server.h @@ -103,6 +103,12 @@ class ProxyServer { // scheme. Returns -1 if unknown. static int GetDefaultPortForScheme(Scheme scheme); + bool operator==(const ProxyServer& other) const { + return scheme_ == other.scheme_ && + host_ == other.host_ && + port_ == other.port_; + } + private: // Create a ProxyServer given a scheme, and host/port string. If parsing the // host/port string fails, the returned instance will be invalid. diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 937d98f..40f4bd3 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -8,7 +8,6 @@ #include "base/compiler_specific.h" #include "base/logging.h" -#include "base/string_tokenizer.h" #include "base/string_util.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" @@ -294,42 +293,7 @@ int ProxyService::TryToCompleteSynchronously(const GURL& url, result->config_was_tried_ = true; if (!config_.proxy_rules.empty()) { - if (ShouldBypassProxyForURL(url)) { - result->UseDirect(); - } else { - // If proxies are specified on a per protocol basis, the proxy server - // field contains a list the format of which is as below:- - // "scheme1=url:port;scheme2=url:port", etc. - std::string url_scheme = url.scheme(); - - StringTokenizer proxy_server_list(config_.proxy_rules, ";"); - while (proxy_server_list.GetNext()) { - StringTokenizer proxy_server_for_scheme( - proxy_server_list.token_begin(), proxy_server_list.token_end(), - "="); - - while (proxy_server_for_scheme.GetNext()) { - const std::string& proxy_server_scheme = - proxy_server_for_scheme.token(); - - // If we fail to get the proxy server here, it means that - // this is a regular proxy server configuration, i.e. proxies - // are not configured per protocol. - if (!proxy_server_for_scheme.GetNext()) { - result->UseNamedProxy(proxy_server_scheme); - return OK; - } - - if (proxy_server_scheme == url_scheme) { - result->UseNamedProxy(proxy_server_for_scheme.token()); - return OK; - } - } - } - // We failed to find a matching proxy server for the current URL - // scheme. Default to direct. - result->UseDirect(); - } + ApplyProxyRules(url, config_.proxy_rules, result); return OK; } @@ -351,6 +315,38 @@ int ProxyService::TryToCompleteSynchronously(const GURL& url, return OK; } +void ProxyService::ApplyProxyRules(const GURL& url, + const ProxyConfig::ProxyRules& proxy_rules, + ProxyInfo* result) { + DCHECK(!proxy_rules.empty()); + + if (ShouldBypassProxyForURL(url)) { + result->UseDirect(); + return; + } + + switch (proxy_rules.type) { + case ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY: + result->UseProxyServer(proxy_rules.single_proxy); + break; + case ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME: { + const ProxyServer* entry = proxy_rules.MapSchemeToProxy(url.scheme()); + if (entry) { + result->UseProxyServer(*entry); + } else { + // We failed to find a matching proxy server for the current URL + // scheme. Default to direct. + result->UseDirect(); + } + break; + } + default: + result->UseDirect(); + NOTREACHED(); + break; + } +} + void ProxyService::InitPacThread() { if (!pac_thread_.get()) { pac_thread_.reset(new base::Thread("pac-thread")); diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index 8ad41c4..7e8fad4 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -141,6 +141,11 @@ class ProxyService { // (ProxyResolver runs on PAC thread.) int TryToCompleteSynchronously(const GURL& url, ProxyInfo* result); + // Set |result| with the proxy to use for |url|, based on |rules|. + void ApplyProxyRules(const GURL& url, + const ProxyConfig::ProxyRules& rules, + ProxyInfo* result); + // Starts the PAC thread if it isn't already running. void InitPacThread(); diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index ba8186f..68d4be5 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -687,7 +687,7 @@ TEST(ProxyServiceTest, ProxyBypassList) { // Test what happens when a proxy bypass list is specified. net::ProxyConfig config; - config.proxy_rules = "foopy1:8080;foopy2:9090"; + config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); config.auto_detect = false; config.proxy_bypass_local_names = true; @@ -767,7 +767,7 @@ TEST(ProxyServiceTest, ProxyBypassList) { TEST(ProxyServiceTest, PerProtocolProxyTests) { net::ProxyConfig config; - config.proxy_rules = "http=foopy1:8080;https=foopy2:8080"; + config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); config.auto_detect = false; SyncProxyService service1(new MockProxyConfigService(config), @@ -797,7 +797,7 @@ TEST(ProxyServiceTest, PerProtocolProxyTests) { EXPECT_FALSE(info3.is_direct()); EXPECT_EQ("foopy2:8080", info3.proxy_server().ToURI()); - config.proxy_rules = "foopy1:8080"; + config.proxy_rules.ParseFromString("foopy1:8080"); SyncProxyService service4(new MockProxyConfigService(config), new MockProxyResolver); GURL test_url4("www.microsoft.com"); |