OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |