diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-31 01:03:23 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-31 01:03:23 +0000 |
commit | 5b45aec04af2be235787c81369c77d627ebd639a (patch) | |
tree | af51655c9ca9374181722a96514f9b827cdceb34 | |
parent | 6dd6c74b945802513e94b4be1012ccfbe240f023 (diff) | |
download | chromium_src-5b45aec04af2be235787c81369c77d627ebd639a.zip chromium_src-5b45aec04af2be235787c81369c77d627ebd639a.tar.gz chromium_src-5b45aec04af2be235787c81369c77d627ebd639a.tar.bz2 |
Extract the parsing of proxy rules to ProxyConfig::ProxyRules, and unit-test.
This avoids re-parsing the rules every time a proxy resolve is done, and also adds extra tolerance for white space.
The other motivation is to not have to fiddle around with strings as much in the various ProxyConfigServceXXXX implementations.
Review URL: http://codereview.chromium.org/57011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12829 0039d316-1c4b-4281-b951-d872f2087c98
-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"); |