1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
10 #include "base/json/json_value_serializer.h"
11 #include "base/logging.h"
12 #include "base/string_util.h"
13 #include "chrome/browser/chromeos/cros/cros_library.h"
14 #include "chrome/browser/chromeos/cros_settings.h"
15 #include "chrome/browser/chromeos/cros_settings_names.h"
16 #include "chrome/browser/chromeos/login/user_manager.h"
17 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
18 #include "chrome/browser/prefs/pref_service.h"
19 #include "chrome/browser/prefs/proxy_config_dictionary.h"
20 #include "chrome/browser/prefs/proxy_prefs.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/pref_names.h"
24 #include "content/public/browser/notification_service.h"
25 #include "grit/generated_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
28 namespace em
= enterprise_management
;
34 // Shoud we try to push this to base?
35 // Helper comparator functor for the find_if call in |findIfEqual|
37 class EqualsComparator
{
39 explicit EqualsComparator(const T
& key
) : key_(key
) { }
40 bool operator() (const T
& element
) {
41 return element
.Equals(key_
);
47 // Tiny STL helper function to allow using the find_if syntax on objects that
48 // doesn't use the operator== but implement the Equals function which is the
49 // quasi standard with the coding style we have.
50 template<class InputIterator
, class T
>
51 InputIterator
findIfEqual(InputIterator first
, InputIterator last
,
53 return std::find_if(first
, last
, EqualsComparator
<T
>(key
));
56 const char* ModeToString(ProxyConfigServiceImpl::ProxyConfig::Mode mode
) {
58 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT
:
60 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT
:
62 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT
:
64 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY
:
65 return "single-proxy";
66 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME
:
67 return "proxy-per-scheme";
69 NOTREACHED() << "Unrecognized mode type";
73 const char* ConfigStateToString(ProxyPrefs::ConfigState state
) {
75 case ProxyPrefs::CONFIG_POLICY
:
76 return "config_policy";
77 case ProxyPrefs::CONFIG_EXTENSION
:
78 return "config_extension";
79 case ProxyPrefs::CONFIG_OTHER_PRECEDE
:
80 return "config_other_precede";
81 case ProxyPrefs::CONFIG_SYSTEM
:
82 return "config_network"; // For ChromeOS, system is network.
83 case ProxyPrefs::CONFIG_FALLBACK
:
84 return "config_recommended"; // Fallback is recommended.
85 case ProxyPrefs::CONFIG_UNSET
:
86 return "config_unset";
88 NOTREACHED() << "Unrecognized config state type";
92 // Only unblock if needed for debugging.
93 #if defined(NEED_DEBUG_LOG)
94 std::ostream
& operator<<(
96 const ProxyConfigServiceImpl::ProxyConfig::ManualProxy
& proxy
) {
97 out
<< (proxy
.server
.is_valid() ? proxy
.server
.ToURI() : "") << "\n";
101 std::ostream
& operator<<(std::ostream
& out
,
102 const ProxyConfigServiceImpl::ProxyConfig
& config
) {
103 switch (config
.mode
) {
104 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT
:
105 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT
:
106 out
<< ModeToString(config
.mode
) << ", "
107 << ConfigStateToString(config
.state
) << "\n";
109 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT
:
110 out
<< ModeToString(config
.mode
) << ", "
111 << ConfigStateToString(config
.state
)
112 << "\n PAC: " << config
.automatic_proxy
.pac_url
<< "\n";
114 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY
:
115 out
<< ModeToString(config
.mode
) << ", "
116 << ConfigStateToString(config
.state
) << "\n " << config
.single_proxy
;
118 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME
:
119 out
<< ModeToString(config
.mode
) << ", "
120 << ConfigStateToString(config
.state
) << "\n"
121 << " HTTP: " << config
.http_proxy
122 << " HTTPS: " << config
.https_proxy
123 << " FTP: " << config
.ftp_proxy
124 << " SOCKS: " << config
.socks_proxy
;
127 NOTREACHED() << "Unrecognized proxy config mode";
130 if (config
.mode
== ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY
||
132 ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME
) {
133 out
<< "Bypass list: ";
134 if (config
.bypass_rules
.rules().empty()) {
137 const net::ProxyBypassRules
& bypass_rules
= config
.bypass_rules
;
138 net::ProxyBypassRules::RuleList::const_iterator it
;
139 for (it
= bypass_rules
.rules().begin();
140 it
!= bypass_rules
.rules().end(); ++it
) {
141 out
<< "\n " << (*it
)->ToString();
148 std::string
ProxyConfigToString(
149 const ProxyConfigServiceImpl::ProxyConfig
& proxy_config
) {
150 std::ostringstream stream
;
151 stream
<< proxy_config
;
154 #endif // defined(NEED_DEBUG_LOG)
158 //----------- ProxyConfigServiceImpl::ProxyConfig: public methods --------------
160 ProxyConfigServiceImpl::ProxyConfig::ProxyConfig()
162 state(ProxyPrefs::CONFIG_UNSET
),
163 user_modifiable(true) {}
165 ProxyConfigServiceImpl::ProxyConfig::~ProxyConfig() {}
167 bool ProxyConfigServiceImpl::ProxyConfig::FromNetProxyConfig(
168 const net::ProxyConfig
& net_config
) {
169 *this = ProxyConfigServiceImpl::ProxyConfig(); // Reset to default.
170 const net::ProxyConfig::ProxyRules
& rules
= net_config
.proxy_rules();
171 switch (rules
.type
) {
172 case net::ProxyConfig::ProxyRules::TYPE_NO_RULES
:
173 if (!net_config
.HasAutomaticSettings()) {
174 mode
= ProxyConfig::MODE_DIRECT
;
175 } else if (net_config
.auto_detect()) {
176 mode
= ProxyConfig::MODE_AUTO_DETECT
;
177 } else if (net_config
.has_pac_url()) {
178 mode
= ProxyConfig::MODE_PAC_SCRIPT
;
179 automatic_proxy
.pac_url
= net_config
.pac_url();
184 case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY
:
185 if (!rules
.single_proxy
.is_valid())
187 mode
= MODE_SINGLE_PROXY
;
188 single_proxy
.server
= rules
.single_proxy
;
189 bypass_rules
= rules
.bypass_rules
;
191 case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME
:
192 // Make sure we have valid server for at least one of the protocols.
193 if (!rules
.proxy_for_http
.is_valid() &&
194 !rules
.proxy_for_https
.is_valid() &&
195 !rules
.proxy_for_ftp
.is_valid() &&
196 !rules
.fallback_proxy
.is_valid()) {
199 mode
= MODE_PROXY_PER_SCHEME
;
200 if (rules
.proxy_for_http
.is_valid())
201 http_proxy
.server
= rules
.proxy_for_http
;
202 if (rules
.proxy_for_https
.is_valid())
203 https_proxy
.server
= rules
.proxy_for_https
;
204 if (rules
.proxy_for_ftp
.is_valid())
205 ftp_proxy
.server
= rules
.proxy_for_ftp
;
206 if (rules
.fallback_proxy
.is_valid())
207 socks_proxy
.server
= rules
.fallback_proxy
;
208 bypass_rules
= rules
.bypass_rules
;
211 NOTREACHED() << "Unrecognized proxy config mode";
217 DictionaryValue
* ProxyConfigServiceImpl::ProxyConfig::ToPrefProxyConfig() {
220 return ProxyConfigDictionary::CreateDirect();
222 case MODE_AUTO_DETECT
: {
223 return ProxyConfigDictionary::CreateAutoDetect();
225 case MODE_PAC_SCRIPT
: {
226 return ProxyConfigDictionary::CreatePacScript(
227 automatic_proxy
.pac_url
.spec(), false);
229 case MODE_SINGLE_PROXY
: {
231 if (single_proxy
.server
.is_valid())
232 spec
= single_proxy
.server
.ToURI();
233 return ProxyConfigDictionary::CreateFixedServers(
234 spec
, bypass_rules
.ToString());
236 case MODE_PROXY_PER_SCHEME
: {
238 EncodeAndAppendProxyServer("http", http_proxy
.server
, &spec
);
239 EncodeAndAppendProxyServer("https", https_proxy
.server
, &spec
);
240 EncodeAndAppendProxyServer("ftp", ftp_proxy
.server
, &spec
);
241 EncodeAndAppendProxyServer("socks", socks_proxy
.server
, &spec
);
242 return ProxyConfigDictionary::CreateFixedServers(
243 spec
, bypass_rules
.ToString());
248 NOTREACHED() << "Unrecognized proxy config mode for preference";
252 ProxyConfigServiceImpl::ProxyConfig::ManualProxy
*
253 ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy(
254 const std::string
& scheme
) {
255 if (scheme
== "http")
257 if (scheme
== "https")
261 if (scheme
== "socks")
263 NOTREACHED() << "Invalid scheme: " << scheme
;
267 bool ProxyConfigServiceImpl::ProxyConfig::DeserializeForDevice(
268 const std::string
& input
) {
269 em::DeviceProxySettingsProto proxy_proto
;
270 if (!proxy_proto
.ParseFromString(input
))
273 const std::string
& mode_string(proxy_proto
.proxy_mode());
274 if (mode_string
== ProxyPrefs::kDirectProxyModeName
) {
276 } else if (mode_string
== ProxyPrefs::kAutoDetectProxyModeName
) {
277 mode
= MODE_AUTO_DETECT
;
278 } else if (mode_string
== ProxyPrefs::kPacScriptProxyModeName
) {
279 mode
= MODE_PAC_SCRIPT
;
280 if (proxy_proto
.has_proxy_pac_url())
281 automatic_proxy
.pac_url
= GURL(proxy_proto
.proxy_pac_url());
282 } else if (mode_string
== ProxyPrefs::kFixedServersProxyModeName
) {
283 net::ProxyConfig::ProxyRules rules
;
284 rules
.ParseFromString(proxy_proto
.proxy_server());
285 switch (rules
.type
) {
286 case net::ProxyConfig::ProxyRules::TYPE_NO_RULES
:
288 case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY
:
289 if (!rules
.single_proxy
.is_valid())
291 mode
= MODE_SINGLE_PROXY
;
292 single_proxy
.server
= rules
.single_proxy
;
294 case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME
:
295 // Make sure we have valid server for at least one of the protocols.
296 if (!rules
.proxy_for_http
.is_valid() &&
297 !rules
.proxy_for_https
.is_valid() &&
298 !rules
.proxy_for_ftp
.is_valid() &&
299 !rules
.fallback_proxy
.is_valid()) {
302 mode
= MODE_PROXY_PER_SCHEME
;
303 if (rules
.proxy_for_http
.is_valid())
304 http_proxy
.server
= rules
.proxy_for_http
;
305 if (rules
.proxy_for_https
.is_valid())
306 https_proxy
.server
= rules
.proxy_for_https
;
307 if (rules
.proxy_for_ftp
.is_valid())
308 ftp_proxy
.server
= rules
.proxy_for_ftp
;
309 if (rules
.fallback_proxy
.is_valid())
310 socks_proxy
.server
= rules
.fallback_proxy
;
314 NOTREACHED() << "Unrecognized proxy config mode";
318 if (proxy_proto
.has_proxy_bypass_list())
319 bypass_rules
.ParseFromString(proxy_proto
.proxy_bypass_list());
324 bool ProxyConfigServiceImpl::ProxyConfig::SerializeForNetwork(
325 std::string
* output
) {
326 scoped_ptr
<DictionaryValue
> proxy_dict(ToPrefProxyConfig());
327 if (!proxy_dict
.get())
329 JSONStringValueSerializer
serializer(output
);
330 return serializer
.Serialize(*proxy_dict
.get());
333 //----------- ProxyConfigServiceImpl::ProxyConfig: private methods -------------
336 void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
337 const std::string
& scheme
,
338 const net::ProxyServer
& server
,
340 if (!server
.is_valid())
346 if (!scheme
.empty()) {
350 *spec
+= server
.ToURI();
353 //------------------- ProxyConfigServiceImpl: public methods -------------------
355 ProxyConfigServiceImpl::ProxyConfigServiceImpl(PrefService
* pref_service
)
356 : PrefProxyConfigTrackerImpl(pref_service
),
357 active_config_state_(ProxyPrefs::CONFIG_UNSET
),
358 pointer_factory_(this) {
360 // Register for notifications of UseSharedProxies user preference.
361 if (pref_service
->FindPreference(prefs::kUseSharedProxies
))
362 use_shared_proxies_
.Init(prefs::kUseSharedProxies
, pref_service
, this);
364 if (CrosSettings::Get()->GetTrusted(
365 kSettingProxyEverywhere
,
366 base::Bind(&ProxyConfigServiceImpl::FetchProxyPolicy
,
367 pointer_factory_
.GetWeakPtr()))) {
371 // Register for flimflam network notifications.
372 NetworkLibrary
* network_lib
= CrosLibrary::Get()->GetNetworkLibrary();
373 OnActiveNetworkChanged(network_lib
, network_lib
->active_network());
374 network_lib
->AddNetworkManagerObserver(this);
377 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() {
378 NetworkLibrary
* netlib
= CrosLibrary::Get()->GetNetworkLibrary();
380 netlib
->RemoveNetworkManagerObserver(this);
381 netlib
->RemoveObserverForAllNetworks(this);
385 void ProxyConfigServiceImpl::UISetCurrentNetwork(
386 const std::string
& current_network
) {
387 Network
* network
= CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
391 LOG(ERROR
) << "can't find requested network " << current_network
;
394 current_ui_network_
= current_network
;
395 OnUISetCurrentNetwork(network
);
398 void ProxyConfigServiceImpl::UIMakeActiveNetworkCurrent() {
399 Network
* network
= CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
403 LOG(ERROR
) << "can't find requested network " << active_network_
;
406 current_ui_network_
= active_network_
;
407 OnUISetCurrentNetwork(network
);
410 void ProxyConfigServiceImpl::UIGetCurrentNetworkName(
411 std::string
* network_name
) {
414 network_name
->clear();
415 Network
* network
= CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
416 current_ui_network_
);
418 LOG(ERROR
) << "can't find requested network " << current_ui_network_
;
421 if (network
->name().empty() && network
->type() == chromeos::TYPE_ETHERNET
) {
423 l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET
);
425 *network_name
= network
->name();
429 void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig
* config
) {
430 // Simply returns the copy last set from UI via UISetCurrentNetwork or
431 // UIMakeActiveNetworkCurrent.
432 *config
= current_ui_config_
;
435 bool ProxyConfigServiceImpl::UISetProxyConfigToDirect() {
436 current_ui_config_
.mode
= ProxyConfig::MODE_DIRECT
;
437 OnUISetProxyConfig();
441 bool ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() {
442 current_ui_config_
.mode
= ProxyConfig::MODE_AUTO_DETECT
;
443 OnUISetProxyConfig();
447 bool ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL
& pac_url
) {
448 current_ui_config_
.mode
= ProxyConfig::MODE_PAC_SCRIPT
;
449 current_ui_config_
.automatic_proxy
.pac_url
= pac_url
;
450 OnUISetProxyConfig();
454 bool ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy(
455 const net::ProxyServer
& server
) {
456 current_ui_config_
.mode
= ProxyConfig::MODE_SINGLE_PROXY
;
457 current_ui_config_
.single_proxy
.server
= server
;
458 OnUISetProxyConfig();
462 bool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme(
463 const std::string
& scheme
, const net::ProxyServer
& server
) {
464 ProxyConfig::ManualProxy
* proxy
= current_ui_config_
.MapSchemeToProxy(scheme
);
466 NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme
<< "]";
469 current_ui_config_
.mode
= ProxyConfig::MODE_PROXY_PER_SCHEME
;
470 proxy
->server
= server
;
471 OnUISetProxyConfig();
475 bool ProxyConfigServiceImpl::UISetProxyConfigBypassRules(
476 const net::ProxyBypassRules
& bypass_rules
) {
477 if (current_ui_config_
.mode
!= ProxyConfig::MODE_SINGLE_PROXY
&&
478 current_ui_config_
.mode
!= ProxyConfig::MODE_PROXY_PER_SCHEME
) {
480 VLOG(1) << "Cannot set bypass rules for proxy mode ["
481 << current_ui_config_
.mode
<< "]";
484 current_ui_config_
.bypass_rules
= bypass_rules
;
485 OnUISetProxyConfig();
489 void ProxyConfigServiceImpl::AddNotificationCallback(base::Closure callback
) {
491 std::vector
<base::Closure
>::iterator iter
=
492 findIfEqual(callbacks_
.begin(), callbacks_
.end(), callback
);
493 if (iter
== callbacks_
.end())
494 callbacks_
.push_back(callback
);
497 void ProxyConfigServiceImpl::RemoveNotificationCallback(
498 base::Closure callback
) {
499 std::vector
<base::Closure
>::iterator iter
=
500 findIfEqual(callbacks_
.begin(), callbacks_
.end(), callback
);
501 if (iter
!= callbacks_
.end())
502 callbacks_
.erase(iter
);
505 void ProxyConfigServiceImpl::OnProxyConfigChanged(
506 ProxyPrefs::ConfigState config_state
,
507 const net::ProxyConfig
& config
) {
508 VLOG(1) << this << ": got prefs change: " << ConfigStateToString(config_state
)
509 << ", mode=" << config
.proxy_rules().type
;
510 Network
* network
= NULL
;
511 if (!active_network_
.empty()) {
512 network
= CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
515 LOG(ERROR
) << "can't find requested network " << active_network_
;
517 DetermineEffectiveConfig(network
, true);
520 void ProxyConfigServiceImpl::OnNetworkManagerChanged(
521 NetworkLibrary
* network_lib
) {
522 VLOG(1) << this << " OnNetworkManagerChanged: use-shared-proxies="
523 << GetUseSharedProxies();
524 OnActiveNetworkChanged(network_lib
, network_lib
->active_network());
527 void ProxyConfigServiceImpl::OnNetworkChanged(NetworkLibrary
* network_lib
,
528 const Network
* network
) {
531 VLOG(1) << this << " OnNetworkChanged: "
532 << (network
->name().empty() ? network
->service_path() :
534 << ", use-shared-proxies=" << GetUseSharedProxies();
535 // We only care about active network.
536 if (network
== network_lib
->active_network())
537 OnActiveNetworkChanged(network_lib
, network
);
541 void ProxyConfigServiceImpl::RegisterPrefs(PrefService
* pref_service
) {
542 // Use shared proxies default to off. GetUseSharedProxies will return the
543 // correct value based on pre-login and login.
544 pref_service
->RegisterBooleanPref(prefs::kUseSharedProxies
,
546 PrefService::UNSYNCABLE_PREF
);
549 //------------------ ProxyConfigServiceImpl: private methods -------------------
551 void ProxyConfigServiceImpl::Observe(
553 const content::NotificationSource
& source
,
554 const content::NotificationDetails
& details
) {
555 if (type
== chrome::NOTIFICATION_PREF_CHANGED
&&
556 *(content::Details
<std::string
>(details
).ptr()) ==
557 prefs::kUseSharedProxies
) {
558 if (content::Source
<PrefService
>(source
).ptr() == prefs()) {
559 VLOG(1) << this << ": new use-shared-proxies = " << GetUseSharedProxies();
560 // Determine new proxy config which may have changed because of new
561 // use-shared-proxies. If necessary, activate it.
562 Network
* network
= NULL
;
563 if (!active_network_
.empty()) {
564 network
= CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
567 LOG(WARNING
) << "can't find requested network " << active_network_
;
569 DetermineEffectiveConfig(network
, true);
573 PrefProxyConfigTrackerImpl::Observe(type
, source
, details
);
576 void ProxyConfigServiceImpl::OnUISetProxyConfig() {
577 if (current_ui_network_
.empty())
579 // Update config to flimflam.
581 if (current_ui_config_
.SerializeForNetwork(&value
)) {
582 VLOG(1) << this << ": set proxy (mode=" << current_ui_config_
.mode
583 << ") for " << current_ui_network_
;
584 current_ui_config_
.state
= ProxyPrefs::CONFIG_SYSTEM
;
585 SetProxyConfigForNetwork(current_ui_network_
, value
, false);
589 void ProxyConfigServiceImpl::OnActiveNetworkChanged(NetworkLibrary
* network_lib
,
590 const Network
* active_network
) {
591 std::string new_network
;
593 new_network
= active_network
->service_path();
595 if (active_network_
== new_network
) { // Same active network.
596 VLOG(1) << this << ": same active network: "
597 << (new_network
.empty() ? "empty" :
598 (active_network
->name().empty() ?
599 new_network
: active_network
->name()));
600 // Even though network is the same, its proxy config (e.g. if private
601 // version of network replaces the shared version after login), or
602 // use-shared-proxies setting (e.g. after login) may have changed,
603 // so re-determine effective proxy config, and activate if different.
604 if (active_network
) {
605 VLOG(1) << this << ": profile=" << active_network
->profile_type()
606 << "," << active_network
->profile_path()
607 << ", proxy=" << active_network
->proxy_config();
608 DetermineEffectiveConfig(active_network
, true);
613 // If there was a previous active network, remove it as observer.
614 if (!active_network_
.empty())
615 network_lib
->RemoveNetworkObserver(active_network_
, this);
617 active_network_
= new_network
;
619 if (active_network_
.empty()) {
620 VLOG(1) << this << ": new active network: empty";
621 DetermineEffectiveConfig(active_network
, true);
625 VLOG(1) << this << ": new active network: path="
626 << active_network
->service_path()
627 << ", name=" << active_network
->name()
628 << ", profile=" << active_network
->profile_type()
629 << "," << active_network
->profile_path()
630 << ", proxy=" << active_network
->proxy_config();
632 // Register observer for new network.
633 network_lib
->AddNetworkObserver(active_network_
, this);
635 // If necessary, migrate config to flimflam.
636 if (active_network
->proxy_config().empty() && !device_config_
.empty()) {
637 VLOG(1) << this << ": try migrating device config to " << active_network_
;
638 SetProxyConfigForNetwork(active_network_
, device_config_
, true);
640 // Otherwise, determine and activate possibly new effective proxy config.
641 DetermineEffectiveConfig(active_network
, true);
645 void ProxyConfigServiceImpl::SetProxyConfigForNetwork(
646 const std::string
& network_path
, const std::string
& value
,
647 bool only_set_if_empty
) {
648 Network
* network
= CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath(
651 NOTREACHED() << "can't find requested network " << network_path
;
654 if (!only_set_if_empty
|| network
->proxy_config().empty()) {
655 network
->SetProxyConfig(value
);
656 VLOG(1) << this << ": set proxy for " << (network
->name().empty() ?
657 network_path
: network
->name())
658 << ", value=" << value
;
659 if (network_path
== active_network_
)
660 DetermineEffectiveConfig(network
, true);
664 bool ProxyConfigServiceImpl::GetUseSharedProxies() {
665 const PrefService::Preference
* use_shared_proxies_pref
=
666 prefs()->FindPreference(prefs::kUseSharedProxies
);
667 if (!use_shared_proxies_pref
|| use_shared_proxies_pref
->IsDefaultValue())
668 return !UserManager::Get()->user_is_logged_in();
669 return use_shared_proxies_
.GetValue();
672 void ProxyConfigServiceImpl::DetermineEffectiveConfig(const Network
* network
,
674 // Get prefs proxy config if available.
675 net::ProxyConfig pref_config
;
676 ProxyPrefs::ConfigState pref_state
= GetProxyConfig(&pref_config
);
678 // Get network proxy config if available.
679 net::ProxyConfig network_config
;
680 net::ProxyConfigService::ConfigAvailability network_availability
=
681 net::ProxyConfigService::CONFIG_UNSET
;
682 bool ignore_proxy
= activate
;
684 // If we're activating proxy, ignore proxy if necessary;
685 // otherwise, for ui, get actual proxy to show user.
686 ignore_proxy
= activate
? IgnoreProxy(network
) : false;
687 // If network is shared but use-shared-proxies is off, use direct mode.
689 VLOG(1) << this << ": shared network && !use-shared-proxies, use direct";
690 network_availability
= net::ProxyConfigService::CONFIG_VALID
;
691 } else if (!network
->proxy_config().empty()) {
692 // Network is private or shared with user using shared proxies.
693 JSONStringValueSerializer
serializer(network
->proxy_config());
694 scoped_ptr
<Value
> value(serializer
.Deserialize(NULL
, NULL
));
695 if (value
.get() && value
->GetType() == Value::TYPE_DICTIONARY
) {
696 DictionaryValue
* dict
= static_cast<DictionaryValue
*>(value
.get());
697 ProxyConfigDictionary
proxy_dict(dict
);
698 if (PrefConfigToNetConfig(proxy_dict
, &network_config
)) {
699 VLOG(1) << this << ": using network proxy: "
700 << network
->proxy_config();
701 network_availability
= net::ProxyConfigService::CONFIG_VALID
;
707 // Determine effective proxy config, either from prefs or network.
708 ProxyPrefs::ConfigState effective_config_state
;
709 net::ProxyConfig effective_config
;
710 GetEffectiveProxyConfig(pref_state
, pref_config
,
711 network_availability
, network_config
, ignore_proxy
,
712 &effective_config_state
, &effective_config
);
714 // Determine if we should activate effective proxy and which proxy config to
716 if (activate
) { // Activate effective proxy and store into |active_config_|.
717 // If last update didn't complete, we definitely update now.
718 bool update_now
= update_pending();
719 if (!update_now
) { // Otherwise, only update now if there're changes.
720 update_now
= active_config_state_
!= effective_config_state
||
721 (active_config_state_
!= ProxyPrefs::CONFIG_UNSET
&&
722 !active_config_
.Equals(effective_config
));
724 if (update_now
) { // Activate and store new effective config.
725 active_config_state_
= effective_config_state
;
726 if (active_config_state_
!= ProxyPrefs::CONFIG_UNSET
)
727 active_config_
= effective_config
;
728 // If effective config is from system (i.e. network), it's considered a
729 // special kind of prefs that ranks below policy/extension but above
730 // others, so bump it up to CONFIG_OTHER_PRECEDE to force its precedence
731 // when PrefProxyConfigTrackerImpl pushes it to ChromeProxyConfigService.
732 if (effective_config_state
== ProxyPrefs::CONFIG_SYSTEM
)
733 effective_config_state
= ProxyPrefs::CONFIG_OTHER_PRECEDE
;
734 // If config is manual, add rule to bypass local host.
735 if (effective_config
.proxy_rules().type
!=
736 net::ProxyConfig::ProxyRules::TYPE_NO_RULES
)
737 effective_config
.proxy_rules().bypass_rules
.AddRuleToBypassLocal();
738 PrefProxyConfigTrackerImpl::OnProxyConfigChanged(effective_config_state
,
740 if (VLOG_IS_ON(1) && !update_pending()) { // Update was successful.
741 scoped_ptr
<DictionaryValue
> config_dict(static_cast<DictionaryValue
*>(
742 effective_config
.ToValue()));
743 std::string config_value
;
744 JSONStringValueSerializer
serializer(&config_value
);
745 serializer
.Serialize(*config_dict
.get());
746 VLOG(1) << this << ": Proxy changed: "
747 << ConfigStateToString(active_config_state_
)
748 << ", " << config_value
;
751 } else { // For UI, store effective proxy into |current_ui_config_|.
752 current_ui_config_
.FromNetProxyConfig(effective_config
);
753 current_ui_config_
.state
= effective_config_state
;
754 if (PrefPrecedes(effective_config_state
))
755 current_ui_config_
.user_modifiable
= false;
757 current_ui_config_
.user_modifiable
= !network
|| !IgnoreProxy(network
);
761 void ProxyConfigServiceImpl::OnUISetCurrentNetwork(const Network
* network
) {
762 DetermineEffectiveConfig(network
, false);
763 VLOG(1) << this << ": current ui network: "
764 << (network
->name().empty() ?
765 current_ui_network_
: network
->name())
766 << ", " << ModeToString(current_ui_config_
.mode
)
767 << ", " << ConfigStateToString(current_ui_config_
.state
)
768 << ", modifiable:" << current_ui_config_
.user_modifiable
;
769 // Notify whoever is interested in this change.
770 std::vector
<base::Closure
>::iterator iter
= callbacks_
.begin();
771 while (iter
!= callbacks_
.end()) {
772 if (iter
->is_null()) {
773 iter
= callbacks_
.erase(iter
);
781 void ProxyConfigServiceImpl::ResetUICache() {
782 current_ui_network_
.clear();
783 current_ui_config_
= ProxyConfig();
786 void ProxyConfigServiceImpl::FetchProxyPolicy() {
787 std::string policy_value
;
788 if (!CrosSettings::Get()->GetString(kSettingProxyEverywhere
,
790 LOG(WARNING
) << this << ": Error retrieving proxy setting from device";
791 device_config_
.clear();
795 VLOG(1) << this << ": Retrieved proxy setting from device, value=["
796 << policy_value
<< "]";
797 ProxyConfig device_config
;
798 if (!device_config
.DeserializeForDevice(policy_value
) ||
799 !device_config
.SerializeForNetwork(&device_config_
)) {
800 LOG(WARNING
) << "Can't deserialize device setting or serialize for network";
801 device_config_
.clear();
804 if (!active_network_
.empty()) {
805 VLOG(1) << this << ": try migrating device config to " << active_network_
;
806 SetProxyConfigForNetwork(active_network_
, device_config_
, true);
810 } // namespace chromeos