1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// found in the LICENSE file.
4201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/net/pref_proxy_config_service.h"
6201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
7ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch#include "base/values.h"
8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/prefs/pref_service.h"
9201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/prefs/pref_set_observer.h"
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/prefs/proxy_config_dictionary.h"
11201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/common/pref_names.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h"
16201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
17201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPrefProxyConfigTracker::PrefProxyConfigTracker(PrefService* pref_service)
18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    : pref_service_(pref_service) {
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  config_state_ = ReadPrefConfig(&pref_config_);
20201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  proxy_prefs_observer_.reset(
21201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this));
22201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
23201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
24201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPrefProxyConfigTracker::~PrefProxyConfigTracker() {
25201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(pref_service_ == NULL);
26201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
27201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPrefProxyConfigTracker::ConfigState
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PrefProxyConfigTracker::GetProxyConfig(net::ProxyConfig* config) {
30201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (config_state_ != CONFIG_UNSET)
32201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    *config = pref_config_;
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return config_state_;
34201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigTracker::DetachFromPrefService() {
37201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Stop notifications.
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  proxy_prefs_observer_.reset();
40201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  pref_service_ = NULL;
41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
43201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigTracker::AddObserver(
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PrefProxyConfigTracker::Observer* observer) {
45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
46201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  observers_.AddObserver(observer);
47201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
48201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
49201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigTracker::RemoveObserver(
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PrefProxyConfigTracker::Observer* observer) {
51201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  observers_.RemoveObserver(observer);
53201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigTracker::Observe(NotificationType type,
56201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     const NotificationSource& source,
57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     const NotificationDetails& details) {
58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
59201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (type == NotificationType::PREF_CHANGED &&
60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      Source<PrefService>(source).ptr() == pref_service_) {
61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    net::ProxyConfig new_config;
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ConfigState config_state = ReadPrefConfig(&new_config);
63201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    BrowserThread::PostTask(
64201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        BrowserThread::IO, FROM_HERE,
65201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        NewRunnableMethod(this,
66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          &PrefProxyConfigTracker::InstallProxyConfig,
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          new_config, config_state));
68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else {
69201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    NOTREACHED() << "Unexpected notification of type " << type.value;
70201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PrefProxyConfigTracker::InstallProxyConfig(
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const net::ProxyConfig& config,
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PrefProxyConfigTracker::ConfigState config_state) {
76201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (config_state_ != config_state ||
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (config_state_ != CONFIG_UNSET && !pref_config_.Equals(config))) {
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    config_state_ = config_state;
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (config_state_ != CONFIG_UNSET)
81201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      pref_config_ = config;
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    FOR_EACH_OBSERVER(Observer, observers_, OnPrefProxyConfigChanged());
83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPrefProxyConfigTracker::ConfigState
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PrefProxyConfigTracker::ReadPrefConfig(net::ProxyConfig* config) {
88201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
89201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
90201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Clear the configuration.
91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  *config = net::ProxyConfig();
92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const PrefService::Preference* pref =
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pref_service_->FindPreference(prefs::kProxy);
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const DictionaryValue* dict = pref_service_->GetDictionary(prefs::kProxy);
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(dict);
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProxyConfigDictionary proxy_dict(dict);
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (PrefConfigToNetConfig(proxy_dict, config)) {
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return (!pref->IsUserModifiable() || pref->HasUserSetting()) ?
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        CONFIG_PRESENT : CONFIG_FALLBACK;
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return CONFIG_UNSET;
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PrefProxyConfigTracker::PrefConfigToNetConfig(
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ProxyConfigDictionary& proxy_dict,
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    net::ProxyConfig* config) {
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ProxyPrefs::ProxyMode mode;
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!proxy_dict.GetMode(&mode)) {
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Fall back to system settings if the mode preference is invalid.
113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return false;
114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  switch (mode) {
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case ProxyPrefs::MODE_SYSTEM:
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Use system settings.
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return true;
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case ProxyPrefs::MODE_DIRECT:
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Ignore all the other proxy config preferences if the use of a proxy
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // has been explicitly disabled.
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return true;
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case ProxyPrefs::MODE_AUTO_DETECT:
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      config->set_auto_detect(true);
12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return true;
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case ProxyPrefs::MODE_PAC_SCRIPT: {
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::string proxy_pac;
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!proxy_dict.GetPacUrl(&proxy_pac)) {
13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG(ERROR) << "Proxy settings request PAC script but do not specify "
13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   << "its URL. Falling back to direct connection.";
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return true;
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      GURL proxy_pac_url(proxy_pac);
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (!proxy_pac_url.is_valid()) {
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG(ERROR) << "Invalid proxy PAC url: " << proxy_pac;
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return true;
13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      config->set_pac_url(proxy_pac_url);
14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return true;
14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case ProxyPrefs::MODE_FIXED_SERVERS: {
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::string proxy_server;
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!proxy_dict.GetProxyServer(&proxy_server)) {
14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG(ERROR) << "Proxy settings request fixed proxy servers but do not "
14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   << "specify their URLs. Falling back to direct connection.";
14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return true;
14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      config->proxy_rules().ParseFromString(proxy_server);
15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::string proxy_bypass;
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (proxy_dict.GetBypassList(&proxy_bypass)) {
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        config->proxy_rules().bypass_rules.ParseFromString(proxy_bypass);
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return true;
15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case ProxyPrefs::kModeCount: {
15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Fall through to NOTREACHED().
15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  NOTREACHED() << "Unknown proxy mode, falling back to system settings.";
16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return false;
163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
164201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPrefProxyConfigService::PrefProxyConfigService(
166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    PrefProxyConfigTracker* tracker,
167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    net::ProxyConfigService* base_service)
168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    : base_service_(base_service),
169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      pref_config_tracker_(tracker),
170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      registered_observers_(false) {
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPrefProxyConfigService::~PrefProxyConfigService() {
174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (registered_observers_) {
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    base_service_->RemoveObserver(this);
176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    pref_config_tracker_->RemoveObserver(this);
177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigService::AddObserver(
181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    net::ProxyConfigService::Observer* observer) {
182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RegisterObservers();
183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  observers_.AddObserver(observer);
184201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
185201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
186201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigService::RemoveObserver(
187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    net::ProxyConfigService::Observer* observer) {
188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  observers_.RemoveObserver(observer);
189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennet::ProxyConfigService::ConfigAvailability
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PrefProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) {
193201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RegisterObservers();
19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net::ProxyConfig pref_config;
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PrefProxyConfigTracker::ConfigState state =
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pref_config_tracker_->GetProxyConfig(&pref_config);
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (state == PrefProxyConfigTracker::CONFIG_PRESENT) {
19821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    *config = pref_config;
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return CONFIG_VALID;
20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Ask the base service.
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ConfigAvailability available = base_service_->GetLatestProxyConfig(config);
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Base service doesn't have a configuration, fall back to prefs or default.
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (available == CONFIG_UNSET) {
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (state == PrefProxyConfigTracker::CONFIG_FALLBACK)
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *config = pref_config;
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    else
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *config = net::ProxyConfig::CreateDirect();
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return CONFIG_VALID;
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return available;
215201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigService::OnLazyPoll() {
218201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  base_service_->OnLazyPoll();
219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigService::OnProxyConfigChanged(
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const net::ProxyConfig& config,
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ConfigAvailability availability) {
224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Check whether there is a proxy configuration defined by preferences. In
227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // this case that proxy configuration takes precedence and the change event
228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // from the delegate proxy service can be disregarded.
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  net::ProxyConfig actual_config;
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (pref_config_tracker_->GetProxyConfig(&actual_config) !=
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          PrefProxyConfigTracker::CONFIG_PRESENT) {
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    availability = GetLatestProxyConfig(&actual_config);
233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                      OnProxyConfigChanged(actual_config, availability));
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigService::OnPrefProxyConfigChanged() {
239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Evaluate the proxy configuration. If GetLatestProxyConfig returns
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // CONFIG_PENDING, we are using the system proxy service, but it doesn't have
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // a valid configuration yet. Once it is ready, OnProxyConfigChanged() will be
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // called and broadcast the proxy configuration.
245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Note: If a switch between a preference proxy configuration and the system
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // proxy configuration occurs an unnecessary notification might get send if
247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // the two configurations agree. This case should be rare however, so we don't
248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // handle that case specially.
249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  net::ProxyConfig new_config;
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ConfigAvailability availability = GetLatestProxyConfig(&new_config);
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (availability != CONFIG_PENDING) {
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                      OnProxyConfigChanged(new_config, availability));
254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PrefProxyConfigService::RegisterObservers() {
258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!registered_observers_) {
260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    base_service_->AddObserver(this);
261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    pref_config_tracker_->AddObserver(this);
262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    registered_observers_ = true;
263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
265ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch
266ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch// static
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PrefProxyConfigService::RegisterPrefs(PrefService* pref_service) {
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DictionaryValue* default_settings = ProxyConfigDictionary::CreateSystem();
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  pref_service->RegisterDictionaryPref(prefs::kProxy, default_settings);
270ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch}
271