Commit db8ff912 authored by asanka@chromium.org's avatar asanka@chromium.org

Track sources of proxy settings.

ProxyConfig keeps track of the source of proxy settings. During proxy resolution ProxyService tags the resulting ProxyInfo with the same source information.

BUG=none
TEST=net_unittests


Review URL: https://chromiumcodereview.appspot.com/10310179

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141784 0039d316-1c4b-4281-b951-d872f2087c98
parent 72cf3215
......@@ -557,6 +557,8 @@
'proxy/proxy_config_service_mac.h',
'proxy/proxy_config_service_win.cc',
'proxy/proxy_config_service_win.h',
'proxy/proxy_config_source.cc',
'proxy/proxy_config_source.h',
'proxy/proxy_info.cc',
'proxy/proxy_info.h',
'proxy/proxy_list.cc',
......@@ -1184,6 +1186,7 @@
'proxy/proxy_config_service_linux_unittest.cc',
'proxy/proxy_config_service_win_unittest.cc',
'proxy/proxy_config_unittest.cc',
'proxy/proxy_info_unittest.cc',
'proxy/proxy_list_unittest.cc',
'proxy/proxy_resolver_js_bindings_unittest.cc',
'proxy/proxy_resolver_v8_unittest.cc',
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -32,7 +32,7 @@ ProxyConfig::ProxyRules::ProxyRules()
ProxyConfig::ProxyRules::~ProxyRules() {
}
void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) {
void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) const {
if (empty()) {
result->UseDirect();
return;
......@@ -42,7 +42,7 @@ void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) {
if (reverse_bypass)
bypass_proxy = !bypass_proxy;
if (bypass_proxy) {
result->UseDirect();
result->UseDirectWithBypassedProxy();
return;
}
......@@ -159,7 +159,8 @@ ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
}
ProxyConfig::ProxyConfig()
: auto_detect_(false), pac_mandatory_(false), id_(kInvalidConfigID) {
: auto_detect_(false), pac_mandatory_(false),
source_(PROXY_CONFIG_SOURCE_UNKNOWN), id_(kInvalidConfigID) {
}
ProxyConfig::ProxyConfig(const ProxyConfig& config)
......@@ -167,6 +168,7 @@ ProxyConfig::ProxyConfig(const ProxyConfig& config)
pac_url_(config.pac_url_),
pac_mandatory_(config.pac_mandatory_),
proxy_rules_(config.proxy_rules_),
source_(config.source_),
id_(config.id_) {
}
......@@ -178,13 +180,14 @@ ProxyConfig& ProxyConfig::operator=(const ProxyConfig& config) {
pac_url_ = config.pac_url_;
pac_mandatory_ = config.pac_mandatory_;
proxy_rules_ = config.proxy_rules_;
source_ = config.source_;
id_ = config.id_;
return *this;
}
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.
// The two configs can have different IDs and sources. We are just interested
// in if they have the same settings.
return auto_detect_ == other.auto_detect_ &&
pac_url_ == other.pac_url_ &&
pac_mandatory_ == other.pac_mandatory_ &&
......@@ -249,6 +252,9 @@ Value* ProxyConfig::ToValue() const {
}
}
// Output the source.
dict->SetString("source", ProxyConfigSourceToString(source_));
return dict;
}
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -11,6 +11,7 @@
#include "googleurl/src/gurl.h"
#include "net/base/net_export.h"
#include "net/proxy/proxy_bypass_rules.h"
#include "net/proxy/proxy_config_source.h"
#include "net/proxy/proxy_server.h"
namespace base {
......@@ -53,7 +54,7 @@ class NET_EXPORT ProxyConfig {
}
// Sets |result| with the proxy to use for |url| based on the current rules.
void Apply(const GURL& url, ProxyInfo* result);
void Apply(const GURL& url, ProxyInfo* result) const;
// Parses the rules from a string, indicating which proxies to use.
//
......@@ -122,7 +123,8 @@ class NET_EXPORT ProxyConfig {
void set_id(ID id) { id_ = id; }
bool is_valid() const { return id_ != kInvalidConfigID; }
// Returns true if the given config is equivalent to this config.
// Returns true if the given config is equivalent to this config. The
// comparison ignores differences in |id()| and |source()|.
bool Equals(const ProxyConfig& other) const;
// Returns true if this config contains any "automatic" settings. See the
......@@ -171,6 +173,14 @@ class NET_EXPORT ProxyConfig {
return auto_detect_;
}
void set_source(ProxyConfigSource source) {
source_ = source;
}
ProxyConfigSource source() const {
return source_;
}
// Helpers to construct some common proxy configurations.
static ProxyConfig CreateDirect() {
......@@ -205,6 +215,9 @@ class NET_EXPORT ProxyConfig {
// Manual proxy settings.
ProxyRules proxy_rules_;
// Source of proxy settings.
ProxyConfigSource source_;
ID id_;
};
......
......@@ -320,8 +320,8 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter {
return task_runner_;
}
virtual const char* GetDataSource() OVERRIDE {
return "gconf";
virtual ProxyConfigSource GetConfigSource() OVERRIDE {
return PROXY_CONFIG_SOURCE_GCONF;
}
virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
......@@ -637,8 +637,8 @@ class SettingGetterImplGSettings
return task_runner_;
}
virtual const char* GetDataSource() OVERRIDE {
return "gsettings";
virtual ProxyConfigSource GetConfigSource() OVERRIDE {
return PROXY_CONFIG_SOURCE_GSETTINGS;
}
virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
......@@ -1045,8 +1045,8 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
NOTREACHED();
}
virtual const char* GetDataSource() OVERRIDE {
return "KDE";
virtual ProxyConfigSource GetConfigSource() OVERRIDE {
return PROXY_CONFIG_SOURCE_KDE;
}
virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
......@@ -1634,8 +1634,9 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
setting_getter_->Init(glib_thread_task_runner, file_loop) &&
GetConfigFromSettings(&cached_config_)) {
cached_config_.set_id(1); // Mark it as valid.
cached_config_.set_source(setting_getter_->GetConfigSource());
VLOG(1) << "Obtained proxy settings from "
<< setting_getter_->GetDataSource();
<< ProxyConfigSourceToString(cached_config_.source());
// If gconf proxy mode is "none", meaning direct, then we take
// that to be a valid config and will not check environment
......@@ -1675,6 +1676,7 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
// Consulting environment variables doesn't need to be done from the
// default glib main loop, but it's a tiny enough amount of work.
if (GetConfigFromEnv(&cached_config_)) {
cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV);
cached_config_.set_id(1); // Mark it as valid.
VLOG(1) << "Obtained proxy settings from environment variables";
}
......@@ -1708,8 +1710,12 @@ ProxyConfigService::ConfigAvailability
// Simply return the last proxy configuration that glib_default_loop
// notified us of.
*config = cached_config_.is_valid() ?
cached_config_ : ProxyConfig::CreateDirect();
if (cached_config_.is_valid()) {
*config = cached_config_;
} else {
*config = ProxyConfig::CreateDirect();
config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
}
// We return CONFIG_VALID to indicate that *config was filled in. It is always
// going to be available since we initialized eagerly on the UI thread.
......
......@@ -68,9 +68,8 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceLinux : public ProxyConfigService {
// Returns NULL if it does not matter.
virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() = 0;
// Returns the data source's name (e.g. "gconf", "gsettings", "KDE",
// "test"). Used only for diagnostic purposes (e.g. VLOG(1) etc.).
virtual const char* GetDataSource() = 0;
// Returns the source of proxy settings.
virtual ProxyConfigSource GetConfigSource() = 0;
// These are all the values that can be fetched. We used to just use the
// corresponding paths in gconf for these, but gconf is now obsolete and
......
......@@ -191,8 +191,8 @@ class MockSettingGetter
return NULL;
}
virtual const char* GetDataSource() OVERRIDE {
return "test";
virtual ProxyConfigSource GetConfigSource() OVERRIDE {
return PROXY_CONFIG_SOURCE_TEST;
}
virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
......
......@@ -154,6 +154,9 @@ void GetCurrentProxyConfig(ProxyConfig* config) {
false)) {
config->proxy_rules().bypass_rules.AddRuleToBypassLocal();
}
// Source
config->set_source(PROXY_CONFIG_SOURCE_SYSTEM);
}
} // namespace
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -159,6 +159,7 @@ void ProxyConfigServiceWin::GetCurrentProxyConfig(ProxyConfig* config) {
LOG(ERROR) << "WinHttpGetIEProxyConfigForCurrentUser failed: " <<
GetLastError();
*config = ProxyConfig::CreateDirect();
config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
return;
}
SetFromIEConfig(config, ie_config);
......@@ -187,6 +188,7 @@ void ProxyConfigServiceWin::SetFromIEConfig(
}
if (ie_config.lpszAutoConfigUrl)
config->set_pac_url(GURL(ie_config.lpszAutoConfigUrl));
config->set_source(PROXY_CONFIG_SOURCE_SYSTEM);
}
} // namespace net
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -196,6 +196,7 @@ TEST(ProxyConfigServiceWinTest, SetFromIEConfig) {
EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
EXPECT_EQ(tests[i].pac_url, config.pac_url());
EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
EXPECT_EQ(PROXY_CONFIG_SOURCE_SYSTEM, config.source());
}
}
......
// Copyright (c) 2012 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_source.h"
#include "base/basictypes.h"
#include "base/logging.h"
namespace net {
namespace {
const char* kSourceNames[] = {
"UNKNOWN",
"SYSTEM",
"SYSTEM FAILED",
"GCONF",
"GSETTINGS",
"KDE",
"ENV",
"CUSTOM",
"TEST"
};
COMPILE_ASSERT(ARRAYSIZE_UNSAFE(kSourceNames) == NUM_PROXY_CONFIG_SOURCES,
source_names_incorrect_size);
} // namespace
const char* ProxyConfigSourceToString(ProxyConfigSource source) {
DCHECK_GT(NUM_PROXY_CONFIG_SOURCES, source);
return kSourceNames[source];
}
} // namespace net
// Copyright (c) 2012 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_SOURCE_H_
#define NET_PROXY_PROXY_CONFIG_SOURCE_H_
#pragma once
namespace net {
// Source of the configuration settings encapsulated in a ProxyConfig object.
// The source information is used for determining how credentials are used and
// for logging. When adding new values, remember to add a string to
// kSourceNames[] in proxy_config_source.cc.
enum ProxyConfigSource {
PROXY_CONFIG_SOURCE_UNKNOWN, // The source hasn't been set.
PROXY_CONFIG_SOURCE_SYSTEM, // System settings (Win/Mac).
PROXY_CONFIG_SOURCE_SYSTEM_FAILED, // Default settings after failure to
// determine system settings.
PROXY_CONFIG_SOURCE_GCONF, // GConf (Linux)
PROXY_CONFIG_SOURCE_GSETTINGS, // GSettings (Linux).
PROXY_CONFIG_SOURCE_KDE, // KDE (Linux).
PROXY_CONFIG_SOURCE_ENV, // Environment variables.
PROXY_CONFIG_SOURCE_CUSTOM, // Custom settings local to the
// application (command line,
// extensions, application
// specific preferences, etc.)
PROXY_CONFIG_SOURCE_TEST, // Test settings.
NUM_PROXY_CONFIG_SOURCES
};
// Returns a textual representation of the source.
const char* ProxyConfigSourceToString(ProxyConfigSource source);
} // namespace net
#endif // NET_PROXY_PROXY_CONFIG_SOURCE_H_
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -251,6 +251,33 @@ TEST(ProxyConfigTest, ParseProxyRules) {
}
}
TEST(ProxyConfigTest, ProxyRulesSetBypassFlag) {
// Test whether the did_bypass_proxy() flag is set in proxy info correctly.
ProxyConfig::ProxyRules rules;
ProxyInfo result;
rules.ParseFromString("http=httpproxy:80");
rules.bypass_rules.AddRuleFromString(".com");
rules.Apply(GURL("http://example.com"), &result);
EXPECT_TRUE(result.is_direct_only());
EXPECT_TRUE(result.did_bypass_proxy());
rules.Apply(GURL("http://example.org"), &result);
EXPECT_FALSE(result.is_direct());
EXPECT_FALSE(result.did_bypass_proxy());
// Try with reversed bypass rules.
rules.reverse_bypass = true;
rules.Apply(GURL("http://example.org"), &result);
EXPECT_TRUE(result.is_direct_only());
EXPECT_TRUE(result.did_bypass_proxy());
rules.Apply(GURL("http://example.com"), &result);
EXPECT_FALSE(result.is_direct());
EXPECT_FALSE(result.did_bypass_proxy());
}
} // namespace
} // namespace net
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -8,7 +8,11 @@
namespace net {
ProxyInfo::ProxyInfo() : config_id_(ProxyConfig::kInvalidConfigID) {
ProxyInfo::ProxyInfo()
: config_id_(ProxyConfig::kInvalidConfigID),
config_source_(PROXY_CONFIG_SOURCE_UNKNOWN),
did_bypass_proxy_(false),
did_use_pac_script_(false) {
}
ProxyInfo::~ProxyInfo() {
......@@ -17,21 +21,30 @@ ProxyInfo::~ProxyInfo() {
void ProxyInfo::Use(const ProxyInfo& other) {
proxy_list_ = other.proxy_list_;
proxy_retry_info_ = other.proxy_retry_info_;
config_id_ = other.config_id_;
config_source_ = other.config_source_;
did_bypass_proxy_ = other.did_bypass_proxy_;
did_use_pac_script_ = other.did_use_pac_script_;
}
void ProxyInfo::UseDirect() {
Reset();
proxy_list_.SetSingleProxyServer(ProxyServer::Direct());
proxy_retry_info_.clear();
}
void ProxyInfo::UseDirectWithBypassedProxy() {
UseDirect();
did_bypass_proxy_ = true;
}
void ProxyInfo::UseNamedProxy(const std::string& proxy_uri_list) {
Reset();
proxy_list_.Set(proxy_uri_list);
proxy_retry_info_.clear();
}
void ProxyInfo::UseProxyServer(const ProxyServer& proxy_server) {
Reset();
proxy_list_.SetSingleProxyServer(proxy_server);
proxy_retry_info_.clear();
}
std::string ProxyInfo::ToPacString() const {
......@@ -51,4 +64,13 @@ void ProxyInfo::RemoveProxiesWithoutScheme(int scheme_bit_field) {
proxy_list_.RemoveProxiesWithoutScheme(scheme_bit_field);
}
void ProxyInfo::Reset() {
proxy_list_.Clear();
proxy_retry_info_.clear();
config_id_ = ProxyConfig::kInvalidConfigID;
config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN;
did_bypass_proxy_ = false;
did_use_pac_script_ = false;
}
} // namespace net
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -30,6 +30,10 @@ class NET_EXPORT ProxyInfo {
// Uses a direct connection.
void UseDirect();
// Uses a direct connection. did_bypass_proxy() will return true to indicate
// that the direct connection is the result of configured proxy bypass rules.
void UseDirectWithBypassedProxy();
// Uses a specific proxy server, of the form:
// proxy-uri = [<scheme> "://"] <hostname> [":" <port>]
// This may optionally be a semi-colon delimited list of <proxy-uri>.
......@@ -52,6 +56,10 @@ class NET_EXPORT ProxyInfo {
return proxy_list_.Get().is_direct();
}
bool is_direct_only() const {
return is_direct() && proxy_list_.size() == 1 && proxy_retry_info_.empty();
}
// Returns true if the first valid proxy server is an https proxy.
bool is_https() const {
if (is_empty())
......@@ -78,10 +86,24 @@ class NET_EXPORT ProxyInfo {
return proxy_list_.IsEmpty();
}
// Returns true if this proxy resolution is using a direct connection due to
// proxy bypass rules.
bool did_bypass_proxy() const {
return did_bypass_proxy_;
}
// Returns true if the proxy resolution was done using a PAC script.
bool did_use_pac_script() const {
return did_use_pac_script_;
}
// Returns the first valid proxy server. is_empty() must be false to be able
// to call this function.
const ProxyServer& proxy_server() const { return proxy_list_.Get(); }
// Returns the source for configuration settings used for proxy resolution.
ProxyConfigSource config_source() const { return config_source_; }
// See description in ProxyList::ToPacString().
std::string ToPacString() const;
......@@ -103,6 +125,9 @@ class NET_EXPORT ProxyInfo {
return proxy_retry_info_;
}
// Reset proxy and config settings.
void Reset();
// The ordered list of proxy servers (including DIRECT attempts) remaining to
// try. If proxy_list_ is empty, then there is nothing left to fall back to.
ProxyList proxy_list_;
......@@ -112,6 +137,15 @@ class NET_EXPORT ProxyInfo {
// This value identifies the proxy config used to initialize this object.
ProxyConfig::ID config_id_;
// The source of the proxy settings used,
ProxyConfigSource config_source_;
// Whether the proxy result represent a proxy bypass.
bool did_bypass_proxy_;
// Whether we used a PAC script for resolving the proxy.
bool did_use_pac_script_;
};
} // namespace net
......
// Copyright (c) 2012 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"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
TEST(ProxyInfoTest, ProxyInfoIsDirectOnly) {
// Test the is_direct_only() predicate.
ProxyInfo info;
// An empty ProxyInfo is not considered direct.
EXPECT_FALSE(info.is_direct_only());
info.UseDirect();
EXPECT_TRUE(info.is_direct_only());
info.UsePacString("DIRECT");
EXPECT_TRUE(info.is_direct_only());
info.UsePacString("PROXY myproxy:80");
EXPECT_FALSE(info.is_direct_only());
info.UsePacString("DIRECT; PROXY myproxy:80");
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.is_direct_only());
info.UsePacString("PROXY myproxy:80; DIRECT");
EXPECT_FALSE(info.is_direct());
EXPECT_FALSE(info.is_direct_only());
// After falling back to direct, we shouldn't consider it DIRECT only.
EXPECT_TRUE(info.Fallback(BoundNetLog()));
EXPECT_TRUE(info.is_direct());
EXPECT_FALSE(info.is_direct_only());
}
} // namespace
} // namespace net
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -77,10 +77,18 @@ void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) {
}
}
void ProxyList::Clear() {
proxies_.clear();
}
bool ProxyList::IsEmpty() const {
return proxies_.empty();
}
size_t ProxyList::size() const {
return proxies_.size();
}
const ProxyServer& ProxyList::Get() const {
DCHECK(!proxies_.empty());
return proxies_[0];
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -40,9 +40,15 @@ class NET_EXPORT_PRIVATE ProxyList {
// |scheme_bit_field| is a bunch of ProxyServer::Scheme bitwise ORed together.
void RemoveProxiesWithoutScheme(int scheme_bit_field);
// Clear the proxy list.
void Clear();
// Returns true if there is nothing left in the ProxyList.
bool IsEmpty() const;
// Returns the number of proxy servers in this list.
size_t size() const;
// Returns the first proxy server in the list. It is only valid to call
// this if !IsEmpty().
const ProxyServer& Get() const;
......
......@@ -167,6 +167,7 @@ class ProxyConfigServiceDirect : public ProxyConfigService {
virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
OVERRIDE {
*config = ProxyConfig::CreateDirect();
config->set_source(PROXY_CONFIG_SOURCE_UNKNOWN);
return CONFIG_VALID;
}
};
......@@ -802,6 +803,7 @@ class ProxyService::PacRequest
url_(url),
resolve_job_(NULL),
config_id_(ProxyConfig::kInvalidConfigID),
config_source_(PROXY_CONFIG_SOURCE_UNKNOWN),
net_log_(net_log) {
DCHECK(!user_callback.is_null());
}
......@@ -814,6 +816,7 @@ class ProxyService::PacRequest
DCHECK(service_->config_.is_valid());
config_id_ = service_->config_.id();
config_source_ = service_->config_.source();
return resolver()->GetProxyForURL(
url_, results_,
......@@ -869,10 +872,13 @@ class ProxyService::PacRequest
// Make a note in the results which configuration was in use at the
// time of the resolve.
results_->config_id_ = config_id_;
results_->config_source_ = config_source_;
results_->did_use_pac_script_ = true;
// Reset the state associated with in-progress-resolve.
resolve_job_ = NULL;
config_id_ = ProxyConfig::kInvalidConfigID;
config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN;
return service_->DidFinishResolvingProxy(results_, result_code, net_log_);
}
......@@ -914,6 +920,7 @@ class ProxyService::PacRequest
GURL url_;
ProxyResolver::RequestHandle resolve_job_;
ProxyConfig::ID config_id_; // The config id when the resolve was started.
ProxyConfigSource config_source_; // The source of proxy settings.
BoundNetLog net_log_;
};
......@@ -1116,6 +1123,7 @@ int ProxyService::TryToCompleteSynchronously(const GURL& url,
// Use the manual proxy settings.
config_.proxy_rules().Apply(url, result);
result->config_source_ = config_.source();
result->config_id_ = config_.id();
return OK;
}
......@@ -1237,6 +1245,7 @@ void ProxyService::OnInitProxyResolverComplete(int result) {
// TODO(eroman): Make this ID unique in the case where configuration changed
// due to ProxyScriptDeciderPoller.
config_.set_id(fetched_config_.id());
config_.set_source(fetched_config_.source());
// Resume any requests which we had to defer until the PAC script was
// downloaded.
......
......@@ -216,6 +216,7 @@ TEST_F(ProxyServiceTest, PAC) {
EXPECT_EQ(OK, callback.WaitForResult());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
EXPECT_TRUE(info.did_use_pac_script());
// Check the NetLog was filled correctly.
CapturingNetLog::CapturedEntryList entries;
......@@ -292,6 +293,7 @@ TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
EXPECT_EQ(OK, callback1.WaitForResult());
EXPECT_FALSE(info.is_direct());
EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
EXPECT_TRUE(info.did_use_pac_script());
// Now, imagine that connecting to foopy:8080 fails: there is nothing
// left to fallback to, since our proxy list was NOT terminated by
......@@ -382,6 +384,36 @@ TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
EXPECT_TRUE(info.is_empty());
}
TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
// Test whether the ProxyConfigSource set by the ProxyConfigService is applied
// to ProxyInfo after the proxy is resolved via a PAC script.
ProxyConfig config =
ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
config.set_source(PROXY_CONFIG_SOURCE_TEST);
MockProxyConfigService* config_service = new MockProxyConfigService(config);
MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
ProxyService service(config_service, resolver, NULL);
// Resolve something.
GURL url("http://www.google.com/");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(
url, &info, callback.callback(), NULL, BoundNetLog());
ASSERT_EQ(ERR_IO_PENDING, rv);
resolver->pending_set_pac_script_request()->CompleteNow(OK);
ASSERT_EQ(1u, resolver->pending_requests().size());
// Set the result in proxy resolver.
resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
resolver->pending_requests()[0]->CompleteNow(OK);
EXPECT_EQ(OK, callback.WaitForResult());
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
EXPECT_TRUE(info.did_use_pac_script());
}
TEST_F(ProxyServiceTest, ProxyResolverFails) {
// Test what happens when the ProxyResolver fails. The download and setting
// of the PAC script have already succeeded, so this corresponds with a
......@@ -1120,6 +1152,56 @@ TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
}
}
TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
// Test that the proxy config source is set correctly when resolving proxies
// using manual proxy rules. Namely, the config source should only be set if
// any of the rules were applied.
{
ProxyConfig config;
config.set_source(PROXY_CONFIG_SOURCE_TEST);
config.proxy_rules().ParseFromString("https=foopy2:8080");
ProxyService service(
new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
GURL test_url("http://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
BoundNetLog());
ASSERT_EQ(OK, rv);
// Should be SOURCE_TEST, even if there are no HTTP proxies configured.
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
}
{
ProxyConfig config;
config.set_source(PROXY_CONFIG_SOURCE_TEST);
config.proxy_rules().ParseFromString("https=foopy2:8080");
ProxyService service(
new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
GURL test_url("https://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
BoundNetLog());
ASSERT_EQ(OK, rv);
// Used the HTTPS proxy. So source should be TEST.
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
}
{
ProxyConfig config;
config.set_source(PROXY_CONFIG_SOURCE_TEST);
ProxyService service(
new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
GURL test_url("http://www.google.com");
ProxyInfo info;
TestCompletionCallback callback;
int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
BoundNetLog());
ASSERT_EQ(OK, rv);
// ProxyConfig is empty. Source should still be TEST.
EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
}
}
// If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
// fall back to the SOCKS proxy.
TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment