summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/net.gyp1
-rw-r--r--net/proxy/proxy_config.cc54
-rw-r--r--net/proxy/proxy_config.h72
-rw-r--r--net/proxy/proxy_config_service_fixed.h3
-rw-r--r--net/proxy/proxy_config_service_win.cc7
-rw-r--r--net/proxy/proxy_config_service_win_unittest.cc115
-rw-r--r--net/proxy/proxy_config_unittest.cc199
-rw-r--r--net/proxy/proxy_info.cc4
-rw-r--r--net/proxy/proxy_info.h3
-rw-r--r--net/proxy/proxy_list.cc6
-rw-r--r--net/proxy/proxy_list.h3
-rw-r--r--net/proxy/proxy_resolver_mac.cc16
-rw-r--r--net/proxy/proxy_server.h6
-rw-r--r--net/proxy/proxy_service.cc70
-rw-r--r--net/proxy/proxy_service.h5
-rw-r--r--net/proxy/proxy_service_unittest.cc6
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");