diff options
Diffstat (limited to 'net')
28 files changed, 677 insertions, 456 deletions
diff --git a/net/build/net.vcproj b/net/build/net.vcproj index a24ebda..ffe5699 100644 --- a/net/build/net.vcproj +++ b/net/build/net.vcproj @@ -1010,6 +1010,18 @@ Name="proxy" > <File + RelativePath="..\proxy\proxy_config.cc" + > + </File> + <File + RelativePath="..\proxy\proxy_config.h" + > + </File> + <File + RelativePath="..\proxy\proxy_config_service.h" + > + </File> + <File RelativePath="..\proxy\proxy_config_service_fixed.h" > </File> @@ -1022,6 +1034,26 @@ > </File> <File + RelativePath="..\proxy\proxy_info.cc" + > + </File> + <File + RelativePath="..\proxy\proxy_info.h" + > + </File> + <File + RelativePath="..\proxy\proxy_list.cc" + > + </File> + <File + RelativePath="..\proxy\proxy_list.h" + > + </File> + <File + RelativePath="..\proxy\proxy_resolver.h" + > + </File> + <File RelativePath="..\proxy\proxy_resolver_v8.cc" > </File> @@ -1042,6 +1074,10 @@ > </File> <File + RelativePath="..\proxy\proxy_retry_info.h" + > + </File> + <File RelativePath="..\proxy\proxy_script_fetcher.cc" > </File> diff --git a/net/build/net_unittests.vcproj b/net/build/net_unittests.vcproj index 36624d7..6c79cb3 100644 --- a/net/build/net_unittests.vcproj +++ b/net/build/net_unittests.vcproj @@ -419,6 +419,10 @@ Name="proxy" > <File + RelativePath="..\proxy\proxy_list_unittest.cc" + > + </File> + <File RelativePath="..\proxy\proxy_script_fetcher_unittest.cc" > </File> diff --git a/net/net.gyp b/net/net.gyp index e1c73d4..fc2ad65 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -228,15 +228,24 @@ 'http/http_vary_data.h', 'http/md4.cc', 'http/md4.h', + 'proxy/proxy_config.cc', + 'proxy/proxy_config.h', + 'proxy/proxy_config_service.h', 'proxy/proxy_config_service_fixed.h', 'proxy/proxy_config_service_win.cc', 'proxy/proxy_config_service_win.h', + 'proxy/proxy_info.cc', + 'proxy/proxy_info.h', + 'proxy/proxy_list.cc', + 'proxy/proxy_list.h', + 'proxy/proxy_resolver.h', 'proxy/proxy_resolver_mac.cc', 'proxy/proxy_resolver_script.h', 'proxy/proxy_resolver_v8.cc', 'proxy/proxy_resolver_v8.h', 'proxy/proxy_resolver_winhttp.cc', 'proxy/proxy_resolver_winhttp.h', + 'proxy/proxy_retry_info.h', 'proxy/proxy_script_fetcher.cc', 'proxy/proxy_script_fetcher.h', 'proxy/proxy_server.cc', @@ -423,6 +432,7 @@ 'http/http_transaction_unittest.h', 'http/http_util_unittest.cc', 'http/http_vary_data_unittest.cc', + 'proxy/proxy_list_unittest.cc', 'proxy/proxy_resolver_v8_unittest.cc', 'proxy/proxy_script_fetcher_unittest.cc', 'proxy/proxy_server_unittest.cc', diff --git a/net/net_lib.scons b/net/net_lib.scons index 6a06759..669928a 100644 --- a/net/net_lib.scons +++ b/net/net_lib.scons @@ -244,11 +244,20 @@ input_files = ChromeFileList([ 'disk_cache/trace.h', ]), MSVSFilter('proxy', [ + 'proxy/proxy_config.cc', + 'proxy/proxy_config.h', + 'proxy/proxy_config_service.h', 'proxy/proxy_config_service_fixed.h', 'proxy/proxy_config_service_win.cc', 'proxy/proxy_config_service_win.h', + 'proxy/proxy_info.cc', + 'proxy/proxy_info.h', + 'proxy/proxy_list.cc', + 'proxy/proxy_list.h', + 'proxy/proxy_resolver.h', 'proxy/proxy_resolver_winhttp.cc', 'proxy/proxy_resolver_winhttp.h', + 'proxy/proxy_retry_info.h', 'proxy/proxy_script_fetcher.cc', 'proxy/proxy_script_fetcher.h', 'proxy/proxy_server.cc', diff --git a/net/net_unittests.scons b/net/net_unittests.scons index ce469f9..e2beaac 100644 --- a/net/net_unittests.scons +++ b/net/net_unittests.scons @@ -110,6 +110,7 @@ input_files = ChromeFileList([ 'url_request/url_request_unittest.h', ]), MSVSFilter('proxy', [ + 'proxy/proxy_list_unittest.cc', 'proxy/proxy_script_fetcher_unittest.cc', 'proxy/proxy_server_unittest.cc', 'proxy/proxy_service_unittest.cc', diff --git a/net/proxy/proxy_config.cc b/net/proxy/proxy_config.cc new file mode 100644 index 0000000..b30cb9e --- /dev/null +++ b/net/proxy/proxy_config.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2006-2008 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" + +namespace net { + +// static +ProxyConfig::ID ProxyConfig::last_id_ = ProxyConfig::INVALID_ID; + +ProxyConfig::ProxyConfig() + : auto_detect(false), + proxy_bypass_local_names(false), + id_(++last_id_) { +} + +bool ProxyConfig::Equals(const ProxyConfig& other) const { + // The two configs can have different IDs. We are just interested in if they + // have the same settings. + return auto_detect == other.auto_detect && + pac_url == other.pac_url && + proxy_rules == other.proxy_rules && + proxy_bypass == other.proxy_bypass && + proxy_bypass_local_names == other.proxy_bypass_local_names; +} + +} // namespace net + diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h new file mode 100644 index 0000000..53fdcb2 --- /dev/null +++ b/net/proxy/proxy_config.h @@ -0,0 +1,70 @@ +// Copyright (c) 2006-2008 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. + +#ifndef NET_PROXY_PROXY_CONFIG_H_ +#define NET_PROXY_PROXY_CONFIG_H_ + +#include <string> +#include <vector> + +#include "googleurl/src/gurl.h" + +namespace net { + +// Proxy configuration used to by the ProxyService. +class ProxyConfig { + public: + typedef int ID; + + // Indicates an invalid proxy config. + enum { INVALID_ID = 0 }; + + ProxyConfig(); + // Default copy-constructor and assignment operator are OK! + + // Used to numerically identify this configuration. + ID id() const { return id_; } + + // True if the proxy configuration should be auto-detected. + bool auto_detect; + + // 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; + + // Indicates a list of hosts that should bypass any proxy configuration. For + // these hosts, a direct connection should always be used. + std::vector<std::string> proxy_bypass; + + // Indicates whether local names (no dots) bypass proxies. + bool proxy_bypass_local_names; + + // Returns true if the given config is equivalent to this config. + bool Equals(const ProxyConfig& other) const; + + private: + static int last_id_; + int id_; +}; + +} // namespace net + +#endif // NET_PROXY_PROXY_CONFIG_H_ + diff --git a/net/proxy/proxy_config_service.h b/net/proxy/proxy_config_service.h new file mode 100644 index 0000000..4a802c9 --- /dev/null +++ b/net/proxy/proxy_config_service.h @@ -0,0 +1,27 @@ +// Copyright (c) 2006-2008 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. + +#ifndef NET_PROXY_PROXY_CONFIG_SERVICE_H_ +#define NET_PROXY_PROXY_CONFIG_SERVICE_H_ + +namespace net { + +class ProxyConfig; + +// Synchronously fetch the system's proxy configuration settings. Called on +// the IO Thread. +class ProxyConfigService { + public: + virtual ~ProxyConfigService() {} + + // Get the proxy configuration. Returns OK if successful or an error code if + // otherwise. |config| should be in its initial state when this method is + // called. + virtual int GetProxyConfig(ProxyConfig* config) = 0; +}; + +} // namespace net + +#endif // NET_PROXY_PROXY_CONFIG_SERVICE_H_ + diff --git a/net/proxy/proxy_config_service_fixed.h b/net/proxy/proxy_config_service_fixed.h index ea0d8a1..5120093 100644 --- a/net/proxy/proxy_config_service_fixed.h +++ b/net/proxy/proxy_config_service_fixed.h @@ -5,7 +5,7 @@ #ifndef NET_PROXY_PROXY_CONFIG_SERVICE_FIXED_H_ #define NET_PROXY_PROXY_CONFIG_SERVICE_FIXED_H_ -#include "net/proxy/proxy_service.h" +#include "net/proxy/proxy_config_service.h" namespace net { diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc index 9779928..e3dc95e 100644 --- a/net/proxy/proxy_config_service_win.cc +++ b/net/proxy/proxy_config_service_win.cc @@ -7,8 +7,11 @@ #include <windows.h> #include <winhttp.h> +#include "base/logging.h" #include "base/string_tokenizer.h" +#include "base/string_util.h" #include "net/base/net_errors.h" +#include "net/proxy/proxy_config.h" #pragma comment(lib, "winhttp.lib") diff --git a/net/proxy/proxy_config_service_win.h b/net/proxy/proxy_config_service_win.h index f2a5e47..f9f0366 100644 --- a/net/proxy/proxy_config_service_win.h +++ b/net/proxy/proxy_config_service_win.h @@ -5,7 +5,7 @@ #ifndef NET_PROXY_PROXY_CONFIG_SERVICE_WIN_H_ #define NET_PROXY_PROXY_CONFIG_SERVICE_WIN_H_ -#include "net/proxy/proxy_service.h" +#include "net/proxy/proxy_config_service.h" namespace net { diff --git a/net/proxy/proxy_info.cc b/net/proxy/proxy_info.cc new file mode 100644 index 0000000..c1ef588 --- /dev/null +++ b/net/proxy/proxy_info.cc @@ -0,0 +1,31 @@ +// Copyright (c) 2006-2008 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_info.h" + +namespace net { + +ProxyInfo::ProxyInfo() + : config_id_(ProxyConfig::INVALID_ID), + config_was_tried_(false) { +} + +void ProxyInfo::Use(const ProxyInfo& other) { + proxy_list_ = other.proxy_list_; +} + +void ProxyInfo::UseDirect() { + proxy_list_.Set(std::string()); +} + +void ProxyInfo::UseNamedProxy(const std::string& proxy_uri_list) { + proxy_list_.Set(proxy_uri_list); +} + +std::string ProxyInfo::ToPacString() { + return proxy_list_.ToPacString(); +} + +} // namespace net + diff --git a/net/proxy/proxy_info.h b/net/proxy/proxy_info.h new file mode 100644 index 0000000..e66f9ec --- /dev/null +++ b/net/proxy/proxy_info.h @@ -0,0 +1,86 @@ +// Copyright (c) 2006-2008 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. + +#ifndef NET_PROXY_PROXY_INFO_H_ +#define NET_PROXY_PROXY_INFO_H_ + +#include <string> + +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_list.h" +#include "net/proxy/proxy_retry_info.h" +#include "net/proxy/proxy_server.h" + +class GURL; + +namespace net { + +// This object holds proxy information returned by ResolveProxy. +class ProxyInfo { + public: + ProxyInfo(); + // Default copy-constructor and assignment operator are OK! + + // Use the same proxy server as the given |proxy_info|. + void Use(const ProxyInfo& proxy_info); + + // Use a direct connection. + void UseDirect(); + + // Use a specific proxy server, of the form: + // proxy-uri = [<scheme> "://"] <hostname> [":" <port>] + // This may optionally be a semi-colon delimited list of <proxy-uri>. + // It is OK to have LWS between entries. + void UseNamedProxy(const std::string& proxy_uri_list); + + // Parse from the given PAC result. + void UsePacString(const std::string& pac_string) { + proxy_list_.SetFromPacString(pac_string); + } + + // Returns true if this proxy info specifies a direct connection. + bool is_direct() const { return proxy_list_.Get().is_direct(); } + + // Returns the first valid proxy server. + ProxyServer proxy_server() const { return proxy_list_.Get(); } + + // See description in ProxyList::ToPacString(). + std::string ToPacString(); + + // Marks the current proxy as bad. Returns true if there is another proxy + // available to try in proxy list_. + bool Fallback(ProxyRetryInfoMap* proxy_retry_info) { + return proxy_list_.Fallback(proxy_retry_info); + } + + // Remove all proxies known to be bad from the proxy list. + void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info) { + proxy_list_.RemoveBadProxies(proxy_retry_info); + } + + // Delete any entry which doesn't have one of the specified proxy schemes. + void RemoveProxiesWithoutScheme(int scheme_bit_field) { + proxy_list_.RemoveProxiesWithoutScheme(scheme_bit_field); + } + + private: + friend class ProxyService; + + // If proxy_list_ is set to empty, then a "direct" connection is indicated. + ProxyList proxy_list_; + + // This value identifies the proxy config used to initialize this object. + ProxyConfig::ID config_id_; + + // This flag is false when the proxy configuration was known to be bad when + // this proxy info was initialized. In such cases, we know that if this + // proxy info does not yield a connection that we might want to reconsider + // the proxy config given by config_id_. + bool config_was_tried_; +}; + +} // namespace net + +#endif // NET_PROXY_PROXY_INFO_H_ + diff --git a/net/proxy/proxy_list.cc b/net/proxy/proxy_list.cc new file mode 100644 index 0000000..2313896 --- /dev/null +++ b/net/proxy/proxy_list.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2006-2008 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_list.h" + +#include "base/logging.h" +#include "base/string_tokenizer.h" +#include "base/time.h" + +using base::TimeDelta; +using base::TimeTicks; + +namespace net { + +void ProxyList::Set(const std::string& proxy_uri_list) { + proxies_.clear(); + StringTokenizer str_tok(proxy_uri_list, ";"); + while (str_tok.GetNext()) { + ProxyServer uri = ProxyServer::FromURI( + str_tok.token_begin(), str_tok.token_end()); + // Silently discard malformed inputs. + if (uri.is_valid()) + proxies_.push_back(uri); + } +} + +void ProxyList::RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info) { + std::vector<ProxyServer> new_proxy_list; + std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); + for (; iter != proxies_.end(); ++iter) { + ProxyRetryInfoMap::const_iterator bad_proxy = + proxy_retry_info.find(iter->ToURI()); + if (bad_proxy != proxy_retry_info.end()) { + // This proxy is bad. Check if it's time to retry. + if (bad_proxy->second.bad_until >= TimeTicks::Now()) { + // still invalid. + continue; + } + } + new_proxy_list.push_back(*iter); + } + + proxies_ = new_proxy_list; +} + +void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) { + for (std::vector<ProxyServer>::iterator it = proxies_.begin(); + it != proxies_.end(); ) { + if (!(scheme_bit_field & it->scheme())) { + it = proxies_.erase(it); + continue; + } + ++it; + } +} + +ProxyServer ProxyList::Get() const { + if (!proxies_.empty()) + return proxies_[0]; + return ProxyServer(ProxyServer::SCHEME_DIRECT, std::string(), -1); +} + +std::string ProxyList::ToPacString() const { + std::string proxy_list; + std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); + for (; iter != proxies_.end(); ++iter) { + if (!proxy_list.empty()) + proxy_list += ";"; + proxy_list += iter->ToPacString(); + } + return proxy_list.empty() ? "DIRECT" : proxy_list; +} + +void ProxyList::SetFromPacString(const std::string& pac_string) { + StringTokenizer entry_tok(pac_string, ";"); + proxies_.clear(); + while (entry_tok.GetNext()) { + ProxyServer uri = ProxyServer::FromPacString( + entry_tok.token_begin(), entry_tok.token_end()); + // Silently discard malformed inputs. + if (uri.is_valid()) + proxies_.push_back(uri); + } +} + +bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) { + // Number of minutes to wait before retrying a bad proxy server. + const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); + + if (proxies_.empty()) { + NOTREACHED(); + return false; + } + + std::string key = proxies_[0].ToURI(); + + // Mark this proxy as bad. + ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key); + if (iter != proxy_retry_info->end()) { + // TODO(nsylvain): This is not the first time we get this. We should + // double the retry time. Bug 997660. + iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay; + } else { + ProxyRetryInfo retry_info; + retry_info.current_delay = kProxyRetryDelay; + retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; + (*proxy_retry_info)[key] = retry_info; + } + + // Remove this proxy from our list. + proxies_.erase(proxies_.begin()); + + return !proxies_.empty(); +} + +} // namespace net + diff --git a/net/proxy/proxy_list.h b/net/proxy/proxy_list.h new file mode 100644 index 0000000..ac46671 --- /dev/null +++ b/net/proxy/proxy_list.h @@ -0,0 +1,59 @@ +// Copyright (c) 2006-2008 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. + +#ifndef NET_PROXY_PROXY_LIST_H_ +#define NET_PROXY_PROXY_LIST_H_ + +#include <string> +#include <vector> + +#include "net/proxy/proxy_retry_info.h" +#include "net/proxy/proxy_server.h" + +namespace net { + +// This class is used to hold a list of proxies returned by GetProxyForUrl or +// manually configured. It handles proxy fallback if multiple servers are +// specified. +class ProxyList { + public: + // Initializes the proxy list to a string containing one or more proxy servers + // delimited by a semicolon. + void Set(const std::string& proxy_uri_list); + + // Remove all proxies known to be bad from the proxy list. + void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info); + + // Delete any entry which doesn't have one of the specified proxy schemes. + // |scheme_bit_field| is a bunch of ProxyServer::Scheme bitwise ORed together. + void RemoveProxiesWithoutScheme(int scheme_bit_field); + + // Returns the first valid proxy server in the list. + ProxyServer Get() const; + + // Set the list by parsing the pac result |pac_string|. + // Some examples for |pac_string|: + // "DIRECT" + // "PROXY foopy1" + // "PROXY foopy1; SOCKS4 foopy2:1188" + void SetFromPacString(const std::string& pac_string); + + // Returns a PAC-style semicolon-separated list of valid proxy servers. + // For example: "PROXY xxx.xxx.xxx.xxx:xx; SOCKS yyy.yyy.yyy:yy". + std::string ToPacString() const; + + // Marks the current proxy server as bad and deletes it from the list. The + // list of known bad proxies is given by proxy_retry_info. Returns true if + // there is another server available in the list. + bool Fallback(ProxyRetryInfoMap* proxy_retry_info); + + private: + // List of proxies. + std::vector<ProxyServer> proxies_; +}; + +} // namespace net + +#endif // NET_PROXY_PROXY_LIST_H_ + diff --git a/net/proxy/proxy_list_unittest.cc b/net/proxy/proxy_list_unittest.cc new file mode 100644 index 0000000..c604d0a --- /dev/null +++ b/net/proxy/proxy_list_unittest.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2006-2008 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_list.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Test parsing from a PAC string. +TEST(ProxyListTest, SetFromPacString) { + const struct { + const char* pac_input; + const char* pac_output; + } tests[] = { + // Valid inputs: + { "PROXY foopy:10", + "PROXY foopy:10", + }, + { " DIRECT", // leading space. + "DIRECT", + }, + { "PROXY foopy1 ; proxy foopy2;\t DIRECT", + "PROXY foopy1:80;PROXY foopy2:80;DIRECT", + }, + { "proxy foopy1 ; SOCKS foopy2", + "PROXY foopy1:80;SOCKS foopy2:1080", + }, + + // Invalid inputs (parts which aren't understood get + // silently discarded): + { "PROXY-foopy:10", + "DIRECT", + }, + { "PROXY", + "DIRECT", + }, + { "PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;", + "PROXY foopy1:80;SOCKS5 foopy2:1080", + }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + net::ProxyList list; + list.SetFromPacString(tests[i].pac_input); + EXPECT_EQ(tests[i].pac_output, list.ToPacString()); + } +} + +TEST(ProxyListTest, RemoveProxiesWithoutScheme) { + const struct { + const char* pac_input; + int filter; + const char* filtered_pac_output; + } tests[] = { + { "PROXY foopy:10 ; SOCKS5 foopy2 ; SOCKS foopy11 ; PROXY foopy3 ; DIRECT", + // Remove anything that isn't HTTP or DIRECT. + net::ProxyServer::SCHEME_DIRECT | net::ProxyServer::SCHEME_HTTP, + "PROXY foopy:10;PROXY foopy3:80;DIRECT", + }, + { "PROXY foopy:10 | SOCKS5 foopy2", + // Remove anything that isn't HTTP or SOCKS5. + net::ProxyServer::SCHEME_DIRECT | net::ProxyServer::SCHEME_SOCKS4, + "DIRECT", + }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + net::ProxyList list; + list.SetFromPacString(tests[i].pac_input); + list.RemoveProxiesWithoutScheme(tests[i].filter); + EXPECT_EQ(tests[i].filtered_pac_output, list.ToPacString()); + } +} + diff --git a/net/proxy/proxy_resolver.h b/net/proxy/proxy_resolver.h new file mode 100644 index 0000000..254b250 --- /dev/null +++ b/net/proxy/proxy_resolver.h @@ -0,0 +1,54 @@ +// Copyright (c) 2006-2008 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. + +#ifndef NET_PROXY_PROXY_RESOLVER_H_ +#define NET_PROXY_PROXY_RESOLVER_H_ + +#include <string> + +#include "base/logging.h" + +class GURL; + +namespace net { + +class ProxyInfo; + +// Synchronously resolve the proxy for a URL, using a PAC script. Called on the +// PAC Thread. +class ProxyResolver { + public: + + // If a subclass sets |does_fetch| to false, then the owning ProxyResolver + // will download PAC scripts on our behalf, and notify changes with + // SetPacScript(). Otherwise the subclass is expected to fetch the + // PAC script internally, and SetPacScript() will go unused. + ProxyResolver(bool does_fetch) : does_fetch_(does_fetch) {} + + virtual ~ProxyResolver() {} + + // Query the proxy auto-config file (specified by |pac_url|) for the proxy to + // use to load the given |query_url|. Returns OK if successful or an error + // code otherwise. + virtual int GetProxyForURL(const GURL& query_url, + const GURL& pac_url, + ProxyInfo* results) = 0; + + // Called whenever the PAC script has changed, with the contents of the + // PAC script. |bytes| may be empty string if there was a fetch error. + virtual void SetPacScript(const std::string& bytes) { + // Must override SetPacScript() if |does_fetch_ = true|. + NOTREACHED(); + } + + bool does_fetch() const { return does_fetch_; } + + protected: + bool does_fetch_; +}; + +} // namespace net + +#endif // NET_PROXY_PROXY_RESOLVER_H_ + diff --git a/net/proxy/proxy_resolver_mac.cc b/net/proxy/proxy_resolver_mac.cc index a2e8788..796847d 100644 --- a/net/proxy/proxy_resolver_mac.cc +++ b/net/proxy/proxy_resolver_mac.cc @@ -12,6 +12,9 @@ #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "net/base/net_errors.h" +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_info.h" +#include "net/proxy/proxy_server.h" namespace { diff --git a/net/proxy/proxy_resolver_mac.h b/net/proxy/proxy_resolver_mac.h index 8796d45..8413624 100644 --- a/net/proxy/proxy_resolver_mac.h +++ b/net/proxy/proxy_resolver_mac.h @@ -5,7 +5,8 @@ #ifndef NET_PROXY_PROXY_RESOLVER_MAC_H_ #define NET_PROXY_PROXY_RESOLVER_MAC_H_ -#include "net/proxy/proxy_service.h" +#include "net/proxy/proxy_config_service.h" +#include "net/proxy/proxy_resolver.h" namespace net { diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index 09472e9..81c1138 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc @@ -5,10 +5,13 @@ #include "net/proxy/proxy_resolver_v8.h" #include "base/logging.h" +#include "base/string_util.h" +#include "googleurl/src/gurl.h" #include "net/base/address_list.h" #include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" +#include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_script.h" #include "v8/include/v8.h" diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h index ec765fb..a0275c8 100644 --- a/net/proxy/proxy_resolver_v8.h +++ b/net/proxy/proxy_resolver_v8.h @@ -8,7 +8,7 @@ #include <string> #include "base/scoped_ptr.h" -#include "net/proxy/proxy_service.h" +#include "net/proxy/proxy_resolver.h" namespace net { diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc index 5f8bef2..c2ddb9f 100644 --- a/net/proxy/proxy_resolver_v8_unittest.cc +++ b/net/proxy/proxy_resolver_v8_unittest.cc @@ -3,11 +3,12 @@ // found in the LICENSE file. #include "base/file_util.h" -#include "base/logging.h" +#include "base/string_util.h" #include "base/path_service.h" +#include "googleurl/src/gurl.h" #include "net/base/net_errors.h" -#include "net/base/net_util.h" #include "net/proxy/proxy_resolver_v8.h" +#include "net/proxy/proxy_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/net/proxy/proxy_resolver_winhttp.cc b/net/proxy/proxy_resolver_winhttp.cc index 6065846..a3ed9fe 100644 --- a/net/proxy/proxy_resolver_winhttp.cc +++ b/net/proxy/proxy_resolver_winhttp.cc @@ -8,7 +8,10 @@ #include <winhttp.h> #include "base/histogram.h" +#include "base/string_util.h" +#include "googleurl/src/gurl.h" #include "net/base/net_errors.h" +#include "net/proxy/proxy_info.h" #pragma comment(lib, "winhttp.lib") diff --git a/net/proxy/proxy_resolver_winhttp.h b/net/proxy/proxy_resolver_winhttp.h index 032cab7..b709702 100644 --- a/net/proxy/proxy_resolver_winhttp.h +++ b/net/proxy/proxy_resolver_winhttp.h @@ -5,9 +5,9 @@ #ifndef NET_PROXY_PROXY_RESOLVER_WINHTTP_H_ #define NET_PROXY_PROXY_RESOLVER_WINHTTP_H_ -#include "net/proxy/proxy_service.h" +#include "net/proxy/proxy_resolver.h" -typedef LPVOID HINTERNET; // From winhttp.h +typedef void* HINTERNET; // From winhttp.h namespace net { diff --git a/net/proxy/proxy_retry_info.h b/net/proxy/proxy_retry_info.h new file mode 100644 index 0000000..3e5149e --- /dev/null +++ b/net/proxy/proxy_retry_info.h @@ -0,0 +1,31 @@ +// Copyright (c) 2006-2008 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. + +#ifndef NET_PROXY_PROXY_RETRY_INFO_H_ +#define NET_PROXY_PROXY_RETRY_INFO_H_ + +#include <map> + +#include "base/time.h" + +namespace net { + +// Contains the information about when to retry a proxy server. +struct ProxyRetryInfo { + // We should not retry until this time. + base::TimeTicks bad_until; + + // This is the current delay. If the proxy is still bad, we need to increase + // this delay. + base::TimeDelta current_delay; +}; + +// Map of proxy servers with the associated RetryInfo structures. +// The key is a proxy URI string [<scheme>"://"]<host>":"<port>. +typedef std::map<std::string, ProxyRetryInfo> ProxyRetryInfoMap; + +} // namespace net + +#endif // NET_PROXY_PROXY_RETRY_INFO_H_ + diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 438f147..9b1462f 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -4,20 +4,16 @@ #include "net/proxy/proxy_service.h" -#if defined(OS_WIN) -#include <windows.h> -#include <winhttp.h> -#endif - #include <algorithm> #include "base/compiler_specific.h" #include "base/logging.h" -#include "base/message_loop.h" #include "base/string_tokenizer.h" +#include "base/string_util.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" #include "net/proxy/proxy_config_service_fixed.h" +#include "net/proxy/proxy_script_fetcher.h" #if defined(OS_WIN) #include "net/proxy/proxy_config_service_win.h" #include "net/proxy/proxy_resolver_winhttp.h" @@ -67,153 +63,6 @@ class NotifyFetchCompletionTask : public Task { std::string bytes_; }; -// ProxyConfig ---------------------------------------------------------------- - -// static -ProxyConfig::ID ProxyConfig::last_id_ = ProxyConfig::INVALID_ID; - -ProxyConfig::ProxyConfig() - : auto_detect(false), - proxy_bypass_local_names(false), - id_(++last_id_) { -} - -bool ProxyConfig::Equals(const ProxyConfig& other) const { - // The two configs can have different IDs. We are just interested in if they - // have the same settings. - return auto_detect == other.auto_detect && - pac_url == other.pac_url && - proxy_rules == other.proxy_rules && - proxy_bypass == other.proxy_bypass && - proxy_bypass_local_names == other.proxy_bypass_local_names; -} - -// ProxyList ------------------------------------------------------------------ - -void ProxyList::Set(const std::string& proxy_uri_list) { - proxies_.clear(); - StringTokenizer str_tok(proxy_uri_list, ";"); - while (str_tok.GetNext()) { - ProxyServer uri = ProxyServer::FromURI( - str_tok.token_begin(), str_tok.token_end()); - // Silently discard malformed inputs. - if (uri.is_valid()) - proxies_.push_back(uri); - } -} - -void ProxyList::RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info) { - std::vector<ProxyServer> new_proxy_list; - std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); - for (; iter != proxies_.end(); ++iter) { - ProxyRetryInfoMap::const_iterator bad_proxy = - proxy_retry_info.find(iter->ToURI()); - if (bad_proxy != proxy_retry_info.end()) { - // This proxy is bad. Check if it's time to retry. - if (bad_proxy->second.bad_until >= TimeTicks::Now()) { - // still invalid. - continue; - } - } - new_proxy_list.push_back(*iter); - } - - proxies_ = new_proxy_list; -} - -void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) { - for (std::vector<ProxyServer>::iterator it = proxies_.begin(); - it != proxies_.end(); ) { - if (!(scheme_bit_field & it->scheme())) { - it = proxies_.erase(it); - continue; - } - ++it; - } -} - -ProxyServer ProxyList::Get() const { - if (!proxies_.empty()) - return proxies_[0]; - return ProxyServer(ProxyServer::SCHEME_DIRECT, std::string(), -1); -} - -std::string ProxyList::ToPacString() const { - std::string proxy_list; - std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); - for (; iter != proxies_.end(); ++iter) { - if (!proxy_list.empty()) - proxy_list += ";"; - proxy_list += iter->ToPacString(); - } - return proxy_list.empty() ? "DIRECT" : proxy_list; -} - -void ProxyList::SetFromPacString(const std::string& pac_string) { - StringTokenizer entry_tok(pac_string, ";"); - proxies_.clear(); - while (entry_tok.GetNext()) { - ProxyServer uri = ProxyServer::FromPacString( - entry_tok.token_begin(), entry_tok.token_end()); - // Silently discard malformed inputs. - if (uri.is_valid()) - proxies_.push_back(uri); - } -} - -bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) { - // Number of minutes to wait before retrying a bad proxy server. - const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); - - if (proxies_.empty()) { - NOTREACHED(); - return false; - } - - std::string key = proxies_[0].ToURI(); - - // Mark this proxy as bad. - ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key); - if (iter != proxy_retry_info->end()) { - // TODO(nsylvain): This is not the first time we get this. We should - // double the retry time. Bug 997660. - iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay; - } else { - ProxyRetryInfo retry_info; - retry_info.current_delay = kProxyRetryDelay; - retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; - (*proxy_retry_info)[key] = retry_info; - } - - // Remove this proxy from our list. - proxies_.erase(proxies_.begin()); - - return !proxies_.empty(); -} - -// ProxyInfo ------------------------------------------------------------------ - -ProxyInfo::ProxyInfo() - : config_id_(ProxyConfig::INVALID_ID), - config_was_tried_(false) { -} - -void ProxyInfo::Use(const ProxyInfo& other) { - proxy_list_ = other.proxy_list_; -} - -void ProxyInfo::UseDirect() { - proxy_list_.Set(std::string()); -} - -void ProxyInfo::UseNamedProxy(const std::string& proxy_uri_list) { - proxy_list_.Set(proxy_uri_list); -} - -std::string ProxyInfo::ToPacString() { - return proxy_list_.ToPacString(); -} - // ProxyService::PacRequest --------------------------------------------------- // We rely on the fact that the origin thread (and its message loop) will not @@ -633,6 +482,11 @@ void ProxyService::CancelPacRequest(PacRequest* req) { } } +void ProxyService::SetProxyScriptFetcher( + ProxyScriptFetcher* proxy_script_fetcher) { + proxy_script_fetcher_.reset(proxy_script_fetcher); +} + void ProxyService::DidCompletePacRequest(int config_id, int result_code) { // If we get an error that indicates a bad PAC config, then we should // remember that, and not try the PAC config again for a while. diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index 3c29195..21b0e07 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -6,95 +6,24 @@ #define NET_PROXY_PROXY_SERVICE_H_ #include <deque> -#include <map> #include <string> -#include <vector> #include "base/ref_counted.h" #include "base/scoped_ptr.h" -#include "base/string_util.h" #include "base/thread.h" -#include "base/time.h" #include "base/waitable_event.h" -#include "googleurl/src/gurl.h" #include "net/base/completion_callback.h" -#include "net/proxy/proxy_script_fetcher.h" #include "net/proxy/proxy_server.h" +#include "net/proxy/proxy_info.h" class GURL; namespace net { +class ProxyScriptFetcher; class ProxyConfigService; -class ProxyInfo; class ProxyResolver; -// Proxy configuration used to by the ProxyService. -class ProxyConfig { - public: - typedef int ID; - - // Indicates an invalid proxy config. - enum { INVALID_ID = 0 }; - - ProxyConfig(); - // Default copy-constructor and assignment operator are OK! - - // Used to numerically identify this configuration. - ID id() const { return id_; } - - // True if the proxy configuration should be auto-detected. - bool auto_detect; - - // 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; - - // Indicates a list of hosts that should bypass any proxy configuration. For - // these hosts, a direct connection should always be used. - std::vector<std::string> proxy_bypass; - - // Indicates whether local names (no dots) bypass proxies. - bool proxy_bypass_local_names; - - // Returns true if the given config is equivalent to this config. - bool Equals(const ProxyConfig& other) const; - - private: - static int last_id_; - int id_; -}; - -// Contains the information about when to retry a proxy server. -struct ProxyRetryInfo { - // We should not retry until this time. - base::TimeTicks bad_until; - - // This is the current delay. If the proxy is still bad, we need to increase - // this delay. - base::TimeDelta current_delay; -}; - -// Map of proxy servers with the associated RetryInfo structures. -// The key is a proxy URI string [<scheme>"://"]<host>":"<port>. -typedef std::map<std::string, ProxyRetryInfo> ProxyRetryInfoMap; - // This class can be used to resolve the proxy server to use when loading a // HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy // resolution. See ProxyResolverWinHttp for example. @@ -151,6 +80,11 @@ class ProxyService { // Call this method with a non-null |pac_request| to cancel the PAC request. void CancelPacRequest(PacRequest* pac_request); + // Set the ProxyScriptFetcher dependency. This is needed if the ProxyResolver + // is of type ProxyResolverWithoutFetch. ProxyService takes ownership of + // |proxy_script_fetcher|. + void SetProxyScriptFetcher(ProxyScriptFetcher* proxy_script_fetcher); + // Create a proxy service using the specified settings. If |pi| is NULL then // the system's default proxy settings will be used (on Windows this will // use IE's settings). @@ -160,13 +94,6 @@ class ProxyService { // so it falls back to direct connect. static ProxyService* CreateNull(); - // Set the ProxyScriptFetcher dependency. This is needed if the ProxyResolver - // is of type ProxyResolverWithoutFetch. ProxyService takes ownership of - // |proxy_script_fetcher|. - void SetProxyScriptFetcher(ProxyScriptFetcher* proxy_script_fetcher) { - proxy_script_fetcher_.reset(proxy_script_fetcher); - } - private: friend class PacRequest; @@ -272,155 +199,6 @@ class ProxyService { DISALLOW_COPY_AND_ASSIGN(ProxyService); }; -// This class is used to hold a list of proxies returned by GetProxyForUrl or -// manually configured. It handles proxy fallback if multiple servers are -// specified. -class ProxyList { - public: - // Initializes the proxy list to a string containing one or more proxy servers - // delimited by a semicolon. - void Set(const std::string& proxy_uri_list); - - // Remove all proxies known to be bad from the proxy list. - void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info); - - // Delete any entry which doesn't have one of the specified proxy schemes. - // |scheme_bit_field| is a bunch of ProxyServer::Scheme bitwise ORed together. - void RemoveProxiesWithoutScheme(int scheme_bit_field); - - // Returns the first valid proxy server in the list. - ProxyServer Get() const; - - // Set the list by parsing the pac result |pac_string|. - // Some examples for |pac_string|: - // "DIRECT" - // "PROXY foopy1" - // "PROXY foopy1; SOCKS4 foopy2:1188" - void SetFromPacString(const std::string& pac_string); - - // Returns a PAC-style semicolon-separated list of valid proxy servers. - // For example: "PROXY xxx.xxx.xxx.xxx:xx; SOCKS yyy.yyy.yyy:yy". - std::string ToPacString() const; - - // Marks the current proxy server as bad and deletes it from the list. The - // list of known bad proxies is given by proxy_retry_info. Returns true if - // there is another server available in the list. - bool Fallback(ProxyRetryInfoMap* proxy_retry_info); - - private: - // List of proxies. - std::vector<ProxyServer> proxies_; -}; - -// This object holds proxy information returned by ResolveProxy. -class ProxyInfo { - public: - ProxyInfo(); - // Default copy-constructor and assignment operator are OK! - - // Use the same proxy server as the given |proxy_info|. - void Use(const ProxyInfo& proxy_info); - - // Use a direct connection. - void UseDirect(); - - // Use a specific proxy server, of the form: - // proxy-uri = [<scheme> "://"] <hostname> [":" <port>] - // This may optionally be a semi-colon delimited list of <proxy-uri>. - // It is OK to have LWS between entries. - void UseNamedProxy(const std::string& proxy_uri_list); - - // Parse from the given PAC result. - void UsePacString(const std::string& pac_string) { - proxy_list_.SetFromPacString(pac_string); - } - - // Returns true if this proxy info specifies a direct connection. - bool is_direct() const { return proxy_list_.Get().is_direct(); } - - // Returns the first valid proxy server. - ProxyServer proxy_server() const { return proxy_list_.Get(); } - - // See description in ProxyList::ToPacString(). - std::string ToPacString(); - - // Marks the current proxy as bad. Returns true if there is another proxy - // available to try in proxy list_. - bool Fallback(ProxyRetryInfoMap* proxy_retry_info) { - return proxy_list_.Fallback(proxy_retry_info); - } - - // Remove all proxies known to be bad from the proxy list. - void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info) { - proxy_list_.RemoveBadProxies(proxy_retry_info); - } - - // Delete any entry which doesn't have one of the specified proxy schemes. - void RemoveProxiesWithoutScheme(int scheme_bit_field) { - proxy_list_.RemoveProxiesWithoutScheme(scheme_bit_field); - } - - private: - friend class ProxyService; - - // If proxy_list_ is set to empty, then a "direct" connection is indicated. - ProxyList proxy_list_; - - // This value identifies the proxy config used to initialize this object. - ProxyConfig::ID config_id_; - - // This flag is false when the proxy configuration was known to be bad when - // this proxy info was initialized. In such cases, we know that if this - // proxy info does not yield a connection that we might want to reconsider - // the proxy config given by config_id_. - bool config_was_tried_; -}; - -// Synchronously fetch the system's proxy configuration settings. Called on -// the IO Thread. -class ProxyConfigService { - public: - virtual ~ProxyConfigService() {} - - // Get the proxy configuration. Returns OK if successful or an error code if - // otherwise. |config| should be in its initial state when this method is - // called. - virtual int GetProxyConfig(ProxyConfig* config) = 0; -}; - -// Synchronously resolve the proxy for a URL, using a PAC script. Called on the -// PAC Thread. -class ProxyResolver { - public: - - // If a subclass sets |does_fetch| to false, then the owning ProxyResolver - // will download PAC scripts on our behalf, and notify changes with - // SetPacScript(). Otherwise the subclass is expected to fetch the - // PAC script internally, and SetPacScript() will go unused. - ProxyResolver(bool does_fetch) : does_fetch_(does_fetch) {} - - virtual ~ProxyResolver() {} - - // Query the proxy auto-config file (specified by |pac_url|) for the proxy to - // use to load the given |query_url|. Returns OK if successful or an error - // code otherwise. - virtual int GetProxyForURL(const GURL& query_url, - const GURL& pac_url, - ProxyInfo* results) = 0; - - // Called whenever the PAC script has changed, with the contents of the - // PAC script. |bytes| may be empty string if there was a fetch error. - virtual void SetPacScript(const std::string& bytes) { - // Must override SetPacScript() if |does_fetch_ = true|. - NOTREACHED(); - } - - bool does_fetch() const { return does_fetch_; } - - protected: - bool does_fetch_; -}; - // Wrapper for invoking methods on a ProxyService synchronously. class SyncProxyServiceHelper : public base::RefCountedThreadSafe<SyncProxyServiceHelper> { diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index 84a9395..ea1d56b 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -5,6 +5,9 @@ #include "base/compiler_specific.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" +#include "net/proxy/proxy_config_service.h" +#include "net/proxy/proxy_resolver.h" +#include "net/proxy/proxy_script_fetcher.h" #include "net/proxy/proxy_service.h" #include "testing/gtest/include/gtest/gtest.h" @@ -348,72 +351,6 @@ template<> void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( MockProxyScriptFetcher* remover) {} -// Test parsing from a PAC string. -TEST(ProxyListTest, SetFromPacString) { - const struct { - const char* pac_input; - const char* pac_output; - } tests[] = { - // Valid inputs: - { "PROXY foopy:10", - "PROXY foopy:10", - }, - { " DIRECT", // leading space. - "DIRECT", - }, - { "PROXY foopy1 ; proxy foopy2;\t DIRECT", - "PROXY foopy1:80;PROXY foopy2:80;DIRECT", - }, - { "proxy foopy1 ; SOCKS foopy2", - "PROXY foopy1:80;SOCKS foopy2:1080", - }, - - // Invalid inputs (parts which aren't understood get - // silently discarded): - { "PROXY-foopy:10", - "DIRECT", - }, - { "PROXY", - "DIRECT", - }, - { "PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;", - "PROXY foopy1:80;SOCKS5 foopy2:1080", - }, - }; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - net::ProxyList list; - list.SetFromPacString(tests[i].pac_input); - EXPECT_EQ(tests[i].pac_output, list.ToPacString()); - } -} - -TEST(ProxyListTest, RemoveProxiesWithoutScheme) { - const struct { - const char* pac_input; - int filter; - const char* filtered_pac_output; - } tests[] = { - { "PROXY foopy:10 ; SOCKS5 foopy2 ; SOCKS foopy11 ; PROXY foopy3 ; DIRECT", - // Remove anything that isn't HTTP or DIRECT. - net::ProxyServer::SCHEME_DIRECT | net::ProxyServer::SCHEME_HTTP, - "PROXY foopy:10;PROXY foopy3:80;DIRECT", - }, - { "PROXY foopy:10 | SOCKS5 foopy2", - // Remove anything that isn't HTTP or SOCKS5. - net::ProxyServer::SCHEME_DIRECT | net::ProxyServer::SCHEME_SOCKS4, - "DIRECT", - }, - }; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - net::ProxyList list; - list.SetFromPacString(tests[i].pac_input); - list.RemoveProxiesWithoutScheme(tests[i].filter); - EXPECT_EQ(tests[i].filtered_pac_output, list.ToPacString()); - } -} - TEST(ProxyServiceTest, Direct) { SyncProxyService service(new MockProxyConfigService, new MockProxyResolver); |