summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-24 17:34:08 +0000
committerkuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-24 17:34:08 +0000
commitf50278cd30e63f2deddd6989a93ed2c28134bcd5 (patch)
tree7e7630856bdf77cb96b443eb9f6f65a75b990ec7 /chrome
parenta60aca40a6f65cdbe2533ebf2b2a4caf885a6c41 (diff)
downloadchromium_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.h42
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.cc305
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.h191
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl_unittest.cc539
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc17
-rw-r--r--chrome/browser/profile.cc7
-rw-r--r--chrome/browser/profile.h13
-rw-r--r--chrome/browser/profile_impl.cc13
-rw-r--r--chrome/browser/profile_impl.h7
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/test/testing_profile.h7
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