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

Side by Side Diff: chrome/browser/chromeos/proxy_config_service_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, 2 months 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/chromeos/proxy_config_service_impl.h" 5 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
6 6
7 #include <ostream> 7 #include <ostream>
8 8
9 #include "base/bind.h"
9 #include "base/json/json_value_serializer.h" 10 #include "base/json/json_value_serializer.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "base/task.h"
13 #include "chrome/browser/chromeos/cros/cros_library.h" 13 #include "chrome/browser/chromeos/cros/cros_library.h"
14 #include "chrome/browser/chromeos/cros_settings_names.h" 14 #include "chrome/browser/chromeos/cros_settings_names.h"
15 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" 15 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
16 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/prefs/proxy_config_dictionary.h" 17 #include "chrome/browser/prefs/proxy_config_dictionary.h"
17 #include "chrome/browser/prefs/proxy_prefs.h" 18 #include "chrome/browser/prefs/proxy_prefs.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/common/chrome_notification_types.h"
21 #include "chrome/common/pref_names.h"
18 #include "content/browser/browser_thread.h" 22 #include "content/browser/browser_thread.h"
23 #include "content/common/notification_details.h"
24 #include "content/common/notification_source.h"
19 #include "grit/generated_resources.h" 25 #include "grit/generated_resources.h"
20 #include "ui/base/l10n/l10n_util.h" 26 #include "ui/base/l10n/l10n_util.h"
21 27
22 namespace em = enterprise_management; 28 namespace em = enterprise_management;
23 29
24 namespace chromeos { 30 namespace chromeos {
25 31
26 namespace { 32 namespace {
27 33
28 const char* SourceToString(ProxyConfigServiceImpl::ProxyConfig::Source source) { 34 const char* ModeToString(ProxyConfigServiceImpl::ProxyConfig::Mode mode) {
29 switch (source) { 35 switch (mode) {
30 case ProxyConfigServiceImpl::ProxyConfig::SOURCE_NONE: 36 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT:
31 return "SOURCE_NONE"; 37 return "direct";
32 case ProxyConfigServiceImpl::ProxyConfig::SOURCE_POLICY: 38 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT:
33 return "SOURCE_POLICY"; 39 return "auto-detect";
34 case ProxyConfigServiceImpl::ProxyConfig::SOURCE_OWNER: 40 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT:
35 return "SOURCE_OWNER"; 41 return "pacurl";
42 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY:
43 return "single-proxy";
44 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME:
45 return "proxy-per-scheme";
36 } 46 }
37 NOTREACHED() << "Unrecognized source type"; 47 NOTREACHED() << "Unrecognized mode type";
38 return ""; 48 return "";
39 } 49 }
40 50
51 const char* ConfigStateToString(ProxyPrefs::ConfigState state) {
52 switch (state) {
53 case ProxyPrefs::CONFIG_POLICY:
54 return "config_policy";
55 case ProxyPrefs::CONFIG_EXTENSION:
56 return "config_extension";
57 case ProxyPrefs::CONFIG_OTHER_PRECEDE:
58 return "config_other_precede";
59 case ProxyPrefs::CONFIG_SYSTEM:
60 return "config_network"; // For ChromeOS, system is network.
61 case ProxyPrefs::CONFIG_FALLBACK:
62 return "config_recommended"; // Fallback is recommended.
63 case ProxyPrefs::CONFIG_UNSET:
64 return "config_unset";
65 }
66 NOTREACHED() << "Unrecognized config state type";
67 return "";
68 }
69
70 // Only unblock if needed for debugging.
71 #if defined(NEED_DEBUG_LOG)
41 std::ostream& operator<<(std::ostream& out, 72 std::ostream& operator<<(std::ostream& out,
42 const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) { 73 const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) {
Mattias Nissler (ping if slow) 2011/10/24 10:18:28 arguments on multiple lines should line up.
kuan 2011/10/25 02:01:54 it won't fit if i align the arguments.
Mattias Nissler (ping if slow) 2011/10/25 12:43:11 Then break line 72 after (, the style guide says t
kuan 2011/10/25 16:01:50 Done.
43 out << " " << SourceToString(proxy.source) << "\n" 74 out << (proxy.server.is_valid() ? proxy.server.ToURI() : "") << "\n";
44 << " server: " << (proxy.server.is_valid() ? proxy.server.ToURI() : "")
45 << "\n";
46 return out; 75 return out;
47 } 76 }
48 77
49 std::ostream& operator<<(std::ostream& out, 78 std::ostream& operator<<(std::ostream& out,
50 const ProxyConfigServiceImpl::ProxyConfig& config) { 79 const ProxyConfigServiceImpl::ProxyConfig& config) {
51 switch (config.mode) { 80 switch (config.mode) {
52 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT: 81 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT:
53 out << "Direct connection:\n "
54 << SourceToString(config.automatic_proxy.source) << "\n";
55 break;
56 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT: 82 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT:
57 out << "Auto detection:\n " 83 out << ModeToString(config.mode) << ", "
58 << SourceToString(config.automatic_proxy.source) << "\n"; 84 << ConfigStateToString(config.state) << "\n";
59 break; 85 break;
60 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT: 86 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT:
61 out << "Custom PAC script:\n " 87 out << ModeToString(config.mode) << ", "
62 << SourceToString(config.automatic_proxy.source) 88 << ConfigStateToString(config.state)
63 << "\n PAC: " << config.automatic_proxy.pac_url << "\n"; 89 << "\n PAC: " << config.automatic_proxy.pac_url << "\n";
64 break; 90 break;
65 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY: 91 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY:
66 out << "Single proxy:\n" << config.single_proxy; 92 out << ModeToString(config.mode) << ", "
93 << ConfigStateToString(config.state) << "\n " << config.single_proxy;
67 break; 94 break;
68 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME: 95 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME:
69 out << "HTTP proxy: " << config.http_proxy; 96 out << ModeToString(config.mode) << ", "
70 out << "HTTPS proxy: " << config.https_proxy; 97 << ConfigStateToString(config.state) << "\n"
71 out << "FTP proxy: " << config.ftp_proxy; 98 << " HTTP: " << config.http_proxy
72 out << "SOCKS proxy: " << config.socks_proxy; 99 << " HTTPS: " << config.https_proxy
100 << " FTP: " << config.ftp_proxy
101 << " SOCKS: " << config.socks_proxy;
73 break; 102 break;
74 default: 103 default:
75 NOTREACHED() << "Unrecognized proxy config mode"; 104 NOTREACHED() << "Unrecognized proxy config mode";
76 break; 105 break;
77 } 106 }
78 if (config.mode == ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY || 107 if (config.mode == ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY ||
79 config.mode == 108 config.mode ==
80 ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) { 109 ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) {
81 out << "Bypass list: "; 110 out << "Bypass list: ";
82 if (config.bypass_rules.rules().empty()) { 111 if (config.bypass_rules.rules().empty()) {
83 out << "[None]"; 112 out << "[None]";
84 } else { 113 } else {
85 const net::ProxyBypassRules& bypass_rules = config.bypass_rules; 114 const net::ProxyBypassRules& bypass_rules = config.bypass_rules;
86 net::ProxyBypassRules::RuleList::const_iterator it; 115 net::ProxyBypassRules::RuleList::const_iterator it;
87 for (it = bypass_rules.rules().begin(); 116 for (it = bypass_rules.rules().begin();
88 it != bypass_rules.rules().end(); ++it) { 117 it != bypass_rules.rules().end(); ++it) {
89 out << "\n " << (*it)->ToString(); 118 out << "\n " << (*it)->ToString();
90 } 119 }
91 } 120 }
92 } 121 }
93 return out; 122 return out;
94 } 123 }
95 124
96 std::string ProxyConfigToString( 125 std::string ProxyConfigToString(
97 const ProxyConfigServiceImpl::ProxyConfig& proxy_config) { 126 const ProxyConfigServiceImpl::ProxyConfig& proxy_config) {
98 std::ostringstream stream; 127 std::ostringstream stream;
99 stream << proxy_config; 128 stream << proxy_config;
100 return stream.str(); 129 return stream.str();
101 } 130 }
131 #endif // defined(NEED_DEBUG_LOG)
102 132
103 } // namespace 133 } // namespace
104 134
105 //---------- ProxyConfigServiceImpl::ProxyConfig::Setting methods --------------
106
107 bool ProxyConfigServiceImpl::ProxyConfig::Setting::CanBeWrittenByUser(
108 bool user_is_owner) {
109 // Setting can only be written by user if user is owner and setting is not
110 // from policy.
111 return user_is_owner && source != ProxyConfig::SOURCE_POLICY;
112 }
113
114 //----------- ProxyConfigServiceImpl::ProxyConfig: public methods -------------- 135 //----------- ProxyConfigServiceImpl::ProxyConfig: public methods --------------
115 136
116 ProxyConfigServiceImpl::ProxyConfig::ProxyConfig() : mode(MODE_DIRECT) {} 137 ProxyConfigServiceImpl::ProxyConfig::ProxyConfig()
138 : mode(MODE_DIRECT),
139 state(ProxyPrefs::CONFIG_UNSET),
140 user_modifiable(true) {}
117 141
118 ProxyConfigServiceImpl::ProxyConfig::~ProxyConfig() {} 142 ProxyConfigServiceImpl::ProxyConfig::~ProxyConfig() {}
119 143
120 void ProxyConfigServiceImpl::ProxyConfig::ToNetProxyConfig( 144 void ProxyConfigServiceImpl::ProxyConfig::ToNetProxyConfig(
121 net::ProxyConfig* net_config) { 145 net::ProxyConfig* net_config) {
122 switch (mode) { 146 switch (mode) {
123 case MODE_DIRECT: 147 case MODE_DIRECT:
124 *net_config = net::ProxyConfig::CreateDirect(); 148 *net_config = net::ProxyConfig::CreateDirect();
125 break; 149 break;
126 case MODE_AUTO_DETECT: 150 case MODE_AUTO_DETECT:
127 *net_config = net::ProxyConfig::CreateAutoDetect(); 151 *net_config = net::ProxyConfig::CreateAutoDetect();
128 break; 152 break;
129 case MODE_PAC_SCRIPT: 153 case MODE_PAC_SCRIPT:
130 *net_config = net::ProxyConfig::CreateFromCustomPacURL( 154 *net_config = net::ProxyConfig::CreateFromCustomPacURL(
131 automatic_proxy.pac_url); 155 automatic_proxy.pac_url);
132 break; 156 break;
133 case MODE_SINGLE_PROXY: 157 case MODE_SINGLE_PROXY:
134 *net_config = net::ProxyConfig(); 158 *net_config = net::ProxyConfig();
135 net_config->proxy_rules().type = 159 net_config->proxy_rules().type =
136 net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; 160 net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
137 net_config->proxy_rules().single_proxy = single_proxy.server; 161 net_config->proxy_rules().single_proxy = single_proxy.server;
138 net_config->proxy_rules().bypass_rules = bypass_rules; 162 net_config->proxy_rules().bypass_rules = bypass_rules;
163 net_config->proxy_rules().bypass_rules.AddRuleToBypassLocal();
139 break; 164 break;
140 case MODE_PROXY_PER_SCHEME: 165 case MODE_PROXY_PER_SCHEME:
141 *net_config = net::ProxyConfig(); 166 *net_config = net::ProxyConfig();
142 net_config->proxy_rules().type = 167 net_config->proxy_rules().type =
143 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; 168 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
144 net_config->proxy_rules().proxy_for_http = http_proxy.server; 169 net_config->proxy_rules().proxy_for_http = http_proxy.server;
145 net_config->proxy_rules().proxy_for_https = https_proxy.server; 170 net_config->proxy_rules().proxy_for_https = https_proxy.server;
146 net_config->proxy_rules().proxy_for_ftp = ftp_proxy.server; 171 net_config->proxy_rules().proxy_for_ftp = ftp_proxy.server;
147 net_config->proxy_rules().fallback_proxy = socks_proxy.server; 172 net_config->proxy_rules().fallback_proxy = socks_proxy.server;
148 net_config->proxy_rules().bypass_rules = bypass_rules; 173 net_config->proxy_rules().bypass_rules = bypass_rules;
174 net_config->proxy_rules().bypass_rules.AddRuleToBypassLocal();
149 break; 175 break;
150 default: 176 default:
151 NOTREACHED() << "Unrecognized proxy config mode"; 177 NOTREACHED() << "Unrecognized proxy config mode";
152 break; 178 break;
153 } 179 }
154 } 180 }
155 181
156 bool ProxyConfigServiceImpl::ProxyConfig::CanBeWrittenByUser( 182 bool ProxyConfigServiceImpl::ProxyConfig::FromNetProxyConfig(
157 bool user_is_owner, const std::string& scheme) { 183 const net::ProxyConfig& net_config) {
158 // Setting can only be written by user if user is owner and setting is not 184 *this = ProxyConfigServiceImpl::ProxyConfig(); // Reset to default.
159 // from policy. 185 const net::ProxyConfig::ProxyRules& rules = net_config.proxy_rules();
160 Setting* setting = NULL; 186 switch (rules.type) {
187 case net::ProxyConfig::ProxyRules::TYPE_NO_RULES:
188 if (!net_config.HasAutomaticSettings()) {
189 mode = ProxyConfig::MODE_DIRECT;
190 } else if (net_config.auto_detect()) {
191 mode = ProxyConfig::MODE_AUTO_DETECT;
192 } else if (net_config.has_pac_url()) {
193 mode = ProxyConfig::MODE_PAC_SCRIPT;
194 automatic_proxy.pac_url = net_config.pac_url();
195 } else {
196 return false;
197 }
198 return true;
199 case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY:
200 if (!rules.single_proxy.is_valid())
201 return false;
202 mode = MODE_SINGLE_PROXY;
203 single_proxy.server = rules.single_proxy;
204 bypass_rules = rules.bypass_rules;
205 return true;
206 case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME:
207 // Make sure we have valid server for at least one of the protocols.
208 if (!rules.proxy_for_http.is_valid() &&
209 !rules.proxy_for_https.is_valid() &&
210 !rules.proxy_for_ftp.is_valid() &&
211 !rules.fallback_proxy.is_valid()) {
212 return false;
213 }
214 mode = MODE_PROXY_PER_SCHEME;
215 if (rules.proxy_for_http.is_valid())
216 http_proxy.server = rules.proxy_for_http;
217 if (rules.proxy_for_https.is_valid())
218 https_proxy.server = rules.proxy_for_https;
219 if (rules.proxy_for_ftp.is_valid())
220 ftp_proxy.server = rules.proxy_for_ftp;
221 if (rules.fallback_proxy.is_valid())
222 socks_proxy.server = rules.fallback_proxy;
223 bypass_rules = rules.bypass_rules;
224 return true;
225 default:
226 NOTREACHED() << "Unrecognized proxy config mode";
227 break;
228 }
229 return false;
230 }
231
232 DictionaryValue* ProxyConfigServiceImpl::ProxyConfig::ToPrefProxyConfig() {
161 switch (mode) { 233 switch (mode) {
162 case MODE_DIRECT: 234 case MODE_DIRECT: {
163 case MODE_AUTO_DETECT: 235 return ProxyConfigDictionary::CreateDirect();
164 case MODE_PAC_SCRIPT: 236 }
165 setting = &automatic_proxy; 237 case MODE_AUTO_DETECT: {
166 break; 238 return ProxyConfigDictionary::CreateAutoDetect();
167 case MODE_SINGLE_PROXY: 239 }
168 setting = &single_proxy; 240 case MODE_PAC_SCRIPT: {
169 break; 241 return ProxyConfigDictionary::CreatePacScript(
170 case MODE_PROXY_PER_SCHEME: 242 automatic_proxy.pac_url.spec(), false);
171 setting = MapSchemeToProxy(scheme); 243 }
172 break; 244 case MODE_SINGLE_PROXY: {
245 std::string spec;
246 if (single_proxy.server.is_valid())
247 spec = single_proxy.server.ToURI();
248 return ProxyConfigDictionary::CreateFixedServers(
249 spec, bypass_rules.ToString());
250 }
251 case MODE_PROXY_PER_SCHEME: {
252 std::string spec;
253 EncodeAndAppendProxyServer("http", http_proxy.server, &spec);
254 EncodeAndAppendProxyServer("https", https_proxy.server, &spec);
255 EncodeAndAppendProxyServer("ftp", ftp_proxy.server, &spec);
256 EncodeAndAppendProxyServer("socks", socks_proxy.server, &spec);
257 return ProxyConfigDictionary::CreateFixedServers(
258 spec, bypass_rules.ToString());
259 }
173 default: 260 default:
174 break; 261 break;
175 } 262 }
176 if (!setting) { 263 NOTREACHED() << "Unrecognized proxy config mode for preference";
177 NOTREACHED() << "Unrecognized proxy config mode"; 264 return NULL;
265 }
266
267 bool ProxyConfigServiceImpl::ProxyConfig::FromPrefProxyConfig(
268 const DictionaryValue* dict) {
269 ProxyConfigDictionary proxy_dict(dict);
270
271 *this = ProxyConfigServiceImpl::ProxyConfig(); // Reset to default.
272
273 ProxyPrefs::ProxyMode proxy_mode;
274 if (!proxy_dict.GetMode(&proxy_mode)) {
275 // Fall back to system settings if the mode preference is invalid.
178 return false; 276 return false;
179 } 277 }
180 return setting->CanBeWrittenByUser(user_is_owner); 278
279 switch (proxy_mode) {
280 case ProxyPrefs::MODE_SYSTEM:
281 // Use system settings, so we shouldn't use |this| proxy config.
282 return false;
283 case ProxyPrefs::MODE_DIRECT:
284 // Ignore all the other proxy config preferences if the use of a proxy
285 // has been explicitly disabled.
286 return true;
287 case ProxyPrefs::MODE_AUTO_DETECT:
288 mode = MODE_AUTO_DETECT;
289 return true;
290 case ProxyPrefs::MODE_PAC_SCRIPT: {
291 std::string proxy_pac;
292 if (!proxy_dict.GetPacUrl(&proxy_pac)) {
293 LOG(ERROR) << "Proxy settings request PAC script but do not specify "
294 << "its URL. Falling back to direct connection.";
295 return true;
296 }
297 GURL proxy_pac_url(proxy_pac);
298 if (!proxy_pac_url.is_valid()) {
299 LOG(ERROR) << "Invalid proxy PAC url: " << proxy_pac;
300 return true;
301 }
302 mode = MODE_PAC_SCRIPT;
303 automatic_proxy.pac_url = proxy_pac_url;
304 return true;
305 }
306 case ProxyPrefs::MODE_FIXED_SERVERS: {
307 std::string proxy_server;
308 if (!proxy_dict.GetProxyServer(&proxy_server)) {
309 LOG(ERROR) << "Proxy settings request fixed proxy servers but do not "
310 << "specify their URLs. Falling back to direct connection.";
311 return true;
312 }
313 net::ProxyConfig::ProxyRules proxy_rules;
314 proxy_rules.ParseFromString(proxy_server);
315 if (proxy_rules.type == net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY) {
316 mode = MODE_SINGLE_PROXY;
317 single_proxy.server = proxy_rules.single_proxy;
318 } else if (proxy_rules.type ==
319 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) {
320 mode = MODE_PROXY_PER_SCHEME;
321 http_proxy.server = proxy_rules.proxy_for_http;
322 https_proxy.server = proxy_rules.proxy_for_https;
323 ftp_proxy.server = proxy_rules.proxy_for_ftp;
324 socks_proxy.server = proxy_rules.fallback_proxy;
325 } else {
326 LOG(ERROR) << "Proxy settings request fixed proxy servers but do not "
327 << "have valid proxy rules type. "
328 << "Falling back to direct connection.";
329 return true;
330 }
331
332 std::string proxy_bypass;
333 if (proxy_dict.GetBypassList(&proxy_bypass))
334 bypass_rules.ParseFromString(proxy_bypass);
335 return true;
336 }
337 case ProxyPrefs::kModeCount: {
338 // Fall through to NOTREACHED().
339 }
340 }
341 NOTREACHED() << "Unknown proxy mode, falling back to system settings.";
342 return false;
181 } 343 }
182 344
183 ProxyConfigServiceImpl::ProxyConfig::ManualProxy* 345 ProxyConfigServiceImpl::ProxyConfig::ManualProxy*
184 ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy( 346 ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy(
185 const std::string& scheme) { 347 const std::string& scheme) {
186 if (scheme == "http") 348 if (scheme == "http")
187 return &http_proxy; 349 return &http_proxy;
188 if (scheme == "https") 350 if (scheme == "https")
189 return &https_proxy; 351 return &https_proxy;
190 if (scheme == "ftp") 352 if (scheme == "ftp")
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 JSONStringValueSerializer serializer(input); 428 JSONStringValueSerializer serializer(input);
267 scoped_ptr<Value> value(serializer.Deserialize(NULL, NULL)); 429 scoped_ptr<Value> value(serializer.Deserialize(NULL, NULL));
268 if (!value.get() || value->GetType() != Value::TYPE_DICTIONARY) 430 if (!value.get() || value->GetType() != Value::TYPE_DICTIONARY)
269 return false; 431 return false;
270 DictionaryValue* proxy_dict = static_cast<DictionaryValue*>(value.get()); 432 DictionaryValue* proxy_dict = static_cast<DictionaryValue*>(value.get());
271 return FromPrefProxyConfig(proxy_dict); 433 return FromPrefProxyConfig(proxy_dict);
272 } 434 }
273 435
274 bool ProxyConfigServiceImpl::ProxyConfig::Equals( 436 bool ProxyConfigServiceImpl::ProxyConfig::Equals(
275 const ProxyConfig& other) const { 437 const ProxyConfig& other) const {
438 // Intentionally ignore state which is only used for UI purposes and has no
439 // impact on network stack.
276 if (mode != other.mode) 440 if (mode != other.mode)
277 return false; 441 return false;
278 switch (mode) { 442 switch (mode) {
279 case MODE_DIRECT: 443 case MODE_DIRECT:
280 case MODE_AUTO_DETECT: 444 case MODE_AUTO_DETECT:
281 return true; 445 return true;
282 case MODE_PAC_SCRIPT: 446 case MODE_PAC_SCRIPT:
283 return automatic_proxy.pac_url == other.automatic_proxy.pac_url; 447 return automatic_proxy.pac_url == other.automatic_proxy.pac_url;
284 case MODE_SINGLE_PROXY: 448 case MODE_SINGLE_PROXY:
285 return single_proxy.server == other.single_proxy.server && 449 return single_proxy.server == other.single_proxy.server &&
286 bypass_rules.Equals(other.bypass_rules); 450 bypass_rules.Equals(other.bypass_rules);
287 case MODE_PROXY_PER_SCHEME: 451 case MODE_PROXY_PER_SCHEME:
288 return http_proxy.server == other.http_proxy.server && 452 return http_proxy.server == other.http_proxy.server &&
289 https_proxy.server == other.https_proxy.server && 453 https_proxy.server == other.https_proxy.server &&
290 ftp_proxy.server == other.ftp_proxy.server && 454 ftp_proxy.server == other.ftp_proxy.server &&
291 socks_proxy.server == other.socks_proxy.server && 455 socks_proxy.server == other.socks_proxy.server &&
292 bypass_rules.Equals(other.bypass_rules); 456 bypass_rules.Equals(other.bypass_rules);
293 default: { 457 default: {
294 NOTREACHED() << "Unrecognized proxy config mode"; 458 NOTREACHED() << "Unrecognized proxy config mode";
295 break; 459 break;
296 } 460 }
297 } 461 }
298 return false; 462 return false;
299 } 463 }
300 464
301 std::string ProxyConfigServiceImpl::ProxyConfig::ToString() const {
302 return ProxyConfigToString(*this);
303 }
304
305 //----------- ProxyConfigServiceImpl::ProxyConfig: private methods ------------- 465 //----------- ProxyConfigServiceImpl::ProxyConfig: private methods -------------
306 466
307 // static 467 // static
308 void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer( 468 void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
309 const std::string& scheme, 469 const std::string& scheme,
310 const net::ProxyServer& server, 470 const net::ProxyServer& server,
311 std::string* spec) { 471 std::string* spec) {
312 if (!server.is_valid()) 472 if (!server.is_valid())
313 return; 473 return;
314 474
315 if (!spec->empty()) 475 if (!spec->empty())
316 *spec += ';'; 476 *spec += ';';
317 477
318 if (!scheme.empty()) { 478 if (!scheme.empty()) {
319 *spec += scheme; 479 *spec += scheme;
320 *spec += "="; 480 *spec += "=";
321 } 481 }
322 *spec += server.ToURI(); 482 *spec += server.ToURI();
323 } 483 }
324 484
325 DictionaryValue* ProxyConfigServiceImpl::ProxyConfig::ToPrefProxyConfig() {
326 switch (mode) {
327 case MODE_DIRECT: {
328 return ProxyConfigDictionary::CreateDirect();
329 }
330 case MODE_AUTO_DETECT: {
331 return ProxyConfigDictionary::CreateAutoDetect();
332 }
333 case MODE_PAC_SCRIPT: {
334 return ProxyConfigDictionary::CreatePacScript(
335 automatic_proxy.pac_url.spec(), false);
336 }
337 case MODE_SINGLE_PROXY: {
338 std::string spec;
339 if (single_proxy.server.is_valid())
340 spec = single_proxy.server.ToURI();
341 return ProxyConfigDictionary::CreateFixedServers(
342 spec, bypass_rules.ToString());
343 }
344 case MODE_PROXY_PER_SCHEME: {
345 std::string spec;
346 EncodeAndAppendProxyServer("http", http_proxy.server, &spec);
347 EncodeAndAppendProxyServer("https", https_proxy.server, &spec);
348 EncodeAndAppendProxyServer("ftp", ftp_proxy.server, &spec);
349 EncodeAndAppendProxyServer("socks", socks_proxy.server, &spec);
350 return ProxyConfigDictionary::CreateFixedServers(
351 spec, bypass_rules.ToString());
352 }
353 default:
354 break;
355 }
356 NOTREACHED() << "Unrecognized proxy config mode for preference";
357 return NULL;
358 }
359
360 bool ProxyConfigServiceImpl::ProxyConfig::FromPrefProxyConfig(
361 const DictionaryValue* dict) {
362 ProxyConfigDictionary proxy_dict(dict);
363
364 *this = ProxyConfigServiceImpl::ProxyConfig(); // Reset to default.
365
366 ProxyPrefs::ProxyMode proxy_mode;
367 if (!proxy_dict.GetMode(&proxy_mode)) {
368 // Fall back to system settings if the mode preference is invalid.
369 return false;
370 }
371
372 switch (proxy_mode) {
373 case ProxyPrefs::MODE_SYSTEM:
374 // Use system settings, so we shouldn't use |this| proxy config.
375 return false;
376 case ProxyPrefs::MODE_DIRECT:
377 // Ignore all the other proxy config preferences if the use of a proxy
378 // has been explicitly disabled.
379 return true;
380 case ProxyPrefs::MODE_AUTO_DETECT:
381 mode = MODE_AUTO_DETECT;
382 return true;
383 case ProxyPrefs::MODE_PAC_SCRIPT: {
384 std::string proxy_pac;
385 if (!proxy_dict.GetPacUrl(&proxy_pac)) {
386 LOG(ERROR) << "Proxy settings request PAC script but do not specify "
387 << "its URL. Falling back to direct connection.";
388 return true;
389 }
390 GURL proxy_pac_url(proxy_pac);
391 if (!proxy_pac_url.is_valid()) {
392 LOG(ERROR) << "Invalid proxy PAC url: " << proxy_pac;
393 return true;
394 }
395 mode = MODE_PAC_SCRIPT;
396 automatic_proxy.pac_url = proxy_pac_url;
397 return true;
398 }
399 case ProxyPrefs::MODE_FIXED_SERVERS: {
400 std::string proxy_server;
401 if (!proxy_dict.GetProxyServer(&proxy_server)) {
402 LOG(ERROR) << "Proxy settings request fixed proxy servers but do not "
403 << "specify their URLs. Falling back to direct connection.";
404 return true;
405 }
406 net::ProxyConfig::ProxyRules proxy_rules;
407 proxy_rules.ParseFromString(proxy_server);
408 if (proxy_rules.type == net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY) {
409 mode = MODE_SINGLE_PROXY;
410 single_proxy.server = proxy_rules.single_proxy;
411 } else if (proxy_rules.type ==
412 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) {
413 mode = MODE_PROXY_PER_SCHEME;
414 http_proxy.server = proxy_rules.proxy_for_http;
415 https_proxy.server = proxy_rules.proxy_for_https;
416 ftp_proxy.server = proxy_rules.proxy_for_ftp;
417 socks_proxy.server = proxy_rules.fallback_proxy;
418 } else {
419 LOG(ERROR) << "Proxy settings request fixed proxy servers but do not "
420 << "have valid proxy rules type. "
421 << "Falling back to direct connection.";
422 return true;
423 }
424
425 std::string proxy_bypass;
426 if (proxy_dict.GetBypassList(&proxy_bypass)) {
427 bypass_rules.ParseFromString(proxy_bypass);
428 }
429 return true;
430 }
431 case ProxyPrefs::kModeCount: {
432 // Fall through to NOTREACHED().
433 }
434 }
435 NOTREACHED() << "Unknown proxy mode, falling back to system settings.";
436 return false;
437 }
438
439 //------------------- ProxyConfigServiceImpl: public methods ------------------- 485 //------------------- ProxyConfigServiceImpl: public methods -------------------
440 486
441 ProxyConfigServiceImpl::ProxyConfigServiceImpl() 487 ProxyConfigServiceImpl::ProxyConfigServiceImpl(PrefService* pref_service)
442 : testing_(false), 488 : PrefProxyConfigTracker(pref_service),
443 can_post_task_(false), 489 active_config_state_(ProxyPrefs::CONFIG_UNSET),
444 config_availability_(net::ProxyConfigService::CONFIG_UNSET),
445 use_shared_proxies_(true) { 490 use_shared_proxies_(true) {
446 // Start async fetch of proxy config from settings persisted on device. 491 // Start async fetch of proxy config from settings persisted on device.
447 if (CrosLibrary::Get()->EnsureLoaded()) { 492 if (CrosLibrary::Get()->EnsureLoaded()) {
448 retrieve_property_op_ = SignedSettings::CreateRetrievePropertyOp( 493 retrieve_property_op_ = SignedSettings::CreateRetrievePropertyOp(
449 kSettingProxyEverywhere, this); 494 kSettingProxyEverywhere, this);
450 if (retrieve_property_op_) { 495 if (retrieve_property_op_) {
451 retrieve_property_op_->Execute(); 496 retrieve_property_op_->Execute();
452 VLOG(1) << "Start retrieving proxy setting from device"; 497 VLOG(1) << this << ": Start retrieving proxy setting from device";
453 } else { 498 } else {
454 VLOG(1) << "Fail to retrieve proxy setting from device"; 499 VLOG(1) << this << ": Fail to retrieve proxy setting from device";
455 } 500 }
456 } 501 }
457 502
503 // Register for flimflam network notifications.
458 NetworkLibrary* network_lib = CrosLibrary::Get()->GetNetworkLibrary(); 504 NetworkLibrary* network_lib = CrosLibrary::Get()->GetNetworkLibrary();
459 OnActiveNetworkChanged(network_lib, network_lib->active_network()); 505 OnActiveNetworkChanged(network_lib, network_lib->active_network());
460 network_lib->AddNetworkManagerObserver(this); 506 network_lib->AddNetworkManagerObserver(this);
461 507
462 can_post_task_ = true; 508 // Register for notifications of UseSharedProxies user preference.
463 } 509 if (pref_service->FindPreference(prefs::kUseSharedProxies)) {
464 510 use_shared_proxies_pref_.Init(prefs::kUseSharedProxies, pref_service, this);
465 ProxyConfigServiceImpl::ProxyConfigServiceImpl(const ProxyConfig& init_config) 511 SetUseSharedProxies(use_shared_proxies_pref_.GetValue());
466 : testing_(false), 512 }
467 can_post_task_(true),
468 config_availability_(net::ProxyConfigService::CONFIG_VALID),
469 use_shared_proxies_(true) {
470 active_config_ = init_config;
471 // Update the IO-accessible copy in |cached_config_| as well.
472 cached_config_ = active_config_;
473 } 513 }
474 514
475 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() { 515 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() {
476 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary(); 516 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary();
477 if (netlib) { 517 if (netlib) {
478 netlib->RemoveNetworkManagerObserver(this); 518 netlib->RemoveNetworkManagerObserver(this);
479 netlib->RemoveObserverForAllNetworks(this); 519 netlib->RemoveObserverForAllNetworks(this);
480 } 520 }
481 } 521 }
482 522
523 void ProxyConfigServiceImpl::UISetCurrentNetwork(
524 const std::string& current_network) {
525 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
526 current_network);
527 if (!network) {
528 ResetUICache();
529 LOG(ERROR) << "can't find requested network " << current_network;
530 return;
531 }
532 current_ui_network_ = current_network;
533 OnUISetCurrentNetwork(network);
534 }
535
536 void ProxyConfigServiceImpl::UIMakeActiveNetworkCurrent() {
537 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
538 active_network_);
539 if (!network) {
540 ResetUICache();
541 LOG(ERROR) << "can't find requested network " << active_network_;
542 return;
543 }
544 current_ui_network_ = active_network_;
545 OnUISetCurrentNetwork(network);
546 }
547
548 void ProxyConfigServiceImpl::UIGetCurrentNetworkName(
549 std::string* network_name) {
550 if (!network_name)
551 return;
552 network_name->clear();
553 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
554 current_ui_network_);
555 if (!network) {
556 LOG(ERROR) << "can't find requested network " << current_ui_network_;
557 return;
558 }
559 if (network->name().empty() && network->type() == chromeos::TYPE_ETHERNET) {
560 *network_name =
561 l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
562 } else {
563 *network_name = network->name();
564 }
565 }
566
483 void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) { 567 void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) {
484 // Should be called from UI thread. 568 // Simply returns the copy last set from UI via UISetCurrentNetwork or
485 CheckCurrentlyOnUIThread(); 569 // UIMakeActiveNetworkCurrent.
486 // Simply returns the copy on the UI thread.
487 *config = current_ui_config_; 570 *config = current_ui_config_;
488 } 571 }
489 572
490 bool ProxyConfigServiceImpl::UISetCurrentNetwork(
491 const std::string& current_network) {
492 // Should be called from UI thread.
493 CheckCurrentlyOnUIThread();
494 if (current_ui_network_ == current_network)
495 return false;
496 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
497 current_network);
498 if (!network) {
499 LOG(ERROR) << "can't find requested network " << current_network;
500 return false;
501 }
502 current_ui_network_ = current_network;
503 current_ui_config_ = ProxyConfig();
504 SetCurrentNetworkName(network);
505 if (!network->proxy_config().empty())
506 current_ui_config_.DeserializeForNetwork(network->proxy_config());
507 VLOG(1) << "current ui network: "
508 << (current_ui_network_name_.empty() ?
509 current_ui_network_ : current_ui_network_name_)
510 << ", proxy mode: " << current_ui_config_.mode;
511 return true;
512 }
513
514 bool ProxyConfigServiceImpl::UIMakeActiveNetworkCurrent() {
515 // Should be called from UI thread.
516 CheckCurrentlyOnUIThread();
517 if (current_ui_network_ == active_network_)
518 return false;
519 Network* network = NULL;
520 if (!testing_) {
521 network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
522 active_network_);
523 if (!network) {
524 LOG(ERROR) << "can't find requested network " << active_network_;
525 return false;
526 }
527 }
528 current_ui_network_ = active_network_;
529 current_ui_config_ = active_config_;
530 SetCurrentNetworkName(network);
531 VLOG(1) << "current ui network: "
532 << (current_ui_network_name_.empty() ?
533 current_ui_network_ : current_ui_network_name_)
534 << ", proxy mode: " << current_ui_config_.mode;
535 return true;
536 }
537
538 void ProxyConfigServiceImpl::UISetUseSharedProxies(bool use_shared) {
539 // Should be called from UI thread.
540 CheckCurrentlyOnUIThread();
541
542 // Reset all UI-related variables so that the next opening of proxy
543 // configuration dialog of any network will trigger javascript reloading of
544 // (possibly) new proxy settings.
545 current_ui_network_.clear();
546 current_ui_network_name_.clear();
547 current_ui_config_ = ProxyConfig();
548
549 if (use_shared_proxies_ == use_shared) {
550 VLOG(1) << "same use_shared_proxies = " << use_shared_proxies_;
551 return;
552 }
553 use_shared_proxies_ = use_shared;
554 VLOG(1) << "new use_shared_proxies = " << use_shared_proxies_;
555 if (active_network_.empty())
556 return;
557 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
558 active_network_);
559 if (!network) {
560 LOG(ERROR) << "can't find requested network " << active_network_;
561 return;
562 }
563 DetermineConfigFromNetwork(network);
564 }
565
566 bool ProxyConfigServiceImpl::UISetProxyConfigToDirect() { 573 bool ProxyConfigServiceImpl::UISetProxyConfigToDirect() {
567 // Should be called from UI thread.
568 CheckCurrentlyOnUIThread();
569 current_ui_config_.mode = ProxyConfig::MODE_DIRECT; 574 current_ui_config_.mode = ProxyConfig::MODE_DIRECT;
570 OnUISetProxyConfig(); 575 OnUISetProxyConfig();
571 return true; 576 return true;
572 } 577 }
573 578
574 bool ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() { 579 bool ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() {
575 // Should be called from UI thread.
576 CheckCurrentlyOnUIThread();
577 current_ui_config_.mode = ProxyConfig::MODE_AUTO_DETECT; 580 current_ui_config_.mode = ProxyConfig::MODE_AUTO_DETECT;
578 OnUISetProxyConfig(); 581 OnUISetProxyConfig();
579 return true; 582 return true;
580 } 583 }
581 584
582 bool ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& pac_url) { 585 bool ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& pac_url) {
583 // Should be called from UI thread.
584 CheckCurrentlyOnUIThread();
585 current_ui_config_.mode = ProxyConfig::MODE_PAC_SCRIPT; 586 current_ui_config_.mode = ProxyConfig::MODE_PAC_SCRIPT;
586 current_ui_config_.automatic_proxy.pac_url = pac_url; 587 current_ui_config_.automatic_proxy.pac_url = pac_url;
587 OnUISetProxyConfig(); 588 OnUISetProxyConfig();
588 return true; 589 return true;
589 } 590 }
590 591
591 bool ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy( 592 bool ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy(
592 const net::ProxyServer& server) { 593 const net::ProxyServer& server) {
593 // Should be called from UI thread.
594 CheckCurrentlyOnUIThread();
595 current_ui_config_.mode = ProxyConfig::MODE_SINGLE_PROXY; 594 current_ui_config_.mode = ProxyConfig::MODE_SINGLE_PROXY;
596 current_ui_config_.single_proxy.server = server; 595 current_ui_config_.single_proxy.server = server;
597 OnUISetProxyConfig(); 596 OnUISetProxyConfig();
598 return true; 597 return true;
599 } 598 }
600 599
601 bool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme( 600 bool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme(
602 const std::string& scheme, const net::ProxyServer& server) { 601 const std::string& scheme, const net::ProxyServer& server) {
603 // Should be called from UI thread.
604 CheckCurrentlyOnUIThread();
605 ProxyConfig::ManualProxy* proxy = current_ui_config_.MapSchemeToProxy(scheme); 602 ProxyConfig::ManualProxy* proxy = current_ui_config_.MapSchemeToProxy(scheme);
606 if (!proxy) { 603 if (!proxy) {
607 NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]"; 604 NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]";
608 return false; 605 return false;
609 } 606 }
610 current_ui_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME; 607 current_ui_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME;
611 proxy->server = server; 608 proxy->server = server;
612 OnUISetProxyConfig(); 609 OnUISetProxyConfig();
613 return true; 610 return true;
614 } 611 }
615 612
616 bool ProxyConfigServiceImpl::UISetProxyConfigBypassRules( 613 bool ProxyConfigServiceImpl::UISetProxyConfigBypassRules(
617 const net::ProxyBypassRules& bypass_rules) { 614 const net::ProxyBypassRules& bypass_rules) {
618 // Should be called from UI thread.
619 CheckCurrentlyOnUIThread();
620 if (current_ui_config_.mode != ProxyConfig::MODE_SINGLE_PROXY && 615 if (current_ui_config_.mode != ProxyConfig::MODE_SINGLE_PROXY &&
621 current_ui_config_.mode != ProxyConfig::MODE_PROXY_PER_SCHEME) { 616 current_ui_config_.mode != ProxyConfig::MODE_PROXY_PER_SCHEME) {
622 NOTREACHED(); 617 NOTREACHED();
623 VLOG(1) << "Cannot set bypass rules for proxy mode [" 618 VLOG(1) << "Cannot set bypass rules for proxy mode ["
624 << current_ui_config_.mode << "]"; 619 << current_ui_config_.mode << "]";
625 return false; 620 return false;
626 } 621 }
627 current_ui_config_.bypass_rules = bypass_rules; 622 current_ui_config_.bypass_rules = bypass_rules;
628 OnUISetProxyConfig(); 623 OnUISetProxyConfig();
629 return true; 624 return true;
630 } 625 }
631 626
632 void ProxyConfigServiceImpl::AddObserver( 627 void ProxyConfigServiceImpl::OnProxyConfigChanged(
633 net::ProxyConfigService::Observer* observer) { 628 ProxyPrefs::ConfigState config_state,
634 // Should be called from IO thread. 629 const net::ProxyConfig& config) {
635 CheckCurrentlyOnIOThread(); 630 VLOG(1) << this << ": got prefs change: " << ConfigStateToString(config_state)
636 observers_.AddObserver(observer); 631 << ", mode=" << config.proxy_rules().type;
637 } 632 Network* network = NULL;
638 633 if (!active_network_.empty()) {
639 void ProxyConfigServiceImpl::RemoveObserver( 634 network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
640 net::ProxyConfigService::Observer* observer) { 635 active_network_);
641 // Should be called from IO thread. 636 if (!network)
642 CheckCurrentlyOnIOThread(); 637 LOG(ERROR) << "can't find requested network " << active_network_;
643 observers_.RemoveObserver(observer);
644 }
645
646 net::ProxyConfigService::ConfigAvailability
647 ProxyConfigServiceImpl::IOGetProxyConfig(net::ProxyConfig* net_config) {
648 // Should be called from IO thread.
649 CheckCurrentlyOnIOThread();
650 if (config_availability_ == net::ProxyConfigService::CONFIG_VALID) {
651 VLOG(1) << "returning proxy mode=" << cached_config_.mode;
652 cached_config_.ToNetProxyConfig(net_config);
653 } 638 }
654 return config_availability_; 639 DetermineEffectiveConfig(network, true);
655 } 640 }
656 641
657 void ProxyConfigServiceImpl::OnSettingsOpCompleted( 642 void ProxyConfigServiceImpl::OnSettingsOpCompleted(
658 SignedSettings::ReturnCode code, 643 SignedSettings::ReturnCode code,
659 std::string value) { 644 std::string value) {
660 retrieve_property_op_ = NULL; 645 retrieve_property_op_ = NULL;
661 if (code != SignedSettings::SUCCESS) { 646 if (code != SignedSettings::SUCCESS) {
662 LOG(WARNING) << "Error retrieving proxy setting from device"; 647 LOG(WARNING) << "Error retrieving proxy setting from device";
663 device_config_.clear(); 648 device_config_.clear();
664 return; 649 return;
665 } 650 }
666 VLOG(1) << "Retrieved proxy setting from device, value=[" << value << "]"; 651 VLOG(1) << this << ": Retrieved proxy setting from device, value=["
652 << value << "]";
667 ProxyConfig device_config; 653 ProxyConfig device_config;
668 if (!device_config.DeserializeForDevice(value) || 654 if (!device_config.DeserializeForDevice(value) ||
669 !device_config.SerializeForNetwork(&device_config_)) { 655 !device_config.SerializeForNetwork(&device_config_)) {
670 LOG(WARNING) << "Can't deserialize device setting or serialize for network"; 656 LOG(WARNING) << "Can't deserialize device setting or serialize for network";
671 device_config_.clear(); 657 device_config_.clear();
672 return; 658 return;
673 } 659 }
674 if (!active_network_.empty()) { 660 if (!active_network_.empty()) {
675 VLOG(1) << "try migrating device config to " << active_network_; 661 VLOG(1) << this << ": try migrating device config to " << active_network_;
676 SetProxyConfigForNetwork(active_network_, device_config_, true); 662 SetProxyConfigForNetwork(active_network_, device_config_, true);
677 } 663 }
678 } 664 }
679 665
680 void ProxyConfigServiceImpl::OnNetworkManagerChanged( 666 void ProxyConfigServiceImpl::OnNetworkManagerChanged(
681 NetworkLibrary* network_lib) { 667 NetworkLibrary* network_lib) {
682 VLOG(1) << "OnNetworkManagerChanged: use-shared-proxies=" 668 VLOG(1) << this << " OnNetworkManagerChanged: use-shared-proxies="
683 << use_shared_proxies_; 669 << use_shared_proxies_;
684 OnActiveNetworkChanged(network_lib, network_lib->active_network()); 670 OnActiveNetworkChanged(network_lib, network_lib->active_network());
685 } 671 }
686 672
687 void ProxyConfigServiceImpl::OnNetworkChanged(NetworkLibrary* network_lib, 673 void ProxyConfigServiceImpl::OnNetworkChanged(NetworkLibrary* network_lib,
688 const Network* network) { 674 const Network* network) {
689 if (!network) 675 if (!network)
690 return; 676 return;
691 VLOG(1) << "OnNetworkChanged: " 677 VLOG(1) << this << " OnNetworkChanged: "
692 << (network->name().empty() ? network->service_path() : 678 << (network->name().empty() ? network->service_path() :
693 network->name()) 679 network->name())
694 << ", use-shared-proxies=" << use_shared_proxies_; 680 << ", use-shared-proxies=" << use_shared_proxies_;
695 // We only care about active network. 681 // We only care about active network.
696 if (network == network_lib->active_network()) 682 if (network == network_lib->active_network())
697 OnActiveNetworkChanged(network_lib, network); 683 OnActiveNetworkChanged(network_lib, network);
698 } 684 }
699 685
700 //------------------ ProxyConfigServiceImpl: private methods ------------------- 686 //------------------ ProxyConfigServiceImpl: private methods -------------------
701 687
702 void ProxyConfigServiceImpl::OnUISetProxyConfig() { 688 void ProxyConfigServiceImpl::Observe(int type,
703 if (testing_) { 689 const NotificationSource& source,
704 active_config_ = current_ui_config_; 690 const NotificationDetails& details) {
705 IOSetProxyConfig(active_config_, net::ProxyConfigService::CONFIG_VALID); 691 if (type == chrome::NOTIFICATION_PREF_CHANGED &&
692 Source<PrefService>(source).ptr() == prefs() &&
693 *(Details<std::string>(details).ptr()) == prefs::kUseSharedProxies) {
694 SetUseSharedProxies(use_shared_proxies_pref_.GetValue());
706 return; 695 return;
707 } 696 }
697 PrefProxyConfigTracker::Observe(type, source, details);
698 }
699
700 void ProxyConfigServiceImpl::OnUISetProxyConfig() {
708 if (current_ui_network_.empty()) 701 if (current_ui_network_.empty())
709 return; 702 return;
710 // Update config to flimflam. 703 // Update config to flimflam.
711 std::string value; 704 std::string value;
712 if (current_ui_config_.SerializeForNetwork(&value)) { 705 if (current_ui_config_.SerializeForNetwork(&value)) {
713 VLOG(1) << "set proxy (mode=" << current_ui_config_.mode 706 VLOG(1) << this << ": set proxy (mode=" << current_ui_config_.mode
714 << ") for " << current_ui_network_; 707 << ") for " << current_ui_network_;
708 current_ui_config_.state = ProxyPrefs::CONFIG_SYSTEM;
715 SetProxyConfigForNetwork(current_ui_network_, value, false); 709 SetProxyConfigForNetwork(current_ui_network_, value, false);
716 } 710 }
717 } 711 }
718 712
719 void ProxyConfigServiceImpl::IOSetProxyConfig(
720 const ProxyConfig& new_config,
721 net::ProxyConfigService::ConfigAvailability new_availability) {
722 if (!BrowserThread::CurrentlyOn(BrowserThread::IO) && can_post_task_) {
723 // Posts a task to IO thread with the new config, so it can update
724 // |cached_config_|.
725 Task* task = NewRunnableMethod(this,
726 &ProxyConfigServiceImpl::IOSetProxyConfig,
727 new_config,
728 new_availability);
729 if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task))
730 VLOG(1) << "Couldn't post task to IO thread to set new proxy config";
731 return;
732 }
733
734 // Now guaranteed to be on the correct thread.
735
736 if (config_availability_ == new_availability &&
737 cached_config_.Equals(new_config))
738 return;
739
740 VLOG(1) << "Proxy changed: mode=" << new_config.mode
741 << ", avail=" << new_availability;
742 cached_config_ = new_config;
743 config_availability_ = new_availability;
744 // Notify observers of new proxy config.
745 net::ProxyConfig net_config;
746 cached_config_.ToNetProxyConfig(&net_config);
747 if (net_config.proxy_rules().type !=
748 net::ProxyConfig::ProxyRules::TYPE_NO_RULES) {
749 net_config.proxy_rules().bypass_rules.AddRuleToBypassLocal();
750 }
751 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
752 OnProxyConfigChanged(net_config, config_availability_));
753 }
754
755 void ProxyConfigServiceImpl::OnActiveNetworkChanged(NetworkLibrary* network_lib, 713 void ProxyConfigServiceImpl::OnActiveNetworkChanged(NetworkLibrary* network_lib,
756 const Network* active_network) { 714 const Network* active_network) {
757 std::string new_network; 715 std::string new_network;
758 if (active_network) 716 if (active_network)
759 new_network = active_network->service_path(); 717 new_network = active_network->service_path();
760 718
761 if (active_network_ == new_network) { // Same active network. 719 if (active_network_ == new_network) { // Same active network.
762 VLOG(1) << "same active network: " 720 VLOG(1) << this << ": same active network: "
763 << (new_network.empty() ? "empty" : 721 << (new_network.empty() ? "empty" :
764 (active_network->name().empty() ? 722 (active_network->name().empty() ?
765 new_network : active_network->name())); 723 new_network : active_network->name()));
724 // If last proxy update to network stack wasn't completed, do it now.
725 if (active_network && update_pending())
726 DetermineEffectiveConfig(active_network, true);
766 return; 727 return;
767 } 728 }
768 729
769 // If there was a previous active network, remove it as observer. 730 // If there was a previous active network, remove it as observer.
770 if (!active_network_.empty()) 731 if (!active_network_.empty())
771 network_lib->RemoveNetworkObserver(active_network_, this); 732 network_lib->RemoveNetworkObserver(active_network_, this);
772 733
773 active_network_ = new_network; 734 active_network_ = new_network;
774 735
775 if (active_network_.empty()) { 736 if (active_network_.empty()) {
776 VLOG(1) << "new active network: empty"; 737 VLOG(1) << this << ": new active network: empty";
777 active_config_ = ProxyConfig(); 738 DetermineEffectiveConfig(active_network, true);
778 IOSetProxyConfig(active_config_, net::ProxyConfigService::CONFIG_UNSET);
779 return; 739 return;
780 } 740 }
781 741
782 VLOG(1) << "new active network: path=" << active_network->service_path() 742 VLOG(1) << this << ": new active network: path="
783 << ", name=" << active_network->name() 743 << active_network->service_path()
784 << ", profile=" << active_network->profile_path() 744 << ", name=" << active_network->name()
785 << ", proxy=" << active_network->proxy_config(); 745 << ", profile=" << active_network->profile_path()
746 << ", proxy=" << active_network->proxy_config();
786 747
787 // Register observer for new network. 748 // Register observer for new network.
788 network_lib->AddNetworkObserver(active_network_, this); 749 network_lib->AddNetworkObserver(active_network_, this);
789 750
790 // If necessary, migrate config to flimflam. 751 // If necessary, migrate config to flimflam.
791 if (active_network->proxy_config().empty() && !device_config_.empty()) { 752 if (active_network->proxy_config().empty() && !device_config_.empty()) {
792 VLOG(1) << "try migrating device config to " << active_network_; 753 VLOG(1) << this << ": try migrating device config to " << active_network_;
793 SetProxyConfigForNetwork(active_network_, device_config_, true); 754 SetProxyConfigForNetwork(active_network_, device_config_, true);
794 } else { 755 } else {
795 DetermineConfigFromNetwork(active_network); 756 // Otherwise, determine and activate possibly new effective proxy config.
757 DetermineEffectiveConfig(active_network, true);
796 } 758 }
797 } 759 }
798 760
799 void ProxyConfigServiceImpl::SetProxyConfigForNetwork( 761 void ProxyConfigServiceImpl::SetProxyConfigForNetwork(
800 const std::string& network_path, const std::string& value, 762 const std::string& network_path, const std::string& value,
801 bool only_set_if_empty) { 763 bool only_set_if_empty) {
802 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( 764 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
803 network_path); 765 network_path);
804 if (!network) { 766 if (!network) {
805 NOTREACHED() << "can't find requested network " << network_path; 767 NOTREACHED() << "can't find requested network " << network_path;
806 return; 768 return;
807 } 769 }
808 if (!only_set_if_empty || network->proxy_config().empty()) { 770 if (!only_set_if_empty || network->proxy_config().empty()) {
809 network->SetProxyConfig(value); 771 network->SetProxyConfig(value);
810 VLOG(1) << "set proxy for " 772 VLOG(1) << this << ": set proxy for " << (network->name().empty() ?
811 << (network->name().empty() ? network_path : network->name()) 773 network_path : network->name())
812 << ", value=" << value; 774 << ", value=" << value;
813 if (network_path == active_network_) 775 if (network_path == active_network_)
814 DetermineConfigFromNetwork(network); 776 DetermineEffectiveConfig(network, true);
815 } 777 }
816 } 778 }
817 779
818 void ProxyConfigServiceImpl::DetermineConfigFromNetwork( 780 void ProxyConfigServiceImpl::SetUseSharedProxies(bool use_shared) {
819 const Network* network) { 781 if (use_shared_proxies_ == use_shared) {
820 active_config_ = ProxyConfig(); // Default is DIRECT mode (i.e. no proxy). 782 VLOG(1) << this << ": same use-shared-proxies = " << use_shared_proxies_;
821 net::ProxyConfigService::ConfigAvailability available = 783 return;
822 net::ProxyConfigService::CONFIG_UNSET;
823 // If network is shared but user doesn't use shared proxies, use direct mode.
824 if (network->profile_type() == PROFILE_SHARED && !use_shared_proxies_) {
825 VLOG(1) << "shared network and !use_shared_proxies, using direct";
826 available = net::ProxyConfigService::CONFIG_VALID;
827 } else if (!network->proxy_config().empty() &&
828 active_config_.DeserializeForNetwork(network->proxy_config())) {
829 // Network is private or shared with user using shared proxies.
830 VLOG(1) << "using network proxy: " << network->proxy_config();
831 available = net::ProxyConfigService::CONFIG_VALID;
832 } 784 }
833 IOSetProxyConfig(active_config_, available); 785
786 use_shared_proxies_ = use_shared;
787 VLOG(1) << this << ": new use-shared-proxies = " << use_shared_proxies_;
788
789 // Determine new proxy config which may have changed because of new
790 // use-shared-proxies. If necessary, activate it.
791 Network* network = NULL;
792 if (!active_network_.empty()) {
793 network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
794 active_network_);
795 if (!network)
796 LOG(WARNING) << "can't find requested network " << active_network_;
797 }
798 DetermineEffectiveConfig(network, true);
834 } 799 }
835 800
836 void ProxyConfigServiceImpl::SetCurrentNetworkName(const Network* network) { 801 void ProxyConfigServiceImpl::DetermineEffectiveConfig(const Network* network,
837 if (!network) { 802 bool activate) {
838 if (testing_) 803 // Get prefs proxy config if available.
839 current_ui_network_name_ = "test"; 804 net::ProxyConfig pref_config;
840 return; 805 ProxyPrefs::ConfigState pref_state = GetProxyConfig(&pref_config);
806
807 // Get network proxy config if available.
808 net::ProxyConfig network_config;
809 net::ProxyConfigService::ConfigAvailability network_availability =
810 net::ProxyConfigService::CONFIG_UNSET;
811 bool ignore_proxy = activate;
812 if (network) {
813 // If we're activating proxy, ignore proxy if necessary;
814 // otherwise, for ui, get actual proxy to show user.
815 ignore_proxy = activate ? IgnoreProxy(network) : false;
816 // If network is shared but use-shared-proxies is off, use direct mode.
817 if (ignore_proxy) {
818 VLOG(1) << this << ": shared network && !use-shared-proxies, use direct";
819 network_availability = net::ProxyConfigService::CONFIG_VALID;
820 } else if (!network->proxy_config().empty()) {
821 // Network is private or shared with user using shared proxies.
822 JSONStringValueSerializer serializer(network->proxy_config());
823 scoped_ptr<Value> value(serializer.Deserialize(NULL, NULL));
824 if (value.get() && value->GetType() == Value::TYPE_DICTIONARY) {
825 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
826 ProxyConfigDictionary proxy_dict(dict);
827 if (PrefConfigToNetConfig(proxy_dict, &network_config)) {
828 VLOG(1) << this << ": using network proxy: "
829 << network->proxy_config();
830 network_availability = net::ProxyConfigService::CONFIG_VALID;
831 }
832 }
833 }
841 } 834 }
842 if (network->name().empty() && network->type() == chromeos::TYPE_ETHERNET) { 835
843 current_ui_network_name_ = l10n_util::GetStringUTF8( 836 // Determine effective proxy config, either from prefs or network.
844 IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); 837 ProxyPrefs::ConfigState effective_config_state;
845 } else { 838 net::ProxyConfig effective_config;
846 current_ui_network_name_ = network->name(); 839 GetEffectiveProxyConfig(pref_state, pref_config,
840 network_availability, network_config, ignore_proxy,
841 &effective_config_state, &effective_config);
842
843 // Determine if we should activate effective proxy and which proxy config to
844 // store it.
845 if (activate) { // Activate effective proxy and store into |active_config_|.
846 // If last update didn't complete, we definitely update now.
847 bool update_now = update_pending();
848 if (!update_now) { // Otherwise, only update now if there're changes.
849 update_now = active_config_state_ != effective_config_state ||
850 (active_config_state_ != ProxyPrefs::CONFIG_UNSET &&
851 !active_config_.Equals(effective_config));
852 }
853 if (update_now) { // Activate and store new effective config.
854 active_config_state_ = effective_config_state;
855 if (active_config_state_ != ProxyPrefs::CONFIG_UNSET)
856 active_config_ = effective_config;
857 // If effective config is from system (i.e. network), it's considered a
858 // special kind of prefs that ranks below policy/extension but above
859 // others, so bump it up to CONFIG_OTHER_PRECEDE to force its precedence
860 // when PrefProxyConfigTracker pushes it to ChromeProxyConfigService.
861 ProxyPrefs::ConfigState new_state =
862 effective_config_state == ProxyPrefs::CONFIG_SYSTEM ?
863 ProxyPrefs::CONFIG_OTHER_PRECEDE : effective_config_state;
864 PrefProxyConfigTracker::OnProxyConfigChanged(new_state, effective_config);
865 if (VLOG_IS_ON(1) && !update_pending()) { // Update was successful.
866 scoped_ptr<DictionaryValue> config_dict(static_cast<DictionaryValue*>(
867 effective_config.ToValue()));
868 std::string config_value;
869 JSONStringValueSerializer serializer(&config_value);
870 serializer.Serialize(*config_dict.get());
871 VLOG(1) << this << ": Proxy changed: "
872 << ConfigStateToString(active_config_state_)
873 << ", " << config_value;
874 }
875 }
876 } else { // For UI, store effective proxy into |current_ui_config_|.
877 current_ui_config_.FromNetProxyConfig(effective_config);
878 current_ui_config_.state = effective_config_state;
879 if (PrefPrecedes(effective_config_state))
880 current_ui_config_.user_modifiable = false;
881 else
882 current_ui_config_.user_modifiable = !network || !IgnoreProxy(network);
847 } 883 }
848 } 884 }
849 885
850 void ProxyConfigServiceImpl::CheckCurrentlyOnIOThread() { 886 void ProxyConfigServiceImpl::OnUISetCurrentNetwork(const Network* network) {
851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 887 DetermineEffectiveConfig(network, false);
888 VLOG(1) << this << ": current ui network: "
889 << (network->name().empty() ?
890 current_ui_network_ : network->name())
891 << ", " << ModeToString(current_ui_config_.mode)
892 << ", " << ConfigStateToString(current_ui_config_.state)
893 << ", modifiable:" << current_ui_config_.user_modifiable;
852 } 894 }
853 895
854 void ProxyConfigServiceImpl::CheckCurrentlyOnUIThread() { 896 void ProxyConfigServiceImpl::ResetUICache() {
855 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 897 current_ui_network_.clear();
898 current_ui_config_ = ProxyConfig();
856 } 899 }
857 900
858 } // namespace chromeos 901 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698