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

Side by Side 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: Back to variant that avoids DeleteOnUIThread, make TestingProfile return a real tracker. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/net/pref_proxy_config_service.h"
6
7 #include "chrome/browser/browser_thread.h"
8 #include "chrome/browser/prefs/pref_service.h"
9 #include "chrome/browser/prefs/pref_set_observer.h"
10 #include "chrome/common/notification_details.h"
11 #include "chrome/common/notification_source.h"
12 #include "chrome/common/notification_type.h"
13 #include "chrome/common/pref_names.h"
14
15 PrefProxyConfigTracker::PrefProxyConfigTracker(PrefService* pref_service)
16 : pref_service_(pref_service) {
17 valid_ = ReadPrefConfig(&pref_config_);
18 proxy_prefs_observer_.reset(
19 PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this));
20 }
21
22 PrefProxyConfigTracker::~PrefProxyConfigTracker() {
23 }
24
25 bool PrefProxyConfigTracker::GetProxyConfig(net::ProxyConfig* config) {
26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
27 if (valid_)
28 *config = pref_config_;
29 return valid_;
30 }
31
32 void PrefProxyConfigTracker::DestroyingPrefService() {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
34 // Stop notifications.
35 proxy_prefs_observer_.reset();
36 pref_service_ = NULL;
37 }
38
39 void PrefProxyConfigTracker::AddObserver(
40 PrefProxyConfigTracker::Observer* observer) {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
42 observers_.AddObserver(observer);
43 }
44
45 void PrefProxyConfigTracker::RemoveObserver(
46 PrefProxyConfigTracker::Observer* observer) {
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
48 observers_.RemoveObserver(observer);
49 }
50
51 void PrefProxyConfigTracker::Observe(NotificationType type,
52 const NotificationSource& source,
53 const NotificationDetails& details) {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55 if (type == NotificationType::PREF_CHANGED &&
56 Source<PrefService>(source).ptr() == pref_service_) {
57 net::ProxyConfig new_config;
58 bool valid = ReadPrefConfig(&new_config);
59 BrowserThread::PostTask(
60 BrowserThread::IO, FROM_HERE,
61 NewRunnableMethod(this,
62 &PrefProxyConfigTracker::InstallProxyConfig,
63 new_config, valid));
64 } else {
65 NOTREACHED() << "Unexpected notification of type " << type.value;
66 }
67 }
68
69 void PrefProxyConfigTracker::InstallProxyConfig(const net::ProxyConfig& config,
70 bool valid) {
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
72 if (valid_ != valid || !pref_config_.Equals(config)) {
jochen (gone - plz use gerrit) 2010/11/24 10:04:52 hum, so if valid = false, you might still end up o
Mattias Nissler (ping if slow) 2010/11/24 11:19:29 That change doesn't make any semantic difference (
73 pref_config_ = config;
74 valid_ = valid;
75 FOR_EACH_OBSERVER(Observer, observers_, OnPrefProxyConfigChanged());
76 }
77 }
78
79 bool PrefProxyConfigTracker::ReadPrefConfig(net::ProxyConfig* config) {
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
81
82 // Clear the configuration.
83 *config = net::ProxyConfig();
84
85 // Scan for all "enable" type proxy switches.
86 static const char* proxy_prefs[] = {
87 prefs::kProxyPacUrl,
88 prefs::kProxyServer,
89 prefs::kProxyBypassList,
90 prefs::kProxyAutoDetect
91 };
92
93 // Check whether the preference system holds a valid proxy configuration. Note
94 // that preferences coming from a lower-priority source than the user settings
95 // are ignored. That's because chrome treats the system settings as the
96 // default values, which should apply if there's no explicit value forced by
97 // policy or the user.
98 bool found_enable_proxy_pref = false;
99 for (size_t i = 0; i < arraysize(proxy_prefs); i++) {
100 const PrefService::Preference* pref =
101 pref_service_->FindPreference(proxy_prefs[i]);
102 DCHECK(pref);
103 if (pref && (!pref->IsUserModifiable() || pref->HasUserSetting())) {
104 found_enable_proxy_pref = true;
105 break;
106 }
107 }
108
109 if (!found_enable_proxy_pref &&
110 !pref_service_->GetBoolean(prefs::kNoProxyServer)) {
111 return false;
112 }
113
114 if (pref_service_->GetBoolean(prefs::kNoProxyServer)) {
115 // Ignore all the other proxy config preferences if the use of a proxy
116 // has been explicitly disabled.
117 return true;
118 }
119
120 if (pref_service_->HasPrefPath(prefs::kProxyServer)) {
121 std::string proxy_server = pref_service_->GetString(prefs::kProxyServer);
122 config->proxy_rules().ParseFromString(proxy_server);
123 }
124
125 if (pref_service_->HasPrefPath(prefs::kProxyPacUrl)) {
126 std::string proxy_pac = pref_service_->GetString(prefs::kProxyPacUrl);
127 config->set_pac_url(GURL(proxy_pac));
128 }
129
130 config->set_auto_detect(pref_service_->GetBoolean(prefs::kProxyAutoDetect));
131
132 if (pref_service_->HasPrefPath(prefs::kProxyBypassList)) {
133 std::string proxy_bypass =
134 pref_service_->GetString(prefs::kProxyBypassList);
135 config->proxy_rules().bypass_rules.ParseFromString(proxy_bypass);
136 }
137
138 return true;
139 }
140
141 PrefProxyConfigService::PrefProxyConfigService(
142 PrefProxyConfigTracker* tracker,
143 net::ProxyConfigService* base_service)
144 : base_service_(base_service),
145 pref_config_tracker_(tracker),
146 registered_observers_(false) {
147 }
148
149 PrefProxyConfigService::~PrefProxyConfigService() {
150 if (registered_observers_) {
151 base_service_->RemoveObserver(this);
152 pref_config_tracker_->RemoveObserver(this);
153 }
154 }
155
156 void PrefProxyConfigService::AddObserver(
157 net::ProxyConfigService::Observer* observer) {
158 RegisterObservers();
159 observers_.AddObserver(observer);
160 }
161
162 void PrefProxyConfigService::RemoveObserver(
163 net::ProxyConfigService::Observer* observer) {
164 observers_.RemoveObserver(observer);
165 }
166
167 bool PrefProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) {
168 RegisterObservers();
169 const net::ProxyConfig pref_config;
170 if (pref_config_tracker_->GetProxyConfig(config))
171 return true;
172
173 return base_service_->GetLatestProxyConfig(config);
174 }
175
176 void PrefProxyConfigService::OnLazyPoll() {
177 base_service_->OnLazyPoll();
178 }
179
180 void PrefProxyConfigService::OnProxyConfigChanged(
181 const net::ProxyConfig& config) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
183
184 // Check whether there is a proxy configuration defined by preferences. In
185 // this case that proxy configuration takes precedence and the change event
186 // from the delegate proxy service can be disregarded.
187 net::ProxyConfig pref_config;
188 if (!pref_config_tracker_->GetProxyConfig(&pref_config)) {
189 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
190 OnProxyConfigChanged(config));
191 }
192 }
193
194 void PrefProxyConfigService::OnPrefProxyConfigChanged() {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
196
197 // Evaluate the proxy configuration. If GetLatestProxyConfig returns false,
198 // we are using the system proxy service, but it doesn't have a valid
199 // configuration yet. Once it is ready, OnProxyConfigChanged() will be called
200 // and broadcast the proxy configuration.
201 // Note: If a switch between a preference proxy configuration and the system
202 // proxy configuration occurs an unnecessary notification might get send if
203 // the two configurations agree. This case should be rare however, so we don't
204 // handle that case specially.
205 net::ProxyConfig new_config;
206 if (GetLatestProxyConfig(&new_config)) {
207 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
208 OnProxyConfigChanged(new_config));
209 }
210 }
211
212 void PrefProxyConfigService::RegisterObservers() {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
214 if (!registered_observers_) {
215 base_service_->AddObserver(this);
216 pref_config_tracker_->AddObserver(this);
217 registered_observers_ = true;
218 }
219 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698