| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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> | |
| 8 | |
| 9 #include "base/bind.h" | 7 #include "base/bind.h" |
| 10 #include "base/json/json_string_value_serializer.h" | |
| 11 #include "base/logging.h" | 8 #include "base/logging.h" |
| 12 #include "base/prefs/pref_registry_simple.h" | 9 #include "base/prefs/pref_registry_simple.h" |
| 13 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
| 14 #include "base/string_util.h" | 11 #include "base/values.h" |
| 15 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
| 16 #include "chrome/browser/chromeos/cros/cros_library.h" | |
| 17 #include "chrome/browser/chromeos/cros/network_property_ui_data.h" | |
| 18 #include "chrome/browser/chromeos/login/user_manager.h" | 13 #include "chrome/browser/chromeos/login/user_manager.h" |
| 19 #include "chrome/browser/policy/browser_policy_connector.h" | 14 #include "chrome/browser/policy/browser_policy_connector.h" |
| 20 #include "chrome/browser/policy/cloud/cloud_policy_constants.h" | 15 #include "chrome/browser/policy/cloud/cloud_policy_constants.h" |
| 21 #include "chrome/browser/prefs/proxy_config_dictionary.h" | 16 #include "chrome/browser/prefs/proxy_config_dictionary.h" |
| 22 #include "chrome/browser/prefs/proxy_prefs.h" | 17 #include "chrome/browser/prefs/proxy_prefs.h" |
| 23 #include "chrome/browser/profiles/profile_manager.h" | |
| 24 #include "chrome/common/chrome_notification_types.h" | |
| 25 #include "chrome/common/pref_names.h" | 18 #include "chrome/common/pref_names.h" |
| 26 #include "chromeos/network/network_ui_data.h" | 19 #include "chromeos/network/network_profile.h" |
| 27 #include "chromeos/network/onc/onc_constants.h" | 20 #include "chromeos/network/network_profile_handler.h" |
| 21 #include "chromeos/network/network_state.h" |
| 22 #include "chromeos/network/network_state_handler.h" |
| 23 #include "chromeos/network/onc/onc_utils.h" |
| 28 #include "components/user_prefs/pref_registry_syncable.h" | 24 #include "components/user_prefs/pref_registry_syncable.h" |
| 29 #include "content/public/browser/notification_service.h" | |
| 30 #include "grit/generated_resources.h" | |
| 31 #include "ui/base/l10n/l10n_util.h" | |
| 32 | 25 |
| 33 namespace chromeos { | 26 namespace chromeos { |
| 34 | 27 |
| 35 namespace { | 28 namespace { |
| 36 | 29 |
| 37 // Shoud we try to push this to base? | 30 // Convert and store the proxy config of |pref_proxy_config| of |
| 38 // Helper comparator functor for the find_if call in |findIfEqual| | 31 // ProxyConfigDictionary format to |proxy_config|. Returns true if |
| 39 template <class T> | 32 // |pref_proxy_config| was not empty and if it was successfully converted. |
| 40 class EqualsComparator{ | 33 bool ParseProxyConfig(const base::DictionaryValue& pref_proxy_config, |
| 41 public: | 34 net::ProxyConfig* proxy_config) { |
| 42 explicit EqualsComparator(const T& key) : key_(key) { } | 35 if (pref_proxy_config.empty()) |
| 43 bool operator() (const T& element) { | 36 return false; |
| 44 return element.Equals(key_); | 37 ProxyConfigDictionary proxy_dict(&pref_proxy_config); |
| 45 } | 38 return PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(proxy_dict, |
| 46 private: | 39 proxy_config); |
| 47 const T& key_; | |
| 48 }; | |
| 49 | |
| 50 // Tiny STL helper function to allow using the find_if syntax on objects that | |
| 51 // doesn't use the operator== but implement the Equals function which is the | |
| 52 // quasi standard with the coding style we have. | |
| 53 template<class InputIterator, class T> | |
| 54 InputIterator findIfEqual(InputIterator first, InputIterator last, | |
| 55 const T& key) { | |
| 56 return std::find_if(first, last, EqualsComparator<T>(key)); | |
| 57 } | |
| 58 | |
| 59 const char* ModeToString(ProxyConfigServiceImpl::ProxyConfig::Mode mode) { | |
| 60 switch (mode) { | |
| 61 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT: | |
| 62 return "direct"; | |
| 63 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT: | |
| 64 return "auto-detect"; | |
| 65 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT: | |
| 66 return "pacurl"; | |
| 67 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY: | |
| 68 return "single-proxy"; | |
| 69 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME: | |
| 70 return "proxy-per-scheme"; | |
| 71 } | |
| 72 NOTREACHED() << "Unrecognized mode type"; | |
| 73 return ""; | |
| 74 } | |
| 75 | |
| 76 const char* ConfigStateToString(ProxyPrefs::ConfigState state) { | |
| 77 switch (state) { | |
| 78 case ProxyPrefs::CONFIG_POLICY: | |
| 79 return "config_policy"; | |
| 80 case ProxyPrefs::CONFIG_EXTENSION: | |
| 81 return "config_extension"; | |
| 82 case ProxyPrefs::CONFIG_OTHER_PRECEDE: | |
| 83 return "config_other_precede"; | |
| 84 case ProxyPrefs::CONFIG_SYSTEM: | |
| 85 return "config_network"; // For ChromeOS, system is network. | |
| 86 case ProxyPrefs::CONFIG_FALLBACK: | |
| 87 return "config_recommended"; // Fallback is recommended. | |
| 88 case ProxyPrefs::CONFIG_UNSET: | |
| 89 return "config_unset"; | |
| 90 } | |
| 91 NOTREACHED() << "Unrecognized config state type"; | |
| 92 return ""; | |
| 93 } | |
| 94 | |
| 95 // Returns true if proxy settings from |network| is editable. | |
| 96 bool IsNetworkProxySettingsEditable(const Network* network) { | |
| 97 if (!network) | |
| 98 return true; // editable if no network given. | |
| 99 | |
| 100 NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary(); | |
| 101 const base::DictionaryValue* onc = | |
| 102 network_library->FindOncForNetwork(network->unique_id()); | |
| 103 | |
| 104 NetworkPropertyUIData proxy_settings_ui_data; | |
| 105 proxy_settings_ui_data.ParseOncProperty( | |
| 106 network->ui_data().onc_source(), | |
| 107 onc, | |
| 108 onc::network_config::kProxySettings); | |
| 109 return proxy_settings_ui_data.IsEditable(); | |
| 110 } | 40 } |
| 111 | 41 |
| 112 } // namespace | 42 } // namespace |
| 113 | 43 |
| 114 //----------- ProxyConfigServiceImpl::ProxyConfig: public methods -------------- | |
| 115 | |
| 116 ProxyConfigServiceImpl::ProxyConfig::ProxyConfig() | |
| 117 : mode(MODE_DIRECT), | |
| 118 state(ProxyPrefs::CONFIG_UNSET), | |
| 119 user_modifiable(true) {} | |
| 120 | |
| 121 ProxyConfigServiceImpl::ProxyConfig::~ProxyConfig() {} | |
| 122 | |
| 123 bool ProxyConfigServiceImpl::ProxyConfig::FromNetProxyConfig( | |
| 124 const net::ProxyConfig& net_config) { | |
| 125 *this = ProxyConfigServiceImpl::ProxyConfig(); // Reset to default. | |
| 126 const net::ProxyConfig::ProxyRules& rules = net_config.proxy_rules(); | |
| 127 switch (rules.type) { | |
| 128 case net::ProxyConfig::ProxyRules::TYPE_NO_RULES: | |
| 129 if (!net_config.HasAutomaticSettings()) { | |
| 130 mode = ProxyConfig::MODE_DIRECT; | |
| 131 } else if (net_config.auto_detect()) { | |
| 132 mode = ProxyConfig::MODE_AUTO_DETECT; | |
| 133 } else if (net_config.has_pac_url()) { | |
| 134 mode = ProxyConfig::MODE_PAC_SCRIPT; | |
| 135 automatic_proxy.pac_url = net_config.pac_url(); | |
| 136 } else { | |
| 137 return false; | |
| 138 } | |
| 139 return true; | |
| 140 case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY: | |
| 141 if (rules.single_proxies.IsEmpty()) | |
| 142 return false; | |
| 143 mode = MODE_SINGLE_PROXY; | |
| 144 single_proxy.server = rules.single_proxies.Get(); | |
| 145 bypass_rules = rules.bypass_rules; | |
| 146 return true; | |
| 147 case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME: | |
| 148 // Make sure we have valid server for at least one of the protocols. | |
| 149 if (rules.proxies_for_http.IsEmpty() && | |
| 150 rules.proxies_for_https.IsEmpty() && | |
| 151 rules.proxies_for_ftp.IsEmpty() && | |
| 152 rules.fallback_proxies.IsEmpty()) { | |
| 153 return false; | |
| 154 } | |
| 155 mode = MODE_PROXY_PER_SCHEME; | |
| 156 if (!rules.proxies_for_http.IsEmpty()) | |
| 157 http_proxy.server = rules.proxies_for_http.Get(); | |
| 158 if (!rules.proxies_for_https.IsEmpty()) | |
| 159 https_proxy.server = rules.proxies_for_https.Get(); | |
| 160 if (!rules.proxies_for_ftp.IsEmpty()) | |
| 161 ftp_proxy.server = rules.proxies_for_ftp.Get(); | |
| 162 if (!rules.fallback_proxies.IsEmpty()) | |
| 163 socks_proxy.server = rules.fallback_proxies.Get(); | |
| 164 bypass_rules = rules.bypass_rules; | |
| 165 return true; | |
| 166 default: | |
| 167 NOTREACHED() << "Unrecognized proxy config mode"; | |
| 168 break; | |
| 169 } | |
| 170 return false; | |
| 171 } | |
| 172 | |
| 173 DictionaryValue* ProxyConfigServiceImpl::ProxyConfig::ToPrefProxyConfig() { | |
| 174 switch (mode) { | |
| 175 case MODE_DIRECT: { | |
| 176 return ProxyConfigDictionary::CreateDirect(); | |
| 177 } | |
| 178 case MODE_AUTO_DETECT: { | |
| 179 return ProxyConfigDictionary::CreateAutoDetect(); | |
| 180 } | |
| 181 case MODE_PAC_SCRIPT: { | |
| 182 return ProxyConfigDictionary::CreatePacScript( | |
| 183 automatic_proxy.pac_url.spec(), false); | |
| 184 } | |
| 185 case MODE_SINGLE_PROXY: { | |
| 186 std::string spec; | |
| 187 if (single_proxy.server.is_valid()) | |
| 188 spec = single_proxy.server.ToURI(); | |
| 189 return ProxyConfigDictionary::CreateFixedServers( | |
| 190 spec, bypass_rules.ToString()); | |
| 191 } | |
| 192 case MODE_PROXY_PER_SCHEME: { | |
| 193 std::string spec; | |
| 194 EncodeAndAppendProxyServer("http", http_proxy.server, &spec); | |
| 195 EncodeAndAppendProxyServer("https", https_proxy.server, &spec); | |
| 196 EncodeAndAppendProxyServer("ftp", ftp_proxy.server, &spec); | |
| 197 EncodeAndAppendProxyServer("socks", socks_proxy.server, &spec); | |
| 198 return ProxyConfigDictionary::CreateFixedServers( | |
| 199 spec, bypass_rules.ToString()); | |
| 200 } | |
| 201 default: | |
| 202 break; | |
| 203 } | |
| 204 NOTREACHED() << "Unrecognized proxy config mode for preference"; | |
| 205 return NULL; | |
| 206 } | |
| 207 | |
| 208 ProxyConfigServiceImpl::ProxyConfig::ManualProxy* | |
| 209 ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy( | |
| 210 const std::string& scheme) { | |
| 211 if (scheme == "http") | |
| 212 return &http_proxy; | |
| 213 if (scheme == "https") | |
| 214 return &https_proxy; | |
| 215 if (scheme == "ftp") | |
| 216 return &ftp_proxy; | |
| 217 if (scheme == "socks") | |
| 218 return &socks_proxy; | |
| 219 NOTREACHED() << "Invalid scheme: " << scheme; | |
| 220 return NULL; | |
| 221 } | |
| 222 | |
| 223 bool ProxyConfigServiceImpl::ProxyConfig::SerializeForNetwork( | |
| 224 std::string* output) { | |
| 225 scoped_ptr<DictionaryValue> proxy_dict_ptr(ToPrefProxyConfig()); | |
| 226 if (!proxy_dict_ptr.get()) | |
| 227 return false; | |
| 228 | |
| 229 // Return empty string for direct mode for portal check to work correctly. | |
| 230 DictionaryValue *dict = proxy_dict_ptr.get(); | |
| 231 ProxyConfigDictionary proxy_dict(dict); | |
| 232 ProxyPrefs::ProxyMode mode; | |
| 233 if (proxy_dict.GetMode(&mode)) { | |
| 234 if (mode == ProxyPrefs::MODE_DIRECT) { | |
| 235 output->clear(); | |
| 236 return true; | |
| 237 } | |
| 238 } | |
| 239 JSONStringValueSerializer serializer(output); | |
| 240 return serializer.Serialize(*dict); | |
| 241 } | |
| 242 | |
| 243 //----------- ProxyConfigServiceImpl::ProxyConfig: private methods ------------- | |
| 244 | |
| 245 // static | |
| 246 void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer( | |
| 247 const std::string& url_scheme, | |
| 248 const net::ProxyServer& server, | |
| 249 std::string* spec) { | |
| 250 if (!server.is_valid()) | |
| 251 return; | |
| 252 | |
| 253 if (!spec->empty()) | |
| 254 *spec += ';'; | |
| 255 | |
| 256 if (!url_scheme.empty()) { | |
| 257 *spec += url_scheme; | |
| 258 *spec += "="; | |
| 259 } | |
| 260 *spec += server.ToURI(); | |
| 261 } | |
| 262 | |
| 263 //------------------- ProxyConfigServiceImpl: public methods ------------------- | |
| 264 | |
| 265 ProxyConfigServiceImpl::ProxyConfigServiceImpl(PrefService* pref_service) | 44 ProxyConfigServiceImpl::ProxyConfigServiceImpl(PrefService* pref_service) |
| 266 : PrefProxyConfigTrackerImpl(pref_service), | 45 : PrefProxyConfigTrackerImpl(pref_service), |
| 267 active_config_state_(ProxyPrefs::CONFIG_UNSET), | 46 active_config_state_(ProxyPrefs::CONFIG_UNSET), |
| 47 ui_proxy_config_service_(pref_service), |
| 268 pointer_factory_(this) { | 48 pointer_factory_(this) { |
| 269 | 49 |
| 270 // Register for notifications of UseSharedProxies user preference. | 50 // Register for notifications of UseSharedProxies user preference. |
| 271 if (pref_service->FindPreference(prefs::kUseSharedProxies)) { | 51 if (pref_service->FindPreference(prefs::kUseSharedProxies)) { |
| 272 use_shared_proxies_.Init( | 52 use_shared_proxies_.Init( |
| 273 prefs::kUseSharedProxies, pref_service, | 53 prefs::kUseSharedProxies, pref_service, |
| 274 base::Bind(&ProxyConfigServiceImpl::OnUseSharedProxiesChanged, | 54 base::Bind(&ProxyConfigServiceImpl::OnUseSharedProxiesChanged, |
| 275 base::Unretained(this))); | 55 base::Unretained(this))); |
| 276 } | 56 } |
| 277 | 57 |
| 278 // Register for shill network notifications. | 58 // Register for changes to the default network. |
| 279 NetworkLibrary* network_lib = CrosLibrary::Get()->GetNetworkLibrary(); | 59 NetworkStateHandler* state_handler = |
| 280 OnActiveNetworkChanged(network_lib, network_lib->active_network()); | 60 NetworkHandler::Get()->network_state_handler(); |
| 281 network_lib->AddNetworkManagerObserver(this); | 61 state_handler->AddObserver(this); |
| 62 DefaultNetworkChanged(state_handler->DefaultNetwork()); |
| 282 } | 63 } |
| 283 | 64 |
| 284 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() { | 65 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() { |
| 285 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary(); | 66 if (NetworkHandler::IsInitialized()) |
| 286 if (netlib) { | 67 NetworkHandler::Get()->network_state_handler()->RemoveObserver(this); |
| 287 netlib->RemoveNetworkManagerObserver(this); | |
| 288 netlib->RemoveObserverForAllNetworks(this); | |
| 289 } | |
| 290 } | 68 } |
| 291 | 69 |
| 292 void ProxyConfigServiceImpl::UISetCurrentNetwork( | 70 UIProxyConfigService& ProxyConfigServiceImpl::GetUIService() { |
| 293 const std::string& current_network) { | 71 return ui_proxy_config_service_; |
| 294 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( | |
| 295 current_network); | |
| 296 if (!network) { | |
| 297 ResetUICache(); | |
| 298 LOG(ERROR) << "Can't find requested network " << current_network; | |
| 299 return; | |
| 300 } | |
| 301 current_ui_network_ = current_network; | |
| 302 OnUISetCurrentNetwork(network); | |
| 303 } | |
| 304 | |
| 305 void ProxyConfigServiceImpl::UIMakeActiveNetworkCurrent() { | |
| 306 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( | |
| 307 active_network_); | |
| 308 if (!network) { | |
| 309 ResetUICache(); | |
| 310 LOG(ERROR) << "Can't find requested network " << active_network_; | |
| 311 return; | |
| 312 } | |
| 313 current_ui_network_ = active_network_; | |
| 314 OnUISetCurrentNetwork(network); | |
| 315 } | |
| 316 | |
| 317 void ProxyConfigServiceImpl::UIGetCurrentNetworkName( | |
| 318 std::string* network_name) { | |
| 319 if (!network_name) | |
| 320 return; | |
| 321 network_name->clear(); | |
| 322 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( | |
| 323 current_ui_network_); | |
| 324 if (!network) { | |
| 325 LOG(ERROR) << "Can't find requested network " << current_ui_network_; | |
| 326 return; | |
| 327 } | |
| 328 if (network->name().empty() && network->type() == chromeos::TYPE_ETHERNET) { | |
| 329 *network_name = | |
| 330 l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); | |
| 331 } else { | |
| 332 *network_name = network->name(); | |
| 333 } | |
| 334 } | |
| 335 | |
| 336 void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) { | |
| 337 // Simply returns the copy last set from UI via UISetCurrentNetwork or | |
| 338 // UIMakeActiveNetworkCurrent. | |
| 339 *config = current_ui_config_; | |
| 340 } | |
| 341 | |
| 342 bool ProxyConfigServiceImpl::UISetProxyConfigToDirect() { | |
| 343 current_ui_config_.mode = ProxyConfig::MODE_DIRECT; | |
| 344 OnUISetProxyConfig(); | |
| 345 return true; | |
| 346 } | |
| 347 | |
| 348 bool ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() { | |
| 349 current_ui_config_.mode = ProxyConfig::MODE_AUTO_DETECT; | |
| 350 OnUISetProxyConfig(); | |
| 351 return true; | |
| 352 } | |
| 353 | |
| 354 bool ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& pac_url) { | |
| 355 current_ui_config_.mode = ProxyConfig::MODE_PAC_SCRIPT; | |
| 356 current_ui_config_.automatic_proxy.pac_url = pac_url; | |
| 357 OnUISetProxyConfig(); | |
| 358 return true; | |
| 359 } | |
| 360 | |
| 361 bool ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy( | |
| 362 const net::ProxyServer& server) { | |
| 363 current_ui_config_.mode = ProxyConfig::MODE_SINGLE_PROXY; | |
| 364 current_ui_config_.single_proxy.server = server; | |
| 365 OnUISetProxyConfig(); | |
| 366 return true; | |
| 367 } | |
| 368 | |
| 369 bool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme( | |
| 370 const std::string& scheme, const net::ProxyServer& server) { | |
| 371 ProxyConfig::ManualProxy* proxy = current_ui_config_.MapSchemeToProxy(scheme); | |
| 372 if (!proxy) { | |
| 373 NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]"; | |
| 374 return false; | |
| 375 } | |
| 376 current_ui_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME; | |
| 377 proxy->server = server; | |
| 378 OnUISetProxyConfig(); | |
| 379 return true; | |
| 380 } | |
| 381 | |
| 382 bool ProxyConfigServiceImpl::UISetProxyConfigBypassRules( | |
| 383 const net::ProxyBypassRules& bypass_rules) { | |
| 384 if (current_ui_config_.mode != ProxyConfig::MODE_SINGLE_PROXY && | |
| 385 current_ui_config_.mode != ProxyConfig::MODE_PROXY_PER_SCHEME) { | |
| 386 NOTREACHED(); | |
| 387 VLOG(1) << "Cannot set bypass rules for proxy mode [" | |
| 388 << current_ui_config_.mode << "]"; | |
| 389 return false; | |
| 390 } | |
| 391 current_ui_config_.bypass_rules = bypass_rules; | |
| 392 OnUISetProxyConfig(); | |
| 393 return true; | |
| 394 } | |
| 395 | |
| 396 void ProxyConfigServiceImpl::AddNotificationCallback(base::Closure callback) { | |
| 397 | |
| 398 std::vector<base::Closure>::iterator iter = | |
| 399 findIfEqual(callbacks_.begin(), callbacks_.end(), callback); | |
| 400 if (iter == callbacks_.end()) | |
| 401 callbacks_.push_back(callback); | |
| 402 } | |
| 403 | |
| 404 void ProxyConfigServiceImpl::RemoveNotificationCallback( | |
| 405 base::Closure callback) { | |
| 406 std::vector<base::Closure>::iterator iter = | |
| 407 findIfEqual(callbacks_.begin(), callbacks_.end(), callback); | |
| 408 if (iter != callbacks_.end()) | |
| 409 callbacks_.erase(iter); | |
| 410 } | 72 } |
| 411 | 73 |
| 412 void ProxyConfigServiceImpl::OnProxyConfigChanged( | 74 void ProxyConfigServiceImpl::OnProxyConfigChanged( |
| 413 ProxyPrefs::ConfigState config_state, | 75 ProxyPrefs::ConfigState config_state, |
| 414 const net::ProxyConfig& config) { | 76 const net::ProxyConfig& config) { |
| 415 VLOG(1) << "Got prefs change: " << ConfigStateToString(config_state) | 77 VLOG(1) << "Got prefs change: " |
| 78 << ProxyPrefs::ConfigStateToDebugString(config_state) |
| 416 << ", mode=" << config.proxy_rules().type; | 79 << ", mode=" << config.proxy_rules().type; |
| 417 Network* network = NULL; | 80 DetermineEffectiveConfigFromDefaultNetwork(); |
| 418 if (!active_network_.empty()) { | |
| 419 network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( | |
| 420 active_network_); | |
| 421 if (!network) | |
| 422 LOG(ERROR) << "can't find requested network " << active_network_; | |
| 423 } | |
| 424 DetermineEffectiveConfig(network, true); | |
| 425 } | |
| 426 | |
| 427 void ProxyConfigServiceImpl::OnNetworkManagerChanged( | |
| 428 NetworkLibrary* network_lib) { | |
| 429 VLOG(1) << "OnNetworkManagerChanged: use-shared-proxies=" | |
| 430 << GetUseSharedProxies(); | |
| 431 OnActiveNetworkChanged(network_lib, network_lib->active_network()); | |
| 432 } | |
| 433 | |
| 434 void ProxyConfigServiceImpl::OnNetworkChanged(NetworkLibrary* network_lib, | |
| 435 const Network* network) { | |
| 436 if (!network) | |
| 437 return; | |
| 438 VLOG(1) << "OnNetworkChanged: " | |
| 439 << (network->name().empty() ? network->service_path() : | |
| 440 network->name()) | |
| 441 << ", use-shared-proxies=" << GetUseSharedProxies(); | |
| 442 // We only care about active network. | |
| 443 if (network == network_lib->active_network()) | |
| 444 OnActiveNetworkChanged(network_lib, network); | |
| 445 } | 81 } |
| 446 | 82 |
| 447 // static | 83 // static |
| 448 bool ProxyConfigServiceImpl::ParseProxyConfig( | |
| 449 const std::string& proxy_config_string, | |
| 450 net::ProxyConfig* proxy_config) { | |
| 451 if (!proxy_config) | |
| 452 return false; | |
| 453 JSONStringValueSerializer serializer(proxy_config_string); | |
| 454 scoped_ptr<Value> value(serializer.Deserialize(NULL, NULL)); | |
| 455 if (!value.get() || value->GetType() != Value::TYPE_DICTIONARY) | |
| 456 return false; | |
| 457 ProxyConfigDictionary proxy_dict(static_cast<DictionaryValue*>(value.get())); | |
| 458 return PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(proxy_dict, | |
| 459 proxy_config); | |
| 460 } | |
| 461 | |
| 462 // static | |
| 463 void ProxyConfigServiceImpl::RegisterPrefs(PrefRegistrySimple* registry) { | 84 void ProxyConfigServiceImpl::RegisterPrefs(PrefRegistrySimple* registry) { |
| 464 // Use shared proxies default to off. GetUseSharedProxies will return the | 85 // Use shared proxies default to off. GetUseSharedProxies will return the |
| 465 // correct value based on pre-login and login. | 86 // correct value based on pre-login and login. |
| 466 registry->RegisterBooleanPref(prefs::kUseSharedProxies, true); | 87 registry->RegisterBooleanPref(prefs::kUseSharedProxies, true); |
| 467 } | 88 } |
| 468 | 89 |
| 469 // static | 90 // static |
| 470 void ProxyConfigServiceImpl::RegisterUserPrefs( | 91 void ProxyConfigServiceImpl::RegisterUserPrefs( |
| 471 user_prefs::PrefRegistrySyncable* registry) { | 92 user_prefs::PrefRegistrySyncable* registry) { |
| 472 registry->RegisterBooleanPref( | 93 registry->RegisterBooleanPref( |
| 473 prefs::kUseSharedProxies, | 94 prefs::kUseSharedProxies, |
| 474 true, | 95 true, |
| 475 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 96 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 476 } | 97 } |
| 477 | 98 |
| 478 //------------------ ProxyConfigServiceImpl: private methods ------------------- | |
| 479 | |
| 480 void ProxyConfigServiceImpl::OnUseSharedProxiesChanged() { | 99 void ProxyConfigServiceImpl::OnUseSharedProxiesChanged() { |
| 481 VLOG(1) << "New use-shared-proxies = " << GetUseSharedProxies(); | 100 VLOG(1) << "New use-shared-proxies = " << GetUseSharedProxies(prefs()); |
| 482 | 101 DetermineEffectiveConfigFromDefaultNetwork(); |
| 483 // Determine new proxy config which may have changed because of new | |
| 484 // use-shared-proxies. If necessary, activate it. | |
| 485 Network* network = NULL; | |
| 486 if (!active_network_.empty()) { | |
| 487 network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( | |
| 488 active_network_); | |
| 489 if (!network) | |
| 490 LOG(WARNING) << "Can't find requested network " << active_network_; | |
| 491 } | |
| 492 DetermineEffectiveConfig(network, true); | |
| 493 } | 102 } |
| 494 | 103 |
| 495 void ProxyConfigServiceImpl::OnUISetProxyConfig() { | 104 void ProxyConfigServiceImpl::DefaultNetworkChanged( |
| 496 if (current_ui_network_.empty()) | 105 const NetworkState* new_network) { |
| 497 return; | 106 std::string new_network_path; |
| 498 // Update config to shill. | 107 if (new_network) |
| 499 std::string value; | 108 new_network_path = new_network->path(); |
| 500 if (current_ui_config_.SerializeForNetwork(&value)) { | 109 |
| 501 VLOG(1) << "Set proxy (mode=" << current_ui_config_.mode | 110 VLOG(1) << "DefaultNetworkChanged to '" << new_network_path << "'."; |
| 502 << ") for " << current_ui_network_; | 111 VLOG_IF(1, new_network) << "New network: name=" << new_network->name() |
| 503 current_ui_config_.state = ProxyPrefs::CONFIG_SYSTEM; | 112 << ", proxy=" << new_network->proxy_config() |
| 504 SetProxyConfigForNetwork(current_ui_network_, value, false); | 113 << ", profile=" << new_network->profile_path(); |
| 505 } | 114 |
| 115 // Even if the default network is the same, its proxy config (e.g. if private |
| 116 // version of network replaces the shared version after login), or |
| 117 // use-shared-proxies setting (e.g. after login) may have changed, so |
| 118 // re-determine effective proxy config, and activate if different. |
| 119 DetermineEffectiveConfigFromDefaultNetwork(); |
| 506 } | 120 } |
| 507 | 121 |
| 508 void ProxyConfigServiceImpl::OnActiveNetworkChanged(NetworkLibrary* network_lib, | 122 // static |
| 509 const Network* active_network) { | 123 bool ProxyConfigServiceImpl::GetUseSharedProxies( |
| 510 std::string new_network; | 124 const PrefService* pref_service) { |
| 511 if (active_network) | 125 const PrefService::Preference* use_shared_proxies_pref = |
| 512 new_network = active_network->service_path(); | 126 pref_service->FindPreference(prefs::kUseSharedProxies); |
| 127 if (!use_shared_proxies_pref || !use_shared_proxies_pref->GetValue()) { |
| 128 if (UserManager::Get()->IsUserLoggedIn()) { |
| 129 VLOG(1) << "use-shared-proxies not set, defaulting to false/IgnoreProxy."; |
| 130 return false; |
| 131 } else { |
| 132 // Make sure that proxies are always enabled at sign in screen. |
| 133 VLOG(1) << "Use proxy on login screen."; |
| 134 return true; |
| 135 } |
| 136 } |
| 137 bool use_shared_proxies = false; |
| 138 use_shared_proxies_pref->GetValue()->GetAsBoolean(&use_shared_proxies); |
| 139 return use_shared_proxies; |
| 140 } |
| 513 | 141 |
| 514 if (active_network_ == new_network) { // Same active network. | 142 // static |
| 515 VLOG(1) << "Same active network: " | 143 bool ProxyConfigServiceImpl::IgnoreProxy(const PrefService* pref_service, |
| 516 << (new_network.empty() ? "empty" : | 144 const std::string network_profile_path, |
| 517 (active_network->name().empty() ? | 145 onc::ONCSource onc_source) { |
| 518 new_network : active_network->name())); | 146 const NetworkProfile* profile = |
| 519 // Even though network is the same, its proxy config (e.g. if private | 147 NetworkHandler::Get()->network_profile_handler()-> |
| 520 // version of network replaces the shared version after login), or | 148 GetProfileForPath(network_profile_path); |
| 521 // use-shared-proxies setting (e.g. after login) may have changed, | 149 if (!profile) { |
| 522 // so re-determine effective proxy config, and activate if different. | 150 LOG(WARNING) << "Unknown profile_path " << network_profile_path; |
| 523 if (active_network) { | 151 return true; |
| 524 VLOG(1) << "Profile=" << active_network->profile_type() | 152 } |
| 525 << "," << active_network->profile_path() | 153 if (profile->type() == NetworkProfile::TYPE_USER) { |
| 526 << ", proxy=" << active_network->proxy_config(); | 154 VLOG(1) << "Respect proxy of not-shared networks."; |
| 527 DetermineEffectiveConfig(active_network, true); | 155 return false; |
| 528 } | |
| 529 return; | |
| 530 } | 156 } |
| 531 | 157 |
| 532 // If there was a previous active network, remove it as observer. | 158 if (onc_source == onc::ONC_SOURCE_DEVICE_POLICY && |
| 533 if (!active_network_.empty()) | |
| 534 network_lib->RemoveNetworkObserver(active_network_, this); | |
| 535 | |
| 536 active_network_ = new_network; | |
| 537 | |
| 538 if (active_network_.empty()) { | |
| 539 VLOG(1) << "New active network: empty"; | |
| 540 DetermineEffectiveConfig(active_network, true); | |
| 541 return; | |
| 542 } | |
| 543 | |
| 544 VLOG(1) << "New active network: path=" << active_network->service_path() | |
| 545 << ", name=" << active_network->name() | |
| 546 << ", profile=" << active_network->profile_type() | |
| 547 << "," << active_network->profile_path() | |
| 548 << ", proxy=" << active_network->proxy_config(); | |
| 549 | |
| 550 // Register observer for new network. | |
| 551 network_lib->AddNetworkObserver(active_network_, this); | |
| 552 | |
| 553 // Determine and activate possibly new effective proxy config. | |
| 554 DetermineEffectiveConfig(active_network, true); | |
| 555 } | |
| 556 | |
| 557 void ProxyConfigServiceImpl::SetProxyConfigForNetwork( | |
| 558 const std::string& network_path, const std::string& value, | |
| 559 bool only_set_if_empty) { | |
| 560 Network* network = CrosLibrary::Get()->GetNetworkLibrary()->FindNetworkByPath( | |
| 561 network_path); | |
| 562 if (!network) { | |
| 563 NOTREACHED() << "Can't find requested network " << network_path; | |
| 564 return; | |
| 565 } | |
| 566 if (!only_set_if_empty || network->proxy_config().empty()) { | |
| 567 network->SetProxyConfig(value); | |
| 568 VLOG(1) << "Set proxy for " | |
| 569 << (network->name().empty() ? network_path : network->name()) | |
| 570 << ", value=" << value; | |
| 571 if (network_path == active_network_) | |
| 572 DetermineEffectiveConfig(network, true); | |
| 573 } | |
| 574 } | |
| 575 | |
| 576 bool ProxyConfigServiceImpl::GetUseSharedProxies() { | |
| 577 const PrefService::Preference* use_shared_proxies_pref = | |
| 578 prefs()->FindPreference(prefs::kUseSharedProxies); | |
| 579 if (!use_shared_proxies_pref) { | |
| 580 // Make sure that proxies are always enabled at sign in screen. | |
| 581 return !UserManager::Get()->IsUserLoggedIn(); | |
| 582 } | |
| 583 return use_shared_proxies_.GetValue(); | |
| 584 } | |
| 585 | |
| 586 bool ProxyConfigServiceImpl::IgnoreProxy(const Network* network) { | |
| 587 if (network->profile_type() == PROFILE_USER) | |
| 588 return false; | |
| 589 | |
| 590 if (network->ui_data().onc_source() == onc::ONC_SOURCE_DEVICE_POLICY && | |
| 591 UserManager::Get()->IsUserLoggedIn()) { | 159 UserManager::Get()->IsUserLoggedIn()) { |
| 592 policy::BrowserPolicyConnector* connector = | 160 policy::BrowserPolicyConnector* connector = |
| 593 g_browser_process->browser_policy_connector(); | 161 g_browser_process->browser_policy_connector(); |
| 594 const User* logged_in_user = UserManager::Get()->GetLoggedInUser(); | 162 const User* logged_in_user = UserManager::Get()->GetLoggedInUser(); |
| 595 if (connector->GetUserAffiliation(logged_in_user->email()) == | 163 if (connector->GetUserAffiliation(logged_in_user->email()) == |
| 596 policy::USER_AFFILIATION_MANAGED) { | 164 policy::USER_AFFILIATION_MANAGED) { |
| 597 VLOG(1) << "Respecting proxy for network " << network->name() | 165 VLOG(1) << "Respecting proxy for network, as logged-in user belongs to " |
| 598 << ", as logged-in user belongs to the domain the device " | 166 << "the domain the device is enrolled to."; |
| 599 << "is enrolled to."; | |
| 600 return false; | 167 return false; |
| 601 } | 168 } |
| 602 } | 169 } |
| 603 | 170 |
| 604 return !GetUseSharedProxies(); | 171 return !GetUseSharedProxies(pref_service); |
| 605 } | 172 } |
| 606 | 173 |
| 607 void ProxyConfigServiceImpl::DetermineEffectiveConfig(const Network* network, | 174 void ProxyConfigServiceImpl::DetermineEffectiveConfigFromDefaultNetwork() { |
| 608 bool activate) { | 175 const NetworkState* network = |
| 176 NetworkHandler::Get()->network_state_handler()->DefaultNetwork(); |
| 177 |
| 609 // Get prefs proxy config if available. | 178 // Get prefs proxy config if available. |
| 610 net::ProxyConfig pref_config; | 179 net::ProxyConfig pref_config; |
| 611 ProxyPrefs::ConfigState pref_state = GetProxyConfig(&pref_config); | 180 ProxyPrefs::ConfigState pref_state = GetProxyConfig(&pref_config); |
| 612 | 181 |
| 613 // Get network proxy config if available. | 182 // Get network proxy config if available. |
| 614 net::ProxyConfig network_config; | 183 net::ProxyConfig network_config; |
| 615 net::ProxyConfigService::ConfigAvailability network_availability = | 184 net::ProxyConfigService::ConfigAvailability network_availability = |
| 616 net::ProxyConfigService::CONFIG_UNSET; | 185 net::ProxyConfigService::CONFIG_UNSET; |
| 617 bool ignore_proxy = activate; | 186 bool ignore_proxy = true; |
| 618 if (network) { | 187 if (network) { |
| 619 // If we're activating proxy, ignore proxy if necessary; | 188 ignore_proxy = |
| 620 // otherwise, for ui, get actual proxy to show user. | 189 IgnoreProxy(prefs(), network->profile_path(), network->onc_source()); |
| 621 ignore_proxy = activate ? IgnoreProxy(network) : false; | |
| 622 // If network is shared but use-shared-proxies is off, use direct mode. | 190 // If network is shared but use-shared-proxies is off, use direct mode. |
| 623 if (ignore_proxy) { | 191 if (ignore_proxy) { |
| 624 VLOG(1) << "Shared network && !use-shared-proxies, use direct"; | 192 VLOG(1) << "Shared network && !use-shared-proxies, use direct"; |
| 625 network_availability = net::ProxyConfigService::CONFIG_VALID; | 193 network_availability = net::ProxyConfigService::CONFIG_VALID; |
| 626 } else if (!network->proxy_config().empty()) { | 194 } else if (ParseProxyConfig(network->proxy_config(), &network_config)) { |
| 627 // Network is private or shared with user using shared proxies. | 195 // Network is private or shared with user using shared proxies. |
| 628 if (ParseProxyConfig(network->proxy_config(), &network_config)) { | 196 VLOG(1) << this << ": using network proxy: " |
| 629 VLOG(1) << this << ": using network proxy: " | 197 << network->proxy_config(); |
| 630 << network->proxy_config(); | 198 network_availability = net::ProxyConfigService::CONFIG_VALID; |
| 631 network_availability = net::ProxyConfigService::CONFIG_VALID; | |
| 632 } | |
| 633 } | 199 } |
| 634 } | 200 } |
| 635 | 201 |
| 636 // Determine effective proxy config, either from prefs or network. | 202 // Determine effective proxy config, either from prefs or network. |
| 637 ProxyPrefs::ConfigState effective_config_state; | 203 ProxyPrefs::ConfigState effective_config_state; |
| 638 net::ProxyConfig effective_config; | 204 net::ProxyConfig effective_config; |
| 639 GetEffectiveProxyConfig(pref_state, pref_config, | 205 GetEffectiveProxyConfig(pref_state, pref_config, |
| 640 network_availability, network_config, ignore_proxy, | 206 network_availability, network_config, ignore_proxy, |
| 641 &effective_config_state, &effective_config); | 207 &effective_config_state, &effective_config); |
| 642 | 208 |
| 643 // Determine if we should activate effective proxy and which proxy config to | 209 // Activate effective proxy and store into |active_config_|. |
| 644 // store it. | 210 // If last update didn't complete, we definitely update now. |
| 645 if (activate) { // Activate effective proxy and store into |active_config_|. | 211 bool update_now = update_pending(); |
| 646 // If last update didn't complete, we definitely update now. | 212 if (!update_now) { // Otherwise, only update now if there're changes. |
| 647 bool update_now = update_pending(); | 213 update_now = active_config_state_ != effective_config_state || |
| 648 if (!update_now) { // Otherwise, only update now if there're changes. | 214 (active_config_state_ != ProxyPrefs::CONFIG_UNSET && |
| 649 update_now = active_config_state_ != effective_config_state || | 215 !active_config_.Equals(effective_config)); |
| 650 (active_config_state_ != ProxyPrefs::CONFIG_UNSET && | 216 } |
| 651 !active_config_.Equals(effective_config)); | 217 if (update_now) { // Activate and store new effective config. |
| 652 } | 218 active_config_state_ = effective_config_state; |
| 653 if (update_now) { // Activate and store new effective config. | 219 if (active_config_state_ != ProxyPrefs::CONFIG_UNSET) |
| 654 active_config_state_ = effective_config_state; | 220 active_config_ = effective_config; |
| 655 if (active_config_state_ != ProxyPrefs::CONFIG_UNSET) | 221 // If effective config is from system (i.e. network), it's considered a |
| 656 active_config_ = effective_config; | 222 // special kind of prefs that ranks below policy/extension but above |
| 657 // If effective config is from system (i.e. network), it's considered a | 223 // others, so bump it up to CONFIG_OTHER_PRECEDE to force its precedence |
| 658 // special kind of prefs that ranks below policy/extension but above | 224 // when PrefProxyConfigTrackerImpl pushes it to ChromeProxyConfigService. |
| 659 // others, so bump it up to CONFIG_OTHER_PRECEDE to force its precedence | 225 if (effective_config_state == ProxyPrefs::CONFIG_SYSTEM) |
| 660 // when PrefProxyConfigTrackerImpl pushes it to ChromeProxyConfigService. | 226 effective_config_state = ProxyPrefs::CONFIG_OTHER_PRECEDE; |
| 661 if (effective_config_state == ProxyPrefs::CONFIG_SYSTEM) | 227 // If config is manual, add rule to bypass local host. |
| 662 effective_config_state = ProxyPrefs::CONFIG_OTHER_PRECEDE; | 228 if (effective_config.proxy_rules().type != |
| 663 // If config is manual, add rule to bypass local host. | 229 net::ProxyConfig::ProxyRules::TYPE_NO_RULES) |
| 664 if (effective_config.proxy_rules().type != | 230 effective_config.proxy_rules().bypass_rules.AddRuleToBypassLocal(); |
| 665 net::ProxyConfig::ProxyRules::TYPE_NO_RULES) | 231 PrefProxyConfigTrackerImpl::OnProxyConfigChanged(effective_config_state, |
| 666 effective_config.proxy_rules().bypass_rules.AddRuleToBypassLocal(); | 232 effective_config); |
| 667 PrefProxyConfigTrackerImpl::OnProxyConfigChanged(effective_config_state, | 233 if (VLOG_IS_ON(1) && !update_pending()) { // Update was successful. |
| 668 effective_config); | 234 scoped_ptr<base::DictionaryValue> config_dict( |
| 669 if (VLOG_IS_ON(1) && !update_pending()) { // Update was successful. | 235 effective_config.ToValue()); |
| 670 scoped_ptr<DictionaryValue> config_dict(static_cast<DictionaryValue*>( | 236 VLOG(1) << this << ": Proxy changed: " |
| 671 effective_config.ToValue())); | 237 << ProxyPrefs::ConfigStateToDebugString(active_config_state_) |
| 672 std::string config_value; | 238 << ", " << *config_dict; |
| 673 JSONStringValueSerializer serializer(&config_value); | |
| 674 serializer.Serialize(*config_dict.get()); | |
| 675 VLOG(1) << this << ": Proxy changed: " | |
| 676 << ConfigStateToString(active_config_state_) | |
| 677 << ", " << config_value; | |
| 678 } | |
| 679 } | |
| 680 } else { // For UI, store effective proxy into |current_ui_config_|. | |
| 681 current_ui_config_.FromNetProxyConfig(effective_config); | |
| 682 current_ui_config_.state = effective_config_state; | |
| 683 if (PrefPrecedes(effective_config_state)) { | |
| 684 current_ui_config_.user_modifiable = false; | |
| 685 } else if (!IsNetworkProxySettingsEditable(network)) { | |
| 686 // TODO(xiyuan): Figure out the right way to set config state for managed | |
| 687 // network. | |
| 688 current_ui_config_.state = ProxyPrefs::CONFIG_POLICY; | |
| 689 current_ui_config_.user_modifiable = false; | |
| 690 } else { | |
| 691 current_ui_config_.user_modifiable = !network || !IgnoreProxy(network); | |
| 692 } | 239 } |
| 693 } | 240 } |
| 694 } | 241 } |
| 695 | 242 |
| 696 void ProxyConfigServiceImpl::OnUISetCurrentNetwork(const Network* network) { | |
| 697 DetermineEffectiveConfig(network, false); | |
| 698 VLOG(1) << "Current ui network: " | |
| 699 << (network->name().empty() ? current_ui_network_ : network->name()) | |
| 700 << ", " << ModeToString(current_ui_config_.mode) | |
| 701 << ", " << ConfigStateToString(current_ui_config_.state) | |
| 702 << ", modifiable:" << current_ui_config_.user_modifiable; | |
| 703 // Notify whoever is interested in this change. | |
| 704 std::vector<base::Closure>::iterator iter = callbacks_.begin(); | |
| 705 while (iter != callbacks_.end()) { | |
| 706 if (iter->is_null()) { | |
| 707 iter = callbacks_.erase(iter); | |
| 708 } else { | |
| 709 iter->Run(); | |
| 710 ++iter; | |
| 711 } | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 void ProxyConfigServiceImpl::ResetUICache() { | |
| 716 current_ui_network_.clear(); | |
| 717 current_ui_config_ = ProxyConfig(); | |
| 718 } | |
| 719 | |
| 720 } // namespace chromeos | 243 } // namespace chromeos |
| OLD | NEW |