Chromium Code Reviews| Index: chrome/browser/net/pref_proxy_config_service.cc |
| diff --git a/chrome/browser/net/pref_proxy_config_service.cc b/chrome/browser/net/pref_proxy_config_service.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c9c8759a3a8d8452e9ff5cdc28878e51e8d26a73 |
| --- /dev/null |
| +++ b/chrome/browser/net/pref_proxy_config_service.cc |
| @@ -0,0 +1,210 @@ |
| +// 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/net/pref_proxy_config_service.h" |
| + |
| +#include "base/ref_counted.h" |
| +#include "chrome/browser/browser_thread.h" |
| +#include "chrome/browser/prefs/pref_service.h" |
| +#include "chrome/browser/prefs/pref_set_observer.h" |
| +#include "chrome/common/notification_details.h" |
| +#include "chrome/common/notification_observer.h" |
| +#include "chrome/common/notification_source.h" |
| +#include "chrome/common/notification_type.h" |
| +#include "chrome/common/pref_names.h" |
| + |
| +// A helper class that tracks proxy preferences. It translates the configuration |
| +// to net::ProxyConfig and proxies the result over to PrefProxyConfigService on |
| +// the IO thread. |
| +class PrefProxyConfigService::PrefProxyConfigTracker |
| + : public base::RefCountedThreadSafe<PrefProxyConfigTracker, |
| + BrowserThread::DeleteOnUIThread>, |
|
jochen (gone - plz use gerrit)
2010/11/16 22:48:32
make sure to run this on the valgrind bots
Mattias Nissler (ping if slow)
2010/11/16 22:58:11
Will do.
|
| + public NotificationObserver { |
| + public: |
| + PrefProxyConfigTracker( |
| + base::WeakPtr<PrefProxyConfigService> pref_config_service, |
| + PrefService* pref_service) |
| + : pref_config_service_(pref_config_service), |
| + pref_service_(pref_service) { |
| + ReadPrefConfig(&pref_config_); |
| + proxy_prefs_observer_.reset( |
| + PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this)); |
| + } |
| + |
| + virtual ~PrefProxyConfigTracker() {} |
| + |
| + // Get the proxy configuration currently defined by preferences. |
| + const net::ProxyConfig& GetProxyConfig() { return pref_config_; } |
| + |
| + private: |
| + // NotificationObserver implementation: |
| + virtual void Observe(NotificationType type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details); |
| + |
| + // Install a new configuration (to be called on the IO thread). |
| + void InstallProxyConfig(const net::ProxyConfig& config); |
| + |
| + // Creates a proxy configuration from proxy-related preferences. Sets |config| |
| + // to invalid if there's no proxy configuration defined in prefs. |
| + void ReadPrefConfig(net::ProxyConfig* config); |
| + |
| + // Configuration as defined by prefs. Only to be accessed from the IO thread |
| + // (expect for construction). |
| + net::ProxyConfig pref_config_; |
| + |
| + base::WeakPtr<PrefProxyConfigService> pref_config_service_; |
| + PrefService* pref_service_; |
| + scoped_ptr<PrefSetObserver> proxy_prefs_observer_; |
| +}; |
|
jochen (gone - plz use gerrit)
2010/11/16 22:48:32
disallow copy and assign?
Mattias Nissler (ping if slow)
2010/11/16 22:58:11
Done.
|
| + |
| +void PrefProxyConfigService::PrefProxyConfigTracker::Observe( |
| + NotificationType type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (type == NotificationType::PREF_CHANGED && |
| + Source<PrefService>(source).ptr() == pref_service_) { |
| + net::ProxyConfig new_config; |
| + ReadPrefConfig(&new_config); |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod(this, |
| + &PrefProxyConfigTracker::InstallProxyConfig, |
| + new_config)); |
| + } else { |
| + NOTREACHED() << "Unexpected notification of type " << type.value; |
| + } |
| +} |
| + |
| +void PrefProxyConfigService::PrefProxyConfigTracker::InstallProxyConfig( |
| + const net::ProxyConfig& config) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + pref_config_ = config; |
| + if (pref_config_service_.get()) |
| + pref_config_service_->PrefProxyConfigChanged(); |
| +} |
| + |
| +void PrefProxyConfigService::PrefProxyConfigTracker::ReadPrefConfig( |
| + net::ProxyConfig* config) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + // Invalidate the configuration. |
| + config->set_id(net::ProxyConfig::INVALID_ID); |
| + |
| + // Scan for all "enable" type proxy switches. |
| + static const char* proxy_prefs[] = { |
| + prefs::kProxyPacUrl, |
| + prefs::kProxyServer, |
| + prefs::kProxyBypassList, |
| + prefs::kProxyAutoDetect |
| + }; |
| + |
| + // Check whether the preference system holds a valid proxy configuration. Note |
| + // that preferences coming from a lower-priority source than the user settings |
| + // are ignored. That's because chrome treats the system settings as the |
| + // default values, which should apply if there's no explicit value forced by |
| + // policy or the user. |
| + bool found_enable_proxy_pref = false; |
| + for (size_t i = 0; i < arraysize(proxy_prefs); i++) { |
| + const PrefService::Preference* pref = |
| + pref_service_->FindPreference(proxy_prefs[i]); |
| + DCHECK(pref); |
| + if (pref && (!pref->IsUserModifiable() || pref->HasUserSetting())) { |
| + found_enable_proxy_pref = true; |
| + break; |
| + } |
| + } |
| + |
| + if (!found_enable_proxy_pref && |
| + !pref_service_->GetBoolean(prefs::kNoProxyServer)) { |
| + return; |
| + } |
| + |
| + // There is a valid configuration present. |
| + config->set_id(1); |
| + |
| + if (pref_service_->GetBoolean(prefs::kNoProxyServer)) { |
| + // Ignore all the other proxy config preferences if the use of a proxy |
| + // has been explicitly disabled. |
| + return; |
| + } |
| + |
| + if (pref_service_->HasPrefPath(prefs::kProxyServer)) { |
| + std::string proxy_server = pref_service_->GetString(prefs::kProxyServer); |
| + config->proxy_rules().ParseFromString(proxy_server); |
| + } |
| + |
| + if (pref_service_->HasPrefPath(prefs::kProxyPacUrl)) { |
| + std::string proxy_pac = pref_service_->GetString(prefs::kProxyPacUrl); |
| + config->set_pac_url(GURL(proxy_pac)); |
| + } |
| + |
| + config->set_auto_detect(pref_service_->GetBoolean(prefs::kProxyAutoDetect)); |
| + |
| + if (pref_service_->HasPrefPath(prefs::kProxyBypassList)) { |
| + std::string proxy_bypass = |
| + pref_service_->GetString(prefs::kProxyBypassList); |
| + config->proxy_rules().bypass_rules.ParseFromString(proxy_bypass); |
| + } |
| +} |
| + |
| +PrefProxyConfigService::PrefProxyConfigService( |
| + PrefService* pref_service, |
| + net::ProxyConfigService* base_service) |
| + : base_service_(base_service), |
| + current_id_(1) { |
| + pref_config_tracker_ = new PrefProxyConfigTracker(AsWeakPtr(), pref_service); |
| + base_service_->AddObserver(this); |
| +} |
| + |
| +PrefProxyConfigService::~PrefProxyConfigService() { |
| + base_service_->RemoveObserver(this); |
| +} |
| + |
| +void PrefProxyConfigService::PrefProxyConfigChanged() { |
| + ++current_id_; |
| + net::ProxyConfig current_config; |
| + GetLatestProxyConfig(¤t_config); |
| + FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, |
| + OnProxyConfigChanged(current_config)); |
| +} |
| + |
| +void PrefProxyConfigService::AddObserver( |
| + net::ProxyConfigService::Observer* observer) { |
| + observers_.AddObserver(observer); |
| +} |
| + |
| +void PrefProxyConfigService::RemoveObserver( |
| + net::ProxyConfigService::Observer* observer) { |
| + observers_.RemoveObserver(observer); |
| +} |
| + |
| +bool PrefProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) { |
| + const net::ProxyConfig& pref_config(pref_config_tracker_->GetProxyConfig()); |
| + if (pref_config.is_valid()) { |
| + *config = pref_config; |
| + config->set_id(current_id_); |
| + return true; |
| + } |
| + |
| + bool result = base_service_->GetLatestProxyConfig(config); |
| + if (config->is_valid()) |
| + config->set_id(current_id_); |
| + return result; |
| +} |
| + |
| +void PrefProxyConfigService::OnLazyPoll() { |
| + base_service_->OnLazyPoll(); |
| +} |
| + |
| +void PrefProxyConfigService::OnProxyConfigChanged( |
| + const net::ProxyConfig& config) { |
| + if (!pref_config_tracker_->GetProxyConfig().is_valid()) { |
| + net::ProxyConfig new_config = config; |
| + new_config.set_id(++current_id_); |
| + FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, |
| + OnProxyConfigChanged(new_config)); |
| + } |
| +} |