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

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: Address 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 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 "base/ref_counted.h"
8 #include "chrome/browser/browser_thread.h"
9 #include "chrome/browser/prefs/pref_service.h"
10 #include "chrome/browser/prefs/pref_set_observer.h"
11 #include "chrome/common/notification_details.h"
12 #include "chrome/common/notification_observer.h"
13 #include "chrome/common/notification_source.h"
14 #include "chrome/common/notification_type.h"
15 #include "chrome/common/pref_names.h"
16
17 // A helper class that tracks proxy preferences. It translates the configuration
18 // to net::ProxyConfig and proxies the result over to PrefProxyConfigService on
19 // the IO thread.
20 class PrefProxyConfigService::PrefProxyConfigTracker
21 : public base::RefCountedThreadSafe<PrefProxyConfigTracker,
22 BrowserThread::DeleteOnUIThread>,
eroman 2010/11/17 02:14:49 DeleteOnUIThread is problematic, since it can lead
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Good point, I actually realized the same thing whi
23 public NotificationObserver {
24 public:
25 PrefProxyConfigTracker(
26 base::WeakPtr<PrefProxyConfigService> pref_config_service,
27 PrefService* pref_service)
28 : pref_config_service_(pref_config_service),
29 pref_service_(pref_service) {
30 ReadPrefConfig(&pref_config_);
31 proxy_prefs_observer_.reset(
32 PrefSetObserver::CreateProxyPrefSetObserver(pref_service_, this));
33 }
34
35 virtual ~PrefProxyConfigTracker() {}
36
37 // Get the proxy configuration currently defined by preferences.
38 const net::ProxyConfig& GetProxyConfig() { return pref_config_; }
39
40 private:
41 // NotificationObserver implementation:
42 virtual void Observe(NotificationType type,
43 const NotificationSource& source,
44 const NotificationDetails& details);
45
46 // Install a new configuration (to be called on the IO thread).
47 void InstallProxyConfig(const net::ProxyConfig& config);
48
49 // Creates a proxy configuration from proxy-related preferences. Sets |config|
50 // to invalid if there's no proxy configuration defined in prefs.
51 void ReadPrefConfig(net::ProxyConfig* config);
52
53 // Configuration as defined by prefs. Only to be accessed from the IO thread
54 // (expect for construction).
55 net::ProxyConfig pref_config_;
56
57 base::WeakPtr<PrefProxyConfigService> pref_config_service_;
eroman 2010/11/17 02:14:49 WeakPtr is not threadsafe. Is it valid for this to
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Replaced this hack with a proper observer interfac
58 PrefService* pref_service_;
59 scoped_ptr<PrefSetObserver> proxy_prefs_observer_;
60
61 DISALLOW_COPY_AND_ASSIGN(PrefProxyConfigTracker);
62 };
63
64 void PrefProxyConfigService::PrefProxyConfigTracker::Observe(
65 NotificationType type,
66 const NotificationSource& source,
67 const NotificationDetails& details) {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69 if (type == NotificationType::PREF_CHANGED &&
70 Source<PrefService>(source).ptr() == pref_service_) {
71 net::ProxyConfig new_config;
72 ReadPrefConfig(&new_config);
73 BrowserThread::PostTask(
74 BrowserThread::IO, FROM_HERE,
75 NewRunnableMethod(this,
76 &PrefProxyConfigTracker::InstallProxyConfig,
77 new_config));
78 } else {
79 NOTREACHED() << "Unexpected notification of type " << type.value;
80 }
81 }
82
83 void PrefProxyConfigService::PrefProxyConfigTracker::InstallProxyConfig(
84 const net::ProxyConfig& config) {
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
86 pref_config_ = config;
87 if (pref_config_service_.get())
88 pref_config_service_->PrefProxyConfigChanged();
89 }
90
91 void PrefProxyConfigService::PrefProxyConfigTracker::ReadPrefConfig(
92 net::ProxyConfig* config) {
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94
95 // Invalidate the configuration.
96 config->set_id(net::ProxyConfig::INVALID_ID);
eroman 2010/11/17 02:14:49 Please avoid using the set_id (see my later commen
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Done.
97
98 // Scan for all "enable" type proxy switches.
99 static const char* proxy_prefs[] = {
100 prefs::kProxyPacUrl,
101 prefs::kProxyServer,
102 prefs::kProxyBypassList,
103 prefs::kProxyAutoDetect
104 };
105
106 // Check whether the preference system holds a valid proxy configuration. Note
107 // that preferences coming from a lower-priority source than the user settings
108 // are ignored. That's because chrome treats the system settings as the
109 // default values, which should apply if there's no explicit value forced by
110 // policy or the user.
111 bool found_enable_proxy_pref = false;
112 for (size_t i = 0; i < arraysize(proxy_prefs); i++) {
113 const PrefService::Preference* pref =
114 pref_service_->FindPreference(proxy_prefs[i]);
115 DCHECK(pref);
116 if (pref && (!pref->IsUserModifiable() || pref->HasUserSetting())) {
117 found_enable_proxy_pref = true;
118 break;
119 }
120 }
121
122 if (!found_enable_proxy_pref &&
123 !pref_service_->GetBoolean(prefs::kNoProxyServer)) {
124 return;
125 }
126
127 // There is a valid configuration present.
128 config->set_id(1);
129
130 if (pref_service_->GetBoolean(prefs::kNoProxyServer)) {
131 // Ignore all the other proxy config preferences if the use of a proxy
132 // has been explicitly disabled.
133 return;
134 }
135
136 if (pref_service_->HasPrefPath(prefs::kProxyServer)) {
137 std::string proxy_server = pref_service_->GetString(prefs::kProxyServer);
138 config->proxy_rules().ParseFromString(proxy_server);
139 }
140
141 if (pref_service_->HasPrefPath(prefs::kProxyPacUrl)) {
142 std::string proxy_pac = pref_service_->GetString(prefs::kProxyPacUrl);
143 config->set_pac_url(GURL(proxy_pac));
144 }
145
146 config->set_auto_detect(pref_service_->GetBoolean(prefs::kProxyAutoDetect));
147
148 if (pref_service_->HasPrefPath(prefs::kProxyBypassList)) {
149 std::string proxy_bypass =
150 pref_service_->GetString(prefs::kProxyBypassList);
151 config->proxy_rules().bypass_rules.ParseFromString(proxy_bypass);
152 }
153 }
154
155 PrefProxyConfigService::PrefProxyConfigService(
156 PrefService* pref_service,
157 net::ProxyConfigService* base_service)
158 : base_service_(base_service),
159 current_id_(1) {
160 pref_config_tracker_ = new PrefProxyConfigTracker(AsWeakPtr(), pref_service);
161 base_service_->AddObserver(this);
162 }
163
164 PrefProxyConfigService::~PrefProxyConfigService() {
165 base_service_->RemoveObserver(this);
166 }
167
168 void PrefProxyConfigService::PrefProxyConfigChanged() {
169 ++current_id_;
eroman 2010/11/17 02:14:49 What is the use-case for this ID number? Please ju
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Done.
170 net::ProxyConfig current_config;
171 GetLatestProxyConfig(&current_config);
eroman 2010/11/17 02:14:49 Important: you are disregarding the return value f
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Done.
172 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
173 OnProxyConfigChanged(current_config));
174 }
175
176 void PrefProxyConfigService::AddObserver(
177 net::ProxyConfigService::Observer* observer) {
178 observers_.AddObserver(observer);
179 }
180
181 void PrefProxyConfigService::RemoveObserver(
182 net::ProxyConfigService::Observer* observer) {
183 observers_.RemoveObserver(observer);
184 }
185
186 bool PrefProxyConfigService::GetLatestProxyConfig(net::ProxyConfig* config) {
187 const net::ProxyConfig& pref_config(pref_config_tracker_->GetProxyConfig());
188 if (pref_config.is_valid()) {
eroman 2010/11/17 02:14:49 See comment about not using the IDs. If you decide
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Done.
189 *config = pref_config;
190 config->set_id(current_id_);
191 return true;
192 }
193
194 bool result = base_service_->GetLatestProxyConfig(config);
195 if (config->is_valid())
196 config->set_id(current_id_);
197 return result;
198 }
199
200 void PrefProxyConfigService::OnLazyPoll() {
201 base_service_->OnLazyPoll();
202 }
203
204 void PrefProxyConfigService::OnProxyConfigChanged(
205 const net::ProxyConfig& config) {
206 if (!pref_config_tracker_->GetProxyConfig().is_valid()) {
eroman 2010/11/17 02:14:49 See earlier comment, please don't use the ID field
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Done.
207 net::ProxyConfig new_config = config;
208 new_config.set_id(++current_id_);
eroman 2010/11/17 02:14:49 Shouldn't be a need for the ID.
Mattias Nissler (ping if slow) 2010/11/17 12:55:37 Done.
209 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
210 OnProxyConfigChanged(new_config));
211 }
212 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698