Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1606)

Unified Diff: chrome/browser/net/pref_proxy_config_service.cc

Issue 5005002: Dynamically refresh pref-configured proxies. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Jochen's comments. Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..5cd62136945832d5832a5929d6f8a5615d6eb6fb
--- /dev/null
+++ b/chrome/browser/net/pref_proxy_config_service.cc
@@ -0,0 +1,222 @@
+// 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 "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_source.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+
+PrefProxyConfigTracker::PrefProxyConfigTracker(PrefService* pref_service)
+ : pref_service_(pref_service) {
+ valid_ = ReadPrefConfig(&pref_config_);
+ proxy_prefs_observer_.reset(
+ PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this));
+}
+
+PrefProxyConfigTracker::~PrefProxyConfigTracker() {
+ DCHECK(pref_service_ == NULL);
+}
+
+bool PrefProxyConfigTracker::GetProxyConfig(net::ProxyConfig* config) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (valid_)
+ *config = pref_config_;
+ return valid_;
+}
+
+void PrefProxyConfigTracker::DetachFromPrefService() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Stop notifications.
+ proxy_prefs_observer_.reset();
+ pref_service_ = NULL;
+}
+
+void PrefProxyConfigTracker::AddObserver(
+ PrefProxyConfigTracker::ObserverInterface* observer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ observers_.AddObserver(observer);
+}
+
+void PrefProxyConfigTracker::RemoveObserver(
+ PrefProxyConfigTracker::ObserverInterface* observer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ observers_.RemoveObserver(observer);
+}
+
+void 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;
+ bool valid = ReadPrefConfig(&new_config);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &PrefProxyConfigTracker::InstallProxyConfig,
+ new_config, valid));
+ } else {
+ NOTREACHED() << "Unexpected notification of type " << type.value;
+ }
+}
+
+void PrefProxyConfigTracker::InstallProxyConfig(const net::ProxyConfig& config,
+ bool valid) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (valid_ != valid || !pref_config_.Equals(config)) {
eroman 2010/11/30 02:58:54 This is a little weird in the case where (!valid_
battre (please use the other) 2010/12/02 18:06:12 Done.
+ valid_ = valid;
+ if (valid_)
+ pref_config_ = config;
+ FOR_EACH_OBSERVER(ObserverInterface, observers_,
+ OnPrefProxyConfigChanged());
+ }
+}
+
+bool PrefProxyConfigTracker::ReadPrefConfig(net::ProxyConfig* config) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Clear the configuration.
+ *config = net::ProxyConfig();
+
+ // 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 false;
+ }
+
+ if (pref_service_->GetBoolean(prefs::kNoProxyServer)) {
+ // Ignore all the other proxy config preferences if the use of a proxy
+ // has been explicitly disabled.
+ return true;
+ }
+
+ 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);
+ }
+
+ return true;
+}
+
+PrefProxyConfigService::PrefProxyConfigService(
+ PrefProxyConfigTracker* tracker,
+ net::ProxyConfigService* base_service)
+ : base_service_(base_service),
+ pref_config_tracker_(tracker),
+ registered_observers_(false) {
+}
+
+PrefProxyConfigService::~PrefProxyConfigService() {
+ if (registered_observers_) {
+ base_service_->RemoveObserver(this);
+ pref_config_tracker_->RemoveObserver(this);
+ }
+}
+
+void PrefProxyConfigService::AddObserver(
+ net::ProxyConfigService::Observer* observer) {
+ RegisterObservers();
+ observers_.AddObserver(observer);
+}
+
+void PrefProxyConfigService::RemoveObserver(
+ net::ProxyConfigService::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+bool PrefProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) {
+ RegisterObservers();
+ const net::ProxyConfig pref_config;
+ if (pref_config_tracker_->GetProxyConfig(config))
+ return true;
+
+ return base_service_->GetLatestProxyConfig(config);
+}
+
+void PrefProxyConfigService::OnLazyPoll() {
+ base_service_->OnLazyPoll();
+}
+
+void PrefProxyConfigService::OnProxyConfigChanged(
+ const net::ProxyConfig& config) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Check whether there is a proxy configuration defined by preferences. In
+ // this case that proxy configuration takes precedence and the change event
+ // from the delegate proxy service can be disregarded.
+ net::ProxyConfig pref_config;
+ if (!pref_config_tracker_->GetProxyConfig(&pref_config)) {
+ FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
+ OnProxyConfigChanged(config));
+ }
+}
+
+void PrefProxyConfigService::OnPrefProxyConfigChanged() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Evaluate the proxy configuration. If GetLatestProxyConfig returns false,
+ // we are using the system proxy service, but it doesn't have a valid
+ // configuration yet. Once it is ready, OnProxyConfigChanged() will be called
+ // and broadcast the proxy configuration.
+ // Note: If a switch between a preference proxy configuration and the system
+ // proxy configuration occurs an unnecessary notification might get send if
+ // the two configurations agree. This case should be rare however, so we don't
+ // handle that case specially.
+ net::ProxyConfig new_config;
+ if (GetLatestProxyConfig(&new_config)) {
+ FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
+ OnProxyConfigChanged(new_config));
+ }
+}
+
+void PrefProxyConfigService::RegisterObservers() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!registered_observers_) {
+ base_service_->AddObserver(this);
+ pref_config_tracker_->AddObserver(this);
+ registered_observers_ = true;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698