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

Side by Side Diff: chrome/browser/net/pref_proxy_config_tracker.cc

Issue 8102019: redesign and reimplement proxy config service and tracker, revise proxy ui on cros (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/net/pref_proxy_config_service.h" 5 #include "chrome/browser/net/pref_proxy_config_tracker.h"
6 6
7 #include "base/bind.h"
7 #include "base/values.h" 8 #include "base/values.h"
8 #include "chrome/browser/prefs/pref_service.h" 9 #include "chrome/browser/prefs/pref_service.h"
9 #include "chrome/browser/prefs/pref_set_observer.h" 10 #include "chrome/browser/prefs/pref_set_observer.h"
10 #include "chrome/browser/prefs/proxy_config_dictionary.h" 11 #include "chrome/browser/prefs/proxy_config_dictionary.h"
11 #include "chrome/common/chrome_notification_types.h" 12 #include "chrome/common/chrome_notification_types.h"
12 #include "chrome/common/pref_names.h" 13 #include "chrome/common/pref_names.h"
13 #include "content/browser/browser_thread.h" 14 #include "content/browser/browser_thread.h"
14 #include "content/common/notification_details.h" 15 #include "content/public/browser/notification_details.h"
15 #include "content/common/notification_source.h" 16 #include "content/public/browser/notification_source.h"
16 17
17 PrefProxyConfigTracker::PrefProxyConfigTracker(PrefService* pref_service) 18 //============================= ChromeProxyConfigService =======================
18 : pref_service_(pref_service) { 19
20 ChromeProxyConfigService::ChromeProxyConfigService(
21 net::ProxyConfigService* base_service)
22 : base_service_(base_service),
23 pref_config_state_(ProxyPrefs::CONFIG_UNSET),
24 registered_observer_(false) {
25 }
26
27 ChromeProxyConfigService::~ChromeProxyConfigService() {
28 if (registered_observer_ && base_service_.get())
29 base_service_->RemoveObserver(this);
30 }
31
32 void ChromeProxyConfigService::AddObserver(
33 net::ProxyConfigService::Observer* observer) {
34 RegisterObserver();
35 observers_.AddObserver(observer);
36 }
37
38 void ChromeProxyConfigService::RemoveObserver(
39 net::ProxyConfigService::Observer* observer) {
40 observers_.RemoveObserver(observer);
41 }
42
43 net::ProxyConfigService::ConfigAvailability
44 ChromeProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) {
45 RegisterObserver();
46
47 // Ask the base service if available.
48 net::ProxyConfig system_config;
49 ConfigAvailability system_availability =
50 net::ProxyConfigService::CONFIG_UNSET;
51 if (base_service_.get())
52 system_availability = base_service_->GetLatestProxyConfig(&system_config);
53
54 ProxyPrefs::ConfigState config_state;
55 return PrefProxyConfigTracker::GetEffectiveProxyConfig(
56 pref_config_state_, pref_config_,
57 system_availability, system_config, false,
58 &config_state, config);
59 }
60
61 void ChromeProxyConfigService::OnLazyPoll() {
62 if (base_service_.get())
63 base_service_->OnLazyPoll();
64 }
65
66 void ChromeProxyConfigService::UpdateProxyConfig(
67 ProxyPrefs::ConfigState config_state,
68 const net::ProxyConfig& config) {
69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
70 VLOG(1) << "got UpdateProxyConfig";
willchan no longer on Chromium 2011/11/02 23:08:17 DVLOG instead? Do you really need this LOG message
kuan 2011/11/03 20:20:14 Done.
71
72 pref_config_state_ = config_state;
73 pref_config_ = config;
74
75 if (!observers_.size())
76 return;
77
78 // Evaluate the proxy configuration. If GetLatestProxyConfig returns
79 // CONFIG_PENDING, we are using the system proxy service, but it doesn't have
80 // a valid configuration yet. Once it is ready, OnProxyConfigChanged() will be
81 // called and broadcast the proxy configuration.
82 // Note: If a switch between a preference proxy configuration and the system
83 // proxy configuration occurs an unnecessary notification might get send if
84 // the two configurations agree. This case should be rare however, so we don't
85 // handle that case specially.
86 net::ProxyConfig new_config;
87 ConfigAvailability availability = GetLatestProxyConfig(&new_config);
88 if (availability != CONFIG_PENDING) {
89 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
90 OnProxyConfigChanged(new_config, availability));
91 }
92 }
93
94 void ChromeProxyConfigService::OnProxyConfigChanged(
95 const net::ProxyConfig& config,
96 ConfigAvailability availability) {
97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
98
99 // Check whether there is a proxy configuration defined by preferences. In
100 // this case that proxy configuration takes precedence and the change event
101 // from the delegate proxy service can be disregarded.
102 if (!PrefProxyConfigTracker::PrefPrecedes(pref_config_state_)) {
103 net::ProxyConfig actual_config;
104 availability = GetLatestProxyConfig(&actual_config);
105 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
106 OnProxyConfigChanged(actual_config, availability));
107 }
108 }
109
110 void ChromeProxyConfigService::RegisterObserver() {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
112 if (!registered_observer_ && base_service_.get()) {
113 base_service_->AddObserver(this);
114 registered_observer_ = true;
115 }
116 }
117
118 //=========================== PrefProxyConfigTracker ===========================
119
120 PrefProxyConfigTracker::PrefProxyConfigTracker(
121 PrefService* pref_service)
122 : pref_service_(pref_service),
123 chrome_proxy_config_service_(NULL),
124 update_pending_(true) {
19 config_state_ = ReadPrefConfig(&pref_config_); 125 config_state_ = ReadPrefConfig(&pref_config_);
20 proxy_prefs_observer_.reset( 126 proxy_prefs_observer_.reset(
21 PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this)); 127 PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this));
22 } 128 }
23 129
24 PrefProxyConfigTracker::~PrefProxyConfigTracker() { 130 PrefProxyConfigTracker::~PrefProxyConfigTracker() {
25 DCHECK(pref_service_ == NULL); 131 DCHECK(pref_service_ == NULL);
26 } 132 }
27 133
28 PrefProxyConfigTracker::ConfigState 134 void PrefProxyConfigTracker::SetChromeProxyConfigService(
29 PrefProxyConfigTracker::GetProxyConfig(net::ProxyConfig* config) { 135 ChromeProxyConfigService* chrome_proxy_config_service) {
30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 136 VLOG(1) << "set chrome proxy config service to "
willchan no longer on Chromium 2011/11/02 23:08:17 Do you really need this? Won't all this be visible
kuan 2011/11/03 20:20:14 this won't be visible in net-internals, it helps m
31 if (config_state_ != CONFIG_UNSET) 137 << chrome_proxy_config_service;
32 *config = pref_config_; 138 chrome_proxy_config_service_ = chrome_proxy_config_service;
33 return config_state_; 139 if (chrome_proxy_config_service_ && update_pending_)
140 OnProxyConfigChanged(config_state_, pref_config_);
34 } 141 }
35 142
36 void PrefProxyConfigTracker::DetachFromPrefService() { 143 void PrefProxyConfigTracker::DetachFromPrefService() {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38 // Stop notifications. 145 // Stop notifications.
39 proxy_prefs_observer_.reset(); 146 proxy_prefs_observer_.reset();
40 pref_service_ = NULL; 147 pref_service_ = NULL;
148 SetChromeProxyConfigService(NULL);
41 } 149 }
42 150
43 void PrefProxyConfigTracker::AddObserver( 151 // static
44 PrefProxyConfigTracker::Observer* observer) { 152 bool PrefProxyConfigTracker::PrefPrecedes(
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 153 ProxyPrefs::ConfigState config_state) {
46 observers_.AddObserver(observer); 154 return config_state == ProxyPrefs::CONFIG_POLICY ||
155 config_state == ProxyPrefs::CONFIG_EXTENSION ||
156 config_state == ProxyPrefs::CONFIG_OTHER_PRECEDE;
47 } 157 }
48 158
49 void PrefProxyConfigTracker::RemoveObserver( 159 // static
50 PrefProxyConfigTracker::Observer* observer) { 160 net::ProxyConfigService::ConfigAvailability
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 161 PrefProxyConfigTracker::GetEffectiveProxyConfig(
52 observers_.RemoveObserver(observer); 162 ProxyPrefs::ConfigState pref_state,
163 const net::ProxyConfig& pref_config,
164 net::ProxyConfigService::ConfigAvailability system_availability,
165 const net::ProxyConfig& system_config,
166 bool ignore_fallback_config,
167 ProxyPrefs::ConfigState* effective_config_state,
168 net::ProxyConfig* effective_config) {
169 *effective_config_state = pref_state;
170
171 if (PrefPrecedes(pref_state)) {
172 *effective_config = pref_config;
173 return net::ProxyConfigService::CONFIG_VALID;
174 }
175
176 // If there's no system proxy config, fall back to prefs or default.
177 if (system_availability == net::ProxyConfigService::CONFIG_UNSET) {
178 if (pref_state == ProxyPrefs::CONFIG_FALLBACK && !ignore_fallback_config)
179 *effective_config = pref_config;
180 else
181 *effective_config = net::ProxyConfig::CreateDirect();
182 return net::ProxyConfigService::CONFIG_VALID;
183 }
184
185 *effective_config_state = ProxyPrefs::CONFIG_SYSTEM;
186 *effective_config = system_config;
187 return system_availability;
53 } 188 }
54 189
55 void PrefProxyConfigTracker::Observe(int type, 190 // static
56 const NotificationSource& source, 191 void PrefProxyConfigTracker::RegisterPrefs(PrefService* pref_service) {
57 const NotificationDetails& details) { 192 DictionaryValue* default_settings = ProxyConfigDictionary::CreateSystem();
58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 193 pref_service->RegisterDictionaryPref(prefs::kProxy,
59 if (type == chrome::NOTIFICATION_PREF_CHANGED && 194 default_settings,
60 Source<PrefService>(source).ptr() == pref_service_) { 195 PrefService::UNSYNCABLE_PREF);
61 net::ProxyConfig new_config;
62 ConfigState config_state = ReadPrefConfig(&new_config);
63 BrowserThread::PostTask(
64 BrowserThread::IO, FROM_HERE,
65 NewRunnableMethod(this,
66 &PrefProxyConfigTracker::InstallProxyConfig,
67 new_config, config_state));
68 } else {
69 NOTREACHED() << "Unexpected notification of type " << type;
70 }
71 } 196 }
72 197
73 void PrefProxyConfigTracker::InstallProxyConfig( 198 ProxyPrefs::ConfigState PrefProxyConfigTracker::GetProxyConfig(
74 const net::ProxyConfig& config, 199 net::ProxyConfig* config) {
75 PrefProxyConfigTracker::ConfigState config_state) { 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 201 if (config_state_ != ProxyPrefs::CONFIG_UNSET)
77 if (config_state_ != config_state || 202 *config = pref_config_;
78 (config_state_ != CONFIG_UNSET && !pref_config_.Equals(config))) { 203 return config_state_;
79 config_state_ = config_state;
80 if (config_state_ != CONFIG_UNSET)
81 pref_config_ = config;
82 FOR_EACH_OBSERVER(Observer, observers_, OnPrefProxyConfigChanged());
83 }
84 } 204 }
85 205
86 PrefProxyConfigTracker::ConfigState 206 void PrefProxyConfigTracker::OnProxyConfigChanged(
87 PrefProxyConfigTracker::ReadPrefConfig(net::ProxyConfig* config) { 207 ProxyPrefs::ConfigState config_state,
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 208 const net::ProxyConfig& config) {
89 209 if (!chrome_proxy_config_service_) {
90 // Clear the configuration. 210 VLOG(1) << "No chrome proxy config service to push to UpdateProxyConfig";
91 *config = net::ProxyConfig(); 211 update_pending_ = true;
92 212 return;
93 const PrefService::Preference* pref =
94 pref_service_->FindPreference(prefs::kProxy);
95 DCHECK(pref);
96
97 const DictionaryValue* dict = pref_service_->GetDictionary(prefs::kProxy);
98 DCHECK(dict);
99 ProxyConfigDictionary proxy_dict(dict);
100
101 if (PrefConfigToNetConfig(proxy_dict, config)) {
102 return (!pref->IsUserModifiable() || pref->HasUserSetting()) ?
103 CONFIG_PRESENT : CONFIG_FALLBACK;
104 } 213 }
105 214 update_pending_ = !BrowserThread::PostTask(
106 return CONFIG_UNSET; 215 BrowserThread::IO, FROM_HERE,
216 base::Bind(&ChromeProxyConfigService::UpdateProxyConfig,
217 base::Unretained(chrome_proxy_config_service_),
218 config_state, config));
219 VLOG(1) << this << (update_pending_ ? ": Error" : ": Done")
220 << " pushing proxy to UpdateProxyConfig";
107 } 221 }
108 222
109 bool PrefProxyConfigTracker::PrefConfigToNetConfig( 223 bool PrefProxyConfigTracker::PrefConfigToNetConfig(
110 const ProxyConfigDictionary& proxy_dict, 224 const ProxyConfigDictionary& proxy_dict,
111 net::ProxyConfig* config) { 225 net::ProxyConfig* config) {
112 ProxyPrefs::ProxyMode mode; 226 ProxyPrefs::ProxyMode mode;
113 if (!proxy_dict.GetMode(&mode)) { 227 if (!proxy_dict.GetMode(&mode)) {
114 // Fall back to system settings if the mode preference is invalid. 228 // Fall back to system settings if the mode preference is invalid.
115 return false; 229 return false;
116 } 230 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 return true; 274 return true;
161 } 275 }
162 case ProxyPrefs::kModeCount: { 276 case ProxyPrefs::kModeCount: {
163 // Fall through to NOTREACHED(). 277 // Fall through to NOTREACHED().
164 } 278 }
165 } 279 }
166 NOTREACHED() << "Unknown proxy mode, falling back to system settings."; 280 NOTREACHED() << "Unknown proxy mode, falling back to system settings.";
167 return false; 281 return false;
168 } 282 }
169 283
170 PrefProxyConfigService::PrefProxyConfigService( 284 void PrefProxyConfigTracker::Observe(
171 PrefProxyConfigTracker* tracker, 285 int type,
172 net::ProxyConfigService* base_service) 286 const content::NotificationSource& source,
173 : base_service_(base_service), 287 const content::NotificationDetails& details) {
174 pref_config_tracker_(tracker), 288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
175 registered_observers_(false) { 289 if (type == chrome::NOTIFICATION_PREF_CHANGED &&
176 } 290 content::Source<PrefService>(source).ptr() == pref_service_) {
177 291 net::ProxyConfig new_config;
178 PrefProxyConfigService::~PrefProxyConfigService() { 292 ProxyPrefs::ConfigState config_state = ReadPrefConfig(&new_config);
179 if (registered_observers_) { 293 if (config_state_ != config_state ||
180 base_service_->RemoveObserver(this); 294 (config_state_ != ProxyPrefs::CONFIG_UNSET &&
181 pref_config_tracker_->RemoveObserver(this); 295 !pref_config_.Equals(new_config))) {
296 config_state_ = config_state;
297 if (config_state_ != ProxyPrefs::CONFIG_UNSET)
298 pref_config_ = new_config;
299 update_pending_ = true;
300 }
301 if (update_pending_)
302 OnProxyConfigChanged(config_state, new_config);
303 } else {
304 NOTREACHED() << "Unexpected notification of type " << type;
182 } 305 }
183 } 306 }
184 307
185 void PrefProxyConfigService::AddObserver( 308 ProxyPrefs::ConfigState PrefProxyConfigTracker::ReadPrefConfig(
186 net::ProxyConfigService::Observer* observer) { 309 net::ProxyConfig* config) {
187 RegisterObservers(); 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
188 observers_.AddObserver(observer);
189 }
190 311
191 void PrefProxyConfigService::RemoveObserver( 312 // Clear the configuration and source.
192 net::ProxyConfigService::Observer* observer) { 313 *config = net::ProxyConfig();
193 observers_.RemoveObserver(observer); 314 ProxyPrefs::ConfigState config_state = ProxyPrefs::CONFIG_UNSET;
194 }
195 315
196 net::ProxyConfigService::ConfigAvailability 316 const PrefService::Preference* pref =
197 PrefProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) { 317 pref_service_->FindPreference(prefs::kProxy);
198 RegisterObservers(); 318 DCHECK(pref);
199 net::ProxyConfig pref_config; 319
200 PrefProxyConfigTracker::ConfigState state = 320 const DictionaryValue* dict = pref_service_->GetDictionary(prefs::kProxy);
201 pref_config_tracker_->GetProxyConfig(&pref_config); 321 DCHECK(dict);
202 if (state == PrefProxyConfigTracker::CONFIG_PRESENT) { 322 ProxyConfigDictionary proxy_dict(dict);
203 *config = pref_config; 323
204 return CONFIG_VALID; 324 if (PrefConfigToNetConfig(proxy_dict, config)) {
325 if (!pref->IsUserModifiable() || pref->HasUserSetting()) {
326 if (pref->IsManaged())
327 config_state = ProxyPrefs::CONFIG_POLICY;
328 else if (pref->IsExtensionControlled())
329 config_state = ProxyPrefs::CONFIG_EXTENSION;
330 else
331 config_state = ProxyPrefs::CONFIG_OTHER_PRECEDE;
332 } else {
333 config_state = ProxyPrefs::CONFIG_FALLBACK;
334 }
205 } 335 }
206 336
207 // Ask the base service. 337 return config_state;
208 ConfigAvailability available = base_service_->GetLatestProxyConfig(config);
209
210 // Base service doesn't have a configuration, fall back to prefs or default.
211 if (available == CONFIG_UNSET) {
212 if (state == PrefProxyConfigTracker::CONFIG_FALLBACK)
213 *config = pref_config;
214 else
215 *config = net::ProxyConfig::CreateDirect();
216 return CONFIG_VALID;
217 }
218
219 return available;
220 } 338 }
221
222 void PrefProxyConfigService::OnLazyPoll() {
223 base_service_->OnLazyPoll();
224 }
225
226 void PrefProxyConfigService::OnProxyConfigChanged(
227 const net::ProxyConfig& config,
228 ConfigAvailability availability) {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230
231 // Check whether there is a proxy configuration defined by preferences. In
232 // this case that proxy configuration takes precedence and the change event
233 // from the delegate proxy service can be disregarded.
234 net::ProxyConfig actual_config;
235 if (pref_config_tracker_->GetProxyConfig(&actual_config) !=
236 PrefProxyConfigTracker::CONFIG_PRESENT) {
237 availability = GetLatestProxyConfig(&actual_config);
238 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
239 OnProxyConfigChanged(actual_config, availability));
240 }
241 }
242
243 void PrefProxyConfigService::OnPrefProxyConfigChanged() {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
245
246 // Evaluate the proxy configuration. If GetLatestProxyConfig returns
247 // CONFIG_PENDING, we are using the system proxy service, but it doesn't have
248 // a valid configuration yet. Once it is ready, OnProxyConfigChanged() will be
249 // called and broadcast the proxy configuration.
250 // Note: If a switch between a preference proxy configuration and the system
251 // proxy configuration occurs an unnecessary notification might get send if
252 // the two configurations agree. This case should be rare however, so we don't
253 // handle that case specially.
254 net::ProxyConfig new_config;
255 ConfigAvailability availability = GetLatestProxyConfig(&new_config);
256 if (availability != CONFIG_PENDING) {
257 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
258 OnProxyConfigChanged(new_config, availability));
259 }
260 }
261
262 void PrefProxyConfigService::RegisterObservers() {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
264 if (!registered_observers_) {
265 base_service_->AddObserver(this);
266 pref_config_tracker_->AddObserver(this);
267 registered_observers_ = true;
268 }
269 }
270
271 // static
272 void PrefProxyConfigService::RegisterPrefs(PrefService* pref_service) {
273 DictionaryValue* default_settings = ProxyConfigDictionary::CreateSystem();
274 pref_service->RegisterDictionaryPref(prefs::kProxy,
275 default_settings,
276 PrefService::UNSYNCABLE_PREF);
277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698