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

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

Powered by Google App Engine
This is Rietveld 408576698