diff options
author | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-24 17:34:08 +0000 |
---|---|---|
committer | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-24 17:34:08 +0000 |
commit | f50278cd30e63f2deddd6989a93ed2c28134bcd5 (patch) | |
tree | 7e7630856bdf77cb96b443eb9f6f65a75b990ec7 /chrome | |
parent | a60aca40a6f65cdbe2533ebf2b2a4caf885a6c41 (diff) | |
download | chromium_src-f50278cd30e63f2deddd6989a93ed2c28134bcd5.zip chromium_src-f50278cd30e63f2deddd6989a93ed2c28134bcd5.tar.gz chromium_src-f50278cd30e63f2deddd6989a93ed2c28134bcd5.tar.bz2 |
chromeos: 1st draft of ProxyConfigService for chromeos
what this cl is:
- a REALLY bare skeleton implementation of ProxyConfigService for chromeos (lots of design details remain to be worked out on the chromeos side, but i needed to get something basic up)
- focused on getting chrome part correct, extracting design flow and implementation from linux variant that are relevant to chromeos, e.g.:
- provide access of ProxyConfigService interface on IO thread
- provide methods on UI thread for UI to read/modify proxy config (like linux's GConf notifications on UI thread)
- fetch initial config on UI thread (this is not absolutely necessary for chromeos, 'cos i don't use GConf, but i just follow linux for now)
- however, the class is RefCountedThreadSafe (so that both net::ProxyService and DOMUI can access it), and the code resides in chrome/browser/chromeos dir instead of net/proxy.
- design details are in .h files
- initial config is hardcoded as pac script and loaded as owner (TODO: load this from cros settings persisted on chromeos device)
- this should work like the current chromeos session manager which sets the auto-proxy environment variable in login script to the same pac script
- implement an augmented analogue to net::ProxyConfig to hold actual proxy config and UI settings (e.g. source and readonly attributes)
- backend uses this as the main proxy config, and only converts it to net:::ProxyConfig for network stack on the IO thread in net::ProxyService::GetLatestProxyConfig.
- UI methods also use this structure
- provide methods to get and set configs from UI thread
- UI can use dom_ui->GetProfile()->GetChromeOSProxyConfigServiceImpl() to access these methods on the UI thread
- these methods are by no means final
- i only added them here to verify the design flow that modifications can be made from UI thread and picked up by IO thread.
- david and i will improve or modify them to whatever works best for frontend and backend.
- unittest that tests most functionalities: socks and bypass_rules will be enabled in a later cl.
TODOs after this cl:
- work with UI, load initial config as owner from cros settings
- implement policy mechanism, merge it with owner during initial load and modifications
- persist proxy settings
- etc etc etc
BUG=chromium-os:5127
TEST=nothing yet.
Review URL: http://codereview.chromium.org/3047052
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57204 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/chromeos/proxy_config_service.h | 42 | ||||
-rw-r--r-- | chrome/browser/chromeos/proxy_config_service_impl.cc | 305 | ||||
-rw-r--r-- | chrome/browser/chromeos/proxy_config_service_impl.h | 191 | ||||
-rw-r--r-- | chrome/browser/chromeos/proxy_config_service_impl_unittest.cc | 539 | ||||
-rw-r--r-- | chrome/browser/net/chrome_url_request_context.cc | 17 | ||||
-rw-r--r-- | chrome/browser/profile.cc | 7 | ||||
-rw-r--r-- | chrome/browser/profile.h | 13 | ||||
-rw-r--r-- | chrome/browser/profile_impl.cc | 13 | ||||
-rw-r--r-- | chrome/browser/profile_impl.h | 7 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 3 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/test/testing_profile.h | 7 |
12 files changed, 1140 insertions, 5 deletions
diff --git a/chrome/browser/chromeos/proxy_config_service.h b/chrome/browser/chromeos/proxy_config_service.h new file mode 100644 index 0000000..cabf8bf --- /dev/null +++ b/chrome/browser/chromeos/proxy_config_service.h @@ -0,0 +1,42 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_H_ +#define CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_H_ +#pragma once + +#include "chrome/browser/chromeos/proxy_config_service_impl.h" + +namespace chromeos { + +// Wrapper class for the RefCountedThreadSafe chromeos::ProxyConfigServiceImpl +// that forwards net::ProxyConfigService interface to the actual implementation, +// instantiated in +// chrome/browser/net/chrome_url_request_context.cc::CreateProxyConfigService. +class ProxyConfigService : public net::ProxyConfigService { + public: + explicit ProxyConfigService(const scoped_refptr<ProxyConfigServiceImpl>& impl) + : impl_(impl) {} + virtual ~ProxyConfigService() {} + + // ProxyConfigService methods. Called from IO thread. + virtual void AddObserver(Observer* observer) { + impl_->AddObserver(observer); + } + virtual void RemoveObserver(Observer* observer) { + impl_->RemoveObserver(observer); + } + virtual bool GetLatestProxyConfig(net::ProxyConfig* config) { + return impl_->IOGetProxyConfig(config); + } + + private: + scoped_refptr<ProxyConfigServiceImpl> impl_; + + DISALLOW_COPY_AND_ASSIGN(ProxyConfigService); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_H_ diff --git a/chrome/browser/chromeos/proxy_config_service_impl.cc b/chrome/browser/chromeos/proxy_config_service_impl.cc new file mode 100644 index 0000000..ad05e43 --- /dev/null +++ b/chrome/browser/chromeos/proxy_config_service_impl.cc @@ -0,0 +1,305 @@ +// Copyright (c) 2010 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 "chrome/browser/chromeos/proxy_config_service_impl.h" + +#include <ostream> + +#include "base/logging.h" +#include "base/string_util.h" +#include "base/task.h" +#include "base/values.h" +#include "chrome/browser/chrome_thread.h" + +namespace chromeos { + +namespace { + +const char* SourceToString(ProxyConfigServiceImpl::ProxyConfig::Source source) { + switch (source) { + case ProxyConfigServiceImpl::ProxyConfig::SOURCE_NONE: + return "SOURCE_NONE"; + case ProxyConfigServiceImpl::ProxyConfig::SOURCE_POLICY: + return "SOURCE_POLICY"; + case ProxyConfigServiceImpl::ProxyConfig::SOURCE_OWNER: + return "SOURCE_OWNER"; + } + NOTREACHED() << "Unrecognized source type"; + return ""; +} + +std::ostream& operator<<(std::ostream& out, + const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) { + out << " " << SourceToString(proxy.source) << "\n" + << " server: " << (proxy.server.is_valid() ? proxy.server.ToURI() : "") + << "\n"; + return out; +} + +std::ostream& operator<<(std::ostream& out, + const ProxyConfigServiceImpl::ProxyConfig& config) { + switch (config.mode) { + case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT: + out << "Direct connection:\n " + << SourceToString(config.automatic_proxy.source) << "\n"; + break; + case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT: + out << "Auto detection:\n " + << SourceToString(config.automatic_proxy.source) << "\n"; + break; + case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT: + out << "Custom PAC script:\n " + << SourceToString(config.automatic_proxy.source) + << "\n PAC: " << config.automatic_proxy.pac_url << "\n"; + break; + case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY: + out << "Single proxy:\n" << config.single_proxy; + break; + case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME: + out << "HTTP proxy: " << config.http_proxy; + out << "HTTPS proxy: " << config.https_proxy; + out << "FTP proxy: " << config.ftp_proxy; + out << "SOCKS proxy: " << config.socks_proxy; + break; + default: + NOTREACHED() << "Unrecognized proxy config mode"; + break; + } + if (config.mode == ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY || + config.mode == + ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) { + out << "Bypass list: "; + if (config.bypass_rules.rules().empty()) { + out << "[None]"; + } else { + const net::ProxyBypassRules& bypass_rules = config.bypass_rules; + net::ProxyBypassRules::RuleList::const_iterator it; + for (it = bypass_rules.rules().begin(); + it != bypass_rules.rules().end(); ++it) { + out << "\n " << (*it)->ToString(); + } + } + } + return out; +} + +std::string ProxyConfigToString( + const ProxyConfigServiceImpl::ProxyConfig& proxy_config) { + std::ostringstream stream; + stream << proxy_config; + return stream.str(); +} + +} // namespace + +//-------------- ProxyConfigServiceImpl::ProxyConfig methods ------------------- + +bool ProxyConfigServiceImpl::ProxyConfig::Setting::CanBeWrittenByUser( + bool user_is_owner) { + // Setting can only be written by user if user is owner and setting is not + // from policy. + return user_is_owner && source != ProxyConfig::SOURCE_POLICY; +} + +void ProxyConfigServiceImpl::ProxyConfig::ConvertToNetProxyConfig( + net::ProxyConfig* net_config) { + switch (mode) { + case MODE_DIRECT: + *net_config = net::ProxyConfig::CreateDirect(); + break; + case MODE_AUTO_DETECT: + *net_config = net::ProxyConfig::CreateAutoDetect(); + break; + case MODE_PAC_SCRIPT: + *net_config = net::ProxyConfig::CreateFromCustomPacURL( + automatic_proxy.pac_url); + break; + case MODE_SINGLE_PROXY: + *net_config = net::ProxyConfig(); + net_config->proxy_rules().type = + net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + net_config->proxy_rules().single_proxy = single_proxy.server; + net_config->proxy_rules().bypass_rules = bypass_rules; + break; + case MODE_PROXY_PER_SCHEME: + *net_config = net::ProxyConfig(); + net_config->proxy_rules().type = + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + net_config->proxy_rules().proxy_for_http = http_proxy.server; + net_config->proxy_rules().proxy_for_https = https_proxy.server; + net_config->proxy_rules().proxy_for_ftp = ftp_proxy.server; + net_config->proxy_rules().socks_proxy = socks_proxy.server; + net_config->proxy_rules().bypass_rules = bypass_rules; + break; + default: + NOTREACHED() << "Unrecognized proxy config mode"; + break; + } +} + +std::string ProxyConfigServiceImpl::ProxyConfig::ToString() const { + return ProxyConfigToString(*this); +} + +//------------------- ProxyConfigServiceImpl: public methods ------------------- + +ProxyConfigServiceImpl::ProxyConfigServiceImpl() { + // Fetch and cache proxy config from cros settings persisted on device. + // TODO(kuan): retrieve config from policy and owner and merge them + // for now, hardcode it as AUTO_DETECT and it'll pick up the PAC script set in + // chromeos environment. + cached_config_.mode = ProxyConfig::MODE_AUTO_DETECT; + cached_config_.automatic_proxy.source = ProxyConfig::SOURCE_OWNER; + + // Update the thread-private copy in |reference_config_| as well. + reference_config_ = cached_config_; +} + +ProxyConfigServiceImpl::ProxyConfigServiceImpl(const ProxyConfig& init_config) { + cached_config_ = init_config; + // Update the thread-private copy in |reference_config_| as well. + reference_config_ = cached_config_; +} + +ProxyConfigServiceImpl::~ProxyConfigServiceImpl() { +} + +void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + // Simply returns the copy on the UI thread. + *config = reference_config_; +} + +void ProxyConfigServiceImpl::UISetProxyConfigToDirect() { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + reference_config_.mode = ProxyConfig::MODE_DIRECT; + OnUISetProxyConfig(); +} + +void ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + reference_config_.mode = ProxyConfig::MODE_AUTO_DETECT; + OnUISetProxyConfig(); +} + +void ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& url) { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + reference_config_.mode = ProxyConfig::MODE_PAC_SCRIPT; + reference_config_.automatic_proxy.pac_url = url; + OnUISetProxyConfig(); +} + +void ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy( + const net::ProxyServer& server) { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + reference_config_.mode = ProxyConfig::MODE_SINGLE_PROXY; + reference_config_.single_proxy.server = server; + OnUISetProxyConfig(); +} + +void ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme( + const std::string& scheme, const net::ProxyServer& server) { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + ProxyConfig::ManualProxy* proxy = NULL; + if (scheme == "http") + proxy = &reference_config_.http_proxy; + else if (scheme == "https") + proxy = &reference_config_.https_proxy; + else if (scheme == "ftp") + proxy = &reference_config_.ftp_proxy; + else if (scheme == "socks") + proxy = &reference_config_.socks_proxy; + else + NOTREACHED() << "Unrecognized scheme for setting proxy config"; + if (proxy) { + reference_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME; + proxy->server = server; + OnUISetProxyConfig(); + } +} + +void ProxyConfigServiceImpl::UISetProxyConfigBypassRules( + const net::ProxyBypassRules& bypass_rules) { + // Should be called from UI thread. + CheckCurrentlyOnUIThread(); + DCHECK(reference_config_.mode == ProxyConfig::MODE_SINGLE_PROXY || + reference_config_.mode == ProxyConfig::MODE_PROXY_PER_SCHEME); + if (reference_config_.mode == ProxyConfig::MODE_SINGLE_PROXY || + reference_config_.mode == ProxyConfig::MODE_PROXY_PER_SCHEME) { + reference_config_.bypass_rules = bypass_rules; + OnUISetProxyConfig(); + } +} + +void ProxyConfigServiceImpl::AddObserver( + net::ProxyConfigService::Observer* observer) { + // Should be called from IO thread. + CheckCurrentlyOnIOThread(); + observers_.AddObserver(observer); +} + +void ProxyConfigServiceImpl::RemoveObserver( + net::ProxyConfigService::Observer* observer) { + // Should be called from IO thread. + CheckCurrentlyOnIOThread(); + observers_.RemoveObserver(observer); +} + +bool ProxyConfigServiceImpl::IOGetProxyConfig(net::ProxyConfig* net_config) { + // Should be called from IO thread. + CheckCurrentlyOnIOThread(); + + // Simply return the last cached proxy configuration. + cached_config_.ConvertToNetProxyConfig(net_config); + + // We return true to indicate that *config was filled in. It is always + // going to be available since we initialized eagerly on the UI thread. + // TODO(kuan): do lazy initialization instead, so we no longer need + // to construct ProxyConfigServiceImpl on the UI thread. + // In which case, we may return false here. + return true; +} + +//------------------ ProxyConfigServiceImpl: private methods ------------------- + +void ProxyConfigServiceImpl::OnUISetProxyConfig() { + // Posts a task to IO thread with the new config, so it can update + // |cached_config_|. + Task* task = NewRunnableMethod(this, + &ProxyConfigServiceImpl::IOSetProxyConfig, reference_config_); + if (!ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, task)) { + LOG(INFO) << "Couldn't post task to IO thread to set new proxy config"; + delete task; + } + + // TODO(kuan): write new config out to cros settings for persistence. +} + +void ProxyConfigServiceImpl::CheckCurrentlyOnIOThread() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); +} + +void ProxyConfigServiceImpl::CheckCurrentlyOnUIThread() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); +} + +void ProxyConfigServiceImpl::IOSetProxyConfig(const ProxyConfig& new_config) { + // This is called on the IO thread (posted from UI thread). + CheckCurrentlyOnIOThread(); + LOG(INFO) << "Proxy configuration changed"; + cached_config_ = new_config; + // Notify observers of new proxy config. + net::ProxyConfig net_config; + cached_config_.ConvertToNetProxyConfig(&net_config); + FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, + OnProxyConfigChanged(net_config)); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/proxy_config_service_impl.h b/chrome/browser/chromeos/proxy_config_service_impl.h new file mode 100644 index 0000000..c22f1a5 --- /dev/null +++ b/chrome/browser/chromeos/proxy_config_service_impl.h @@ -0,0 +1,191 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_ +#define CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/observer_list.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_config_service.h" +#include "net/proxy/proxy_server.h" + +namespace chromeos { + +// Implementation of proxy config service for chromeos that: +// - is RefCountedThreadSafe +// - is wrapped by chromeos::ProxyConfigService which implements +// net::ProxyConfigService interface by fowarding the methods to this class +// - retrieves initial system proxy configuration from cros settings persisted +// on chromeos device +// - provides network stack with latest system proxy configuration for use on +// IO thread +// - provides UI with methods to retrieve and modify system proxy configuration +// on UI thread +// - TODO(kuan): persists proxy configuration settings on chromeos device using +// cros settings +class ProxyConfigServiceImpl + : public base::RefCountedThreadSafe<ProxyConfigServiceImpl> { + public: + // ProxyConfigServiceImpl is created on the UI thread in + // chrome/browser/net/chrome_url_request_context.cc::CreateProxyConfigService + // via ProfileImpl::GetChromeOSProxyConfigServiceImpl, and stored in Profile + // as a scoped_refptr (because it's RefCountedThreadSafe). + // + // Past that point, it can be accessed from the IO or UI threads. + // + // From the IO thread, it is accessed periodically through the wrapper class + // chromeos::ProxyConfigService via net::ProxyConfigService interface + // (GetLatestProxyConfig, AddObserver, RemoveObserver). + // + // From the UI thread, it is accessed via + // DOMUI::GetProfile::GetChromeOSProxyConfigServiceImpl to allow user to read + // or modify the proxy configuration via UIGetProxyConfig or + // UISetProxyConfigTo* respectively. + // The new modified proxy config is posted to the IO thread through + // SetNewProxyConfig(). We then notify observers on the IO thread of the + // configuration change. + + // In contrary to other platforms which simply use the systems' UI to allow + // users to configure proxies, we have to implement our own UI on the chromeos + // device. This requires extra and specific UI requirements that + // net::ProxyConfig does not suffice. So we create an augmented analog to + // net:ProxyConfig here to include and handle these UI requirements, e.g. + // - where configuration was picked up from - policy or owner + // - the read/write access of a proxy setting + // - may add more stuff later. + // This is then converted to the common net::ProxyConfig before being returned + // to ProxyService::GetLatestProxyConfig on the IO thread to be used on the + // network stack. + struct ProxyConfig { + // Specifies if proxy config is direct, auto-detect, using pac script, + // single-proxy, or proxy-per-scheme. + enum Mode { + MODE_DIRECT, + MODE_AUTO_DETECT, + MODE_PAC_SCRIPT, + MODE_SINGLE_PROXY, + MODE_PROXY_PER_SCHEME, + }; + + // Specifies where proxy configuration was picked up from. + enum Source { + SOURCE_NONE, // No default configuration. + SOURCE_POLICY, // Configuration is from policy. + SOURCE_OWNER, // Configuration is from owner. + }; + + struct Setting { + Setting() : source(SOURCE_NONE) {} + + Source source; + bool CanBeWrittenByUser(bool user_is_owner); + }; + + // Proxy setting for mode = direct or auto-detect or using pac script. + struct AutomaticProxy : public Setting { + GURL pac_url; // Set if proxy is using pac script. + }; + + // Proxy setting for mode = single-proxy or proxy-per-scheme. + struct ManualProxy : public Setting { + net::ProxyServer server; + }; + + ProxyConfig() : mode(MODE_DIRECT) {} + + // Converts |this| to net::ProxyConfig. + void ConvertToNetProxyConfig(net::ProxyConfig* net_config); + + // Creates a textual dump of the configuration. + std::string ToString() const; + + Mode mode; + + // Set if mode is MODE_DIRECT or MODE_AUTO_DETECT or MODE_PAC_SCRIPT. + AutomaticProxy automatic_proxy; + // Set if mode is MODE_SINGLE_PROXY. + ManualProxy single_proxy; + // Set if mode is MODE_PROXY_PER_SCHEME and has http proxy. + ManualProxy http_proxy; + // Set if mode is MODE_PROXY_PER_SCHEME and has https proxy. + ManualProxy https_proxy; + // Set if mode is MODE_PROXY_PER_SCHEME and has ftp proxy. + ManualProxy ftp_proxy; + // Set if mode is MODE_PROXY_PER_SCHEME and has socks proxy. + ManualProxy socks_proxy; + + // Exceptions for when not to use a proxy. + net::ProxyBypassRules bypass_rules; + }; + + // Usual constructor. + ProxyConfigServiceImpl(); + // Constructor for testing. + // |init_config| specifies the ProxyConfig to use for initialization. + explicit ProxyConfigServiceImpl(const ProxyConfig& init_config); + virtual ~ProxyConfigServiceImpl(); + + // Methods called on IO thread from wrapper class chromeos::ProxyConfigService + // as ProxyConfigService methods. + void AddObserver(net::ProxyConfigService::Observer* observer); + void RemoveObserver(net::ProxyConfigService::Observer* observer); + // Called from GetLatestProxyConfig. + bool IOGetProxyConfig(net::ProxyConfig* config); + + // Called from UI thread to retrieve proxy configuration in |config|. + void UIGetProxyConfig(ProxyConfig* config); + + // Called from UI thread to update proxy configuration for different modes. + void UISetProxyConfigToDirect(); + void UISetProxyConfigToAutoDetect(); + void UISetProxyConfigToPACScript(const GURL& url); + void UISetProxyConfigToSingleProxy(const net::ProxyServer& server); + void UISetProxyConfigToProxyPerScheme(const std::string& scheme, + const net::ProxyServer& server); + // Only valid for MODE_SINGLE_PROXY or MODE_PROXY_PER_SCHEME. + void UISetProxyConfigBypassRules(const net::ProxyBypassRules& bypass_rules); + + private: + friend class base::RefCountedThreadSafe<ProxyConfigServiceImpl>; + + // Called from UI thread from the various UISetProxyConfigTo* + void OnUISetProxyConfig(); + + // Posted from UI thread to IO thread to carry the new config information. + void IOSetProxyConfig(const ProxyConfig& new_config); + + // Checks that method is called on ChromeThread::IO thread. + void CheckCurrentlyOnIOThread(); + + // Checks that method is called on ChromeThread::UI thread. + void CheckCurrentlyOnUIThread(); + + // Data members. + + // Cached proxy configuration, to be converted to net::ProxyConfig and + // returned by IOGetProxyConfig. + // Initially populated from the UI thread, but afterwards only accessed from + // the IO thread. + ProxyConfig cached_config_; + + // Copy of the proxy configuration kept on the UI thread of the last seen + // proxy config, so as to avoid posting a call to SetNewProxyConfig when we + // are called by UI to set new proxy but the config has not actually changed. + ProxyConfig reference_config_; + + ObserverList<net::ProxyConfigService::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceImpl); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_ diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc new file mode 100644 index 0000000..0603947 --- /dev/null +++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc @@ -0,0 +1,539 @@ +// Copyright (c) 2010 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 "chrome/browser/chromeos/proxy_config_service_impl.h" + +#include <map> +#include <string> +#include <vector> + +#include "base/format_macros.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/browser/chrome_thread.h" +#include "net/proxy/proxy_config_service_common_unittest.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace chromeos { + +namespace { + +struct Input { // Fields of chromeos::ProxyConfigServiceImpl::ProxyConfig. + ProxyConfigServiceImpl::ProxyConfig::Mode mode; + const char* pac_url; + const char* single_uri; + const char* http_uri; + const char* https_uri; + const char* ftp_uri; + const char* socks_uri; + const char* bypass_rules; +}; + +// Builds an identifier for each test in an array. +#define TEST_DESC(desc) StringPrintf("at line %d <%s>", __LINE__, desc) + +// Shortcuts to declare enums within chromeos's ProxyConfig. +#define MK_MODE(mode) ProxyConfigServiceImpl::ProxyConfig::MODE_##mode +#define MK_SRC(src) ProxyConfigServiceImpl::ProxyConfig::SOURCE_##src + +// Inspired from net/proxy/proxy_config_service_linux_unittest.cc. +const struct { + // Short description to identify the test + std::string description; + + Input input; + + // Expected outputs from fields of net::ProxyConfig (via IO). + bool auto_detect; + GURL pac_url; + net::ProxyRulesExpectation proxy_rules; +} tests[] = { + { + TEST_DESC("No proxying"), + { // Input. + MK_MODE(DIRECT), // mode + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Empty(), // proxy_rules + }, + + { + TEST_DESC("Auto detect"), + { // Input. + MK_MODE(AUTO_DETECT), // mode + }, + + // Expected result. + true, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Empty(), // proxy_rules + }, + + { + TEST_DESC("Valid PAC URL"), + { // Input. + MK_MODE(PAC_SCRIPT), // mode + "http://wpad/wpad.dat", // pac_url + }, + + // Expected result. + false, // auto_detect + GURL("http://wpad/wpad.dat"), // pac_url + net::ProxyRulesExpectation::Empty(), // proxy_rules + }, + + { + TEST_DESC("Invalid PAC URL"), + { // Input. + MK_MODE(PAC_SCRIPT), // mode + "wpad.dat", // pac_url + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Empty(), // proxy_rules + }, + + { + TEST_DESC("Single-host in proxy list"), + { // Input. + MK_MODE(SINGLE_PROXY), // mode + NULL, // pac_url + "www.google.com", // single_uri + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "www.google.com:80", // single proxy + ""), // bypass rules + }, + + { + TEST_DESC("Single-host, different port"), + { // Input. + MK_MODE(SINGLE_PROXY), // mode + NULL, // pac_url + "www.google.com:99", // single_uri + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "www.google.com:99", // single + ""), // bypass rules + }, + + { + TEST_DESC("Tolerate a scheme"), + { // Input. + MK_MODE(SINGLE_PROXY), // mode + NULL, // pac_url + "http://www.google.com:99", // single_uri + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "www.google.com:99", // single proxy + ""), // bypass rules + }, + + { + TEST_DESC("Per-scheme proxy rules"), + { // Input. + MK_MODE(PROXY_PER_SCHEME), // mode + NULL, // pac_url + NULL, // single_uri + "www.google.com:80", "www.foo.com:110", "ftp.foo.com:121", // per-proto + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::PerScheme( // proxy_rules + "www.google.com:80", // http + "www.foo.com:110", // https + "ftp.foo.com:121", // ftp + ""), // bypass rules + }, + +// TODO(kuan): enable these. +#if defined(TO_ENABLE_SOON) + { + TEST_DESC("socks"), + { // Input. + MK_MODE(PROXY_PER_SCHEME), // mode + NULL, // pac_url + NULL, // single_uri + NULL, NULL, NULL, // per-proto proxies + "socks.com:888", // socks_uri + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "socks4://socks.com:888", // single proxy + ""), // bypass rules + }, + + { + TEST_DESC("socks5"), + { // Input. + NULL, // auto_proxy + "", // all_proxy + NULL, NULL, NULL, // per-proto proxies + "socks.com:888", "5", // SOCKS + NULL, // no_proxy + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "socks5://socks.com:888", // single proxy + ""), // bypass rules + ProxyConfigServiceImpl::READ_ONLY_MAIN, // readonly for owner + ProxyConfigServiceImpl::READ_ONLY_MAIN, // readonly for non-owner + }, + + { + TEST_DESC("socks default port"), + { // Input. + NULL, // auto_proxy + "", // all_proxy + NULL, NULL, NULL, // per-proto proxies + "socks.com", NULL, // SOCKS + NULL, // no_proxy + }, + + // Expected result. + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "socks4://socks.com:1080", // single proxy + ""), // bypass rules + }, + + { + TEST_DESC("bypass"), + { // Input. + MK_MODE(PROXY_PER_SCHEME), // mode + NULL, // pac_url + "www.google.com", // single_uri + NULL, NULL, NULL, NULL, // per-proto & socks proxies + ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8", // bypass_rules + }, + + // Expected result; + false, // auto_detect + GURL(), // pac_url + net::ProxyRulesExpectation::Single( // proxy_rules + "www.google.com:80", + "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"), + }, +#endif // TO_ENABLE_SOON +}; // tests + +} // namespace + +class ProxyConfigServiceImplTest : public PlatformTest { + protected: + ProxyConfigServiceImplTest() + : ui_thread_(ChromeThread::UI, &message_loop_), + io_thread_(ChromeThread::IO, &message_loop_) { + } + + virtual ~ProxyConfigServiceImplTest() { + config_service_ = NULL; + MessageLoop::current()->RunAllPending(); + } + + void CreateConfigService( + const ProxyConfigServiceImpl::ProxyConfig& init_config) { + // Instantiate proxy config service with |init_config|. + config_service_ = new ProxyConfigServiceImpl(init_config); + } + + void SetAutomaticProxy( + ProxyConfigServiceImpl::ProxyConfig::Mode mode, + ProxyConfigServiceImpl::ProxyConfig::Source source, + const char* pac_url, + ProxyConfigServiceImpl::ProxyConfig* config, + ProxyConfigServiceImpl::ProxyConfig::AutomaticProxy* automatic_proxy) { + config->mode = mode; + automatic_proxy->source = source; + if (pac_url) + automatic_proxy->pac_url = GURL(pac_url); + } + + void SetManualProxy( + ProxyConfigServiceImpl::ProxyConfig::Mode mode, + ProxyConfigServiceImpl::ProxyConfig::Source source, + const char* server_uri, + ProxyConfigServiceImpl::ProxyConfig* config, + ProxyConfigServiceImpl::ProxyConfig::ManualProxy* manual_proxy) { + if (!server_uri) + return; + config->mode = mode; + manual_proxy->source = source; + manual_proxy->server = net::ProxyServer::FromURI(server_uri, + net::ProxyServer::SCHEME_HTTP); + } + + void InitConfigWithTestInput( + const Input& input, + ProxyConfigServiceImpl::ProxyConfig* init_config) { + ProxyConfigServiceImpl::ProxyConfig::Source source = MK_SRC(OWNER); + switch (input.mode) { + case MK_MODE(DIRECT): + case MK_MODE(AUTO_DETECT): + case MK_MODE(PAC_SCRIPT): + SetAutomaticProxy(input.mode, source, input.pac_url, init_config, + &init_config->automatic_proxy); + return; + case MK_MODE(SINGLE_PROXY): + SetManualProxy(input.mode, source, input.single_uri, init_config, + &init_config->single_proxy); + break; + case MK_MODE(PROXY_PER_SCHEME): + SetManualProxy(input.mode, source, input.http_uri, init_config, + &init_config->http_proxy); + SetManualProxy(input.mode, source, input.https_uri, init_config, + &init_config->https_proxy); + SetManualProxy(input.mode, source, input.ftp_uri, init_config, + &init_config->ftp_proxy); + SetManualProxy(input.mode, source, input.socks_uri, init_config, + &init_config->socks_proxy); + break; + } + if (input.bypass_rules) { + init_config->bypass_rules.ParseFromStringUsingSuffixMatching( + input.bypass_rules); + } + } + + // Synchronously gets the latest proxy config. + bool SyncGetLatestProxyConfig(net::ProxyConfig* config) { + // Let message loop process all messages. + MessageLoop::current()->RunAllPending(); + // Calls IOGetProxyConfig (which is called from + // ProxyConfigService::GetLatestProxyConfig), running on faked IO thread. + return config_service_->IOGetProxyConfig(config); + } + + ProxyConfigServiceImpl* config_service() const { + return config_service_; + } + + private: + MessageLoop message_loop_; + ChromeThread ui_thread_; + ChromeThread io_thread_; + + scoped_refptr<ProxyConfigServiceImpl> config_service_; +}; + +TEST_F(ProxyConfigServiceImplTest, ChromeosProxyConfigToNetProxyConfig) { + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i, + tests[i].description.c_str())); + + ProxyConfigServiceImpl::ProxyConfig init_config; + InitConfigWithTestInput(tests[i].input, &init_config); + CreateConfigService(init_config); + + net::ProxyConfig config; + SyncGetLatestProxyConfig(&config); + + 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())); + } +} + +TEST_F(ProxyConfigServiceImplTest, ReadWriteAccess) { + static const char* pac_url = "http://wpad.dat"; + + { // Init with pac script from policy. + ProxyConfigServiceImpl::ProxyConfig init_config; + SetAutomaticProxy(MK_MODE(PAC_SCRIPT), MK_SRC(POLICY), pac_url, + &init_config, &init_config.automatic_proxy); + CreateConfigService(init_config); + + ProxyConfigServiceImpl::ProxyConfig config; + config_service()->UIGetProxyConfig(&config); + + EXPECT_EQ(MK_SRC(POLICY), config.automatic_proxy.source); + // Setting should be not be writeable by owner. + EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(true)); + // Setting should be not be writeable by non-owner. + EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(false)); + } + + { // Init with pac script from owner. + ProxyConfigServiceImpl::ProxyConfig init_config; + SetAutomaticProxy(MK_MODE(PAC_SCRIPT), MK_SRC(OWNER), pac_url, + &init_config, &init_config.automatic_proxy); + CreateConfigService(init_config); + + ProxyConfigServiceImpl::ProxyConfig config; + config_service()->UIGetProxyConfig(&config); + + EXPECT_EQ(MK_SRC(OWNER), config.automatic_proxy.source); + // Setting should be writeable by owner. + EXPECT_TRUE(config.automatic_proxy.CanBeWrittenByUser(true)); + // Setting should not be writeable by non-owner. + EXPECT_FALSE(config.automatic_proxy.CanBeWrittenByUser(false)); + } +} + +TEST_F(ProxyConfigServiceImplTest, ModifyFromUI) { + // Init with direct. + ProxyConfigServiceImpl::ProxyConfig init_config; + SetAutomaticProxy(MK_MODE(DIRECT), MK_SRC(OWNER), NULL, &init_config, + &init_config.automatic_proxy); + CreateConfigService(init_config); + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i, + tests[i].description.c_str())); + + // Set config to tests[i].input via UI. + net::ProxyBypassRules bypass_rules; + net::ProxyServer::Scheme scheme = net::ProxyServer::SCHEME_HTTP; + const Input& input = tests[i].input; + switch (input.mode) { + case MK_MODE(DIRECT) : + config_service()->UISetProxyConfigToDirect(); + break; + case MK_MODE(AUTO_DETECT) : + config_service()->UISetProxyConfigToAutoDetect(); + break; + case MK_MODE(PAC_SCRIPT) : + config_service()->UISetProxyConfigToPACScript(GURL(input.pac_url)); + break; + case MK_MODE(SINGLE_PROXY) : + config_service()->UISetProxyConfigToSingleProxy( + net::ProxyServer::FromURI(input.single_uri, + net::ProxyServer::SCHEME_HTTP)); + if (input.bypass_rules) { + bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules); + config_service()->UISetProxyConfigBypassRules(bypass_rules); + } + break; + case MK_MODE(PROXY_PER_SCHEME) : + if (input.http_uri) { + config_service()->UISetProxyConfigToProxyPerScheme( + "http", + net::ProxyServer::FromURI(input.http_uri, scheme)); + } + if (input.https_uri) { + config_service()->UISetProxyConfigToProxyPerScheme( + "https", + net::ProxyServer::FromURI(input.https_uri, scheme)); + } + if (input.ftp_uri) { + config_service()->UISetProxyConfigToProxyPerScheme( + "ftp", + net::ProxyServer::FromURI(input.ftp_uri, scheme)); + } + if (input.socks_uri) { + config_service()->UISetProxyConfigToProxyPerScheme( + "socks", + net::ProxyServer::FromURI(input.socks_uri, scheme)); + } + if (input.bypass_rules) { + bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules); + config_service()->UISetProxyConfigBypassRules(bypass_rules); + } + break; + } + + // Retrieve config from IO thread. + net::ProxyConfig io_config; + SyncGetLatestProxyConfig(&io_config); + EXPECT_EQ(tests[i].auto_detect, io_config.auto_detect()); + EXPECT_EQ(tests[i].pac_url, io_config.pac_url()); + EXPECT_TRUE(tests[i].proxy_rules.Matches(io_config.proxy_rules())); + + // Retrieve config from UI thread. + ProxyConfigServiceImpl::ProxyConfig ui_config; + config_service()->UIGetProxyConfig(&ui_config); + EXPECT_EQ(input.mode, ui_config.mode); + if (input.pac_url) + EXPECT_EQ(GURL(input.pac_url), ui_config.automatic_proxy.pac_url); + const net::ProxyRulesExpectation& proxy_rules = tests[i].proxy_rules; + if (input.single_uri) + EXPECT_EQ(proxy_rules.single_proxy, + ui_config.single_proxy.server.ToURI()); + if (input.http_uri) + EXPECT_EQ(proxy_rules.proxy_for_http, + ui_config.http_proxy.server.ToURI()); + if (input.https_uri) + EXPECT_EQ(proxy_rules.proxy_for_https, + ui_config.https_proxy.server.ToURI()); + if (input.ftp_uri) + EXPECT_EQ(proxy_rules.proxy_for_ftp, ui_config.ftp_proxy.server.ToURI()); + if (input.socks_uri) + EXPECT_EQ(proxy_rules.socks_proxy, ui_config.socks_proxy.server.ToURI()); + if (input.bypass_rules) + EXPECT_TRUE(bypass_rules.Equals(ui_config.bypass_rules)); + } +} + +TEST_F(ProxyConfigServiceImplTest, ProxyChangedObserver) { + // This is used to observe for OnProxyConfigChanged notification. + class ProxyChangedObserver : public net::ProxyConfigService::Observer { + public: + explicit ProxyChangedObserver( + const scoped_refptr<ProxyConfigServiceImpl>& config_service) + : config_service_(config_service) { + config_service_->AddObserver(this); + } + virtual ~ProxyChangedObserver() { + config_service_->RemoveObserver(this); + } + const net::ProxyConfig& config() const { + return config_; + } + + private: + virtual void OnProxyConfigChanged(const net::ProxyConfig& config) { + config_ = config; + } + + scoped_refptr<ProxyConfigServiceImpl> config_service_; + net::ProxyConfig config_; + }; + + // Init with direct. + ProxyConfigServiceImpl::ProxyConfig init_config; + SetAutomaticProxy(MK_MODE(DIRECT), MK_SRC(OWNER), NULL, &init_config, + &init_config.automatic_proxy); + CreateConfigService(init_config); + + ProxyChangedObserver observer(config_service()); + + // Set to pac script from UI. + config_service()->UISetProxyConfigToPACScript(GURL("http://wpad.dat")); + + // Retrieve config from IO thread. + net::ProxyConfig io_config; + SyncGetLatestProxyConfig(&io_config); + + // Observer should have gotten the same new proxy config. + EXPECT_TRUE(io_config.Equals(observer.config())); +} + +} // namespace chromeos diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index 7c5031f..f5a21f8 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -40,6 +40,10 @@ #include "net/ocsp/nss_ocsp.h" #endif +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/proxy_config_service.h" +#endif // defined(OS_CHROMEOS) + namespace { // ---------------------------------------------------------------------------- @@ -58,22 +62,27 @@ void CheckCurrentlyOnMainThread() { // Helper methods to initialize proxy // ---------------------------------------------------------------------------- -net::ProxyConfigService* CreateProxyConfigService( - const PrefService* pref_service) { +net::ProxyConfigService* CreateProxyConfigService(Profile* profile) { // The linux gconf-based proxy settings getter relies on being initialized // from the UI thread. CheckCurrentlyOnMainThread(); - scoped_ptr<net::ProxyConfig> proxy_config(CreateProxyConfig(pref_service)); + scoped_ptr<net::ProxyConfig> proxy_config(CreateProxyConfig( + profile->GetPrefs())); if (!proxy_config.get()) { // Use system settings. // TODO(port): the IO and FILE message loops are only used by Linux. Can // that code be moved to chrome/browser instead of being in net, so that it // can use ChromeThread instead of raw MessageLoop pointers? See bug 25354. +#if defined(OS_CHROMEOS) + return new chromeos::ProxyConfigService( + profile->GetChromeOSProxyConfigServiceImpl()); +#else return net::ProxyService::CreateSystemProxyConfigService( g_browser_process->io_thread()->message_loop(), g_browser_process->file_thread()->message_loop()); +#endif // defined(OS_CHROMEOS) } // Otherwise use the fixed settings from the command line. @@ -225,7 +234,7 @@ class FactoryForOriginal : public ChromeURLRequestContextFactory { // We need to initialize the ProxyConfigService from the UI thread // because on linux it relies on initializing things through gconf, // and needs to be on the main thread. - proxy_config_service_(CreateProxyConfigService(profile->GetPrefs())) { + proxy_config_service_(CreateProxyConfigService(profile)) { } virtual ChromeURLRequestContext* Create(); diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 51d74f0..116b645 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -487,6 +487,13 @@ class OffTheRecordProfileImpl : public Profile, last_selected_directory_ = path; } +#if defined(OS_CHROMEOS) + virtual chromeos::ProxyConfigServiceImpl* + GetChromeOSProxyConfigServiceImpl() { + return profile_->GetChromeOSProxyConfigServiceImpl(); + } +#endif // defined(OS_CHROMEOS) + virtual void ExitedOffTheRecordMode() { // Drop our download manager so we forget about all the downloads made // in off-the-record mode. diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index 5043607..9d3034c 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -14,6 +14,13 @@ namespace base { class Time; } + +#if defined(OS_CHROMEOS) +namespace chromeos { +class ProxyConfigServiceImpl; +} +#endif + namespace history { class TopSites; } @@ -422,6 +429,12 @@ class Profile { virtual FilePath last_selected_directory() = 0; virtual void set_last_selected_directory(const FilePath& path) = 0; +#if defined(OS_CHROMEOS) + // Returns ChromeOS's ProxyConfigServiceImpl, creating if not yet created. + virtual chromeos::ProxyConfigServiceImpl* + GetChromeOSProxyConfigServiceImpl() = 0; +#endif // defined(OS_CHROMEOS) + #ifdef UNIT_TEST // Use with caution. GetDefaultRequestContext may be called on any thread! static void set_default_request_context(URLRequestContextGetter* c) { diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc index 5680658..4d976d0 100644 --- a/chrome/browser/profile_impl.cc +++ b/chrome/browser/profile_impl.cc @@ -87,6 +87,8 @@ #elif defined(OS_MACOSX) #include "chrome/browser/keychain_mac.h" #include "chrome/browser/password_manager/password_store_mac.h" +#elif defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/proxy_config_service_impl.h" #elif defined(OS_POSIX) && !defined(OS_CHROMEOS) #include "base/xdg_util.h" #include "chrome/browser/password_manager/native_backend_gnome_x.h" @@ -1213,3 +1215,14 @@ void ProfileImpl::InitCloudPrintProxyService() { cloud_print_proxy_service_.reset(new CloudPrintProxyService(this)); cloud_print_proxy_service_->Initialize(); } + +#if defined(OS_CHROMEOS) +chromeos::ProxyConfigServiceImpl* + ProfileImpl::GetChromeOSProxyConfigServiceImpl() { + if (!chromeos_proxy_config_service_impl_) { + chromeos_proxy_config_service_impl_ = + new chromeos::ProxyConfigServiceImpl(); + } + return chromeos_proxy_config_service_impl_; +} +#endif // defined(OS_CHROMEOS) diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h index a219f12..a948e4c5 100644 --- a/chrome/browser/profile_impl.h +++ b/chrome/browser/profile_impl.h @@ -104,6 +104,10 @@ class ProfileImpl : public Profile, virtual CloudPrintProxyService* GetCloudPrintProxyService(); void InitCloudPrintProxyService(); +#if defined(OS_CHROMEOS) + virtual chromeos::ProxyConfigServiceImpl* GetChromeOSProxyConfigServiceImpl(); +#endif // defined(OS_CHROMEOS) + // NotificationObserver implementation. virtual void Observe(NotificationType type, const NotificationSource& source, @@ -231,6 +235,9 @@ class ProfileImpl : public Profile, #if defined(OS_CHROMEOS) chromeos::Preferences chromeos_preferences_; + + scoped_refptr<chromeos::ProxyConfigServiceImpl> + chromeos_proxy_config_service_impl_; #endif DISALLOW_COPY_AND_ASSIGN(ProfileImpl); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index f0d254b..e189e30 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -617,6 +617,9 @@ 'browser/chromeos/pipe_reader.h', 'browser/chromeos/preferences.cc', 'browser/chromeos/preferences.h', + 'browser/chromeos/proxy_config_service.h', + 'browser/chromeos/proxy_config_service_impl.cc', + 'browser/chromeos/proxy_config_service_impl.h', 'browser/chromeos/pulse_audio_mixer.cc', 'browser/chromeos/pulse_audio_mixer.h', 'browser/chromeos/status/clock_menu_button.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index f672664..ad5dce4 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -867,6 +867,7 @@ 'browser/chromeos/offline/offline_load_page_unittest.cc', 'browser/chromeos/options/language_config_model_unittest.cc', 'browser/chromeos/pipe_reader_unittest.cc', + 'browser/chromeos/proxy_config_service_impl_unittest.cc', 'browser/chromeos/status/language_menu_button_unittest.cc', 'browser/chromeos/version_loader_unittest.cc', 'browser/content_setting_bubble_model_unittest.cc', diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h index 5674209..539ae46 100644 --- a/chrome/test/testing_profile.h +++ b/chrome/test/testing_profile.h @@ -236,7 +236,12 @@ class TestingProfile : public Profile { virtual void set_last_selected_directory(const FilePath& path) { last_selected_directory_ = path; } - +#if defined(OS_CHROMEOS) + virtual chromeos::ProxyConfigServiceImpl* + GetChromeOSProxyConfigServiceImpl() { + return NULL; + } +#endif // defined(OS_CHROMEOS) // Schedules a task on the history backend and runs a nested loop until the // task is processed. This has the effect of blocking the caller until the |