// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/ui_proxy_config_service.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" #include "chrome/browser/chromeos/net/proxy_config_handler.h" #include "chrome/browser/chromeos/proxy_config_service_impl.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "net/proxy/proxy_config.h" namespace chromeos { namespace { const char* ModeToString(UIProxyConfig::Mode mode) { switch (mode) { case UIProxyConfig::MODE_DIRECT: return "direct"; case UIProxyConfig::MODE_AUTO_DETECT: return "auto-detect"; case UIProxyConfig::MODE_PAC_SCRIPT: return "pacurl"; case UIProxyConfig::MODE_SINGLE_PROXY: return "single-proxy"; case UIProxyConfig::MODE_PROXY_PER_SCHEME: return "proxy-per-scheme"; } NOTREACHED() << "Unrecognized mode type"; return ""; } // Writes the proxy config of |network| to |proxy_config|. Sets |onc_source| to // the source of this configuration. Returns false if no proxy was configured // for this network. bool GetProxyConfig(const PrefService* profile_prefs, const PrefService* local_state_prefs, const NetworkState& network, net::ProxyConfig* proxy_config, onc::ONCSource* onc_source) { scoped_ptr proxy_dict = proxy_config::GetProxyConfigForNetwork( profile_prefs, local_state_prefs, network, onc_source); if (!proxy_dict) return false; return PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(*proxy_dict, proxy_config); } // Returns true if proxy settings from |onc_source| are editable. bool IsNetworkProxySettingsEditable(const onc::ONCSource onc_source) { return onc_source != onc::ONC_SOURCE_DEVICE_POLICY && onc_source != onc::ONC_SOURCE_USER_POLICY; } } // namespace UIProxyConfigService::UIProxyConfigService() : profile_prefs_(NULL), local_state_prefs_(NULL) { } UIProxyConfigService::~UIProxyConfigService() { } void UIProxyConfigService::SetPrefs(PrefService* profile_prefs, PrefService* local_state_prefs) { profile_prefs_ = profile_prefs; local_state_prefs_ = local_state_prefs; } void UIProxyConfigService::SetCurrentNetwork( const std::string& current_network) { current_ui_network_ = current_network; } void UIProxyConfigService::UpdateFromPrefs() { const NetworkState* network = NULL; if (!current_ui_network_.empty()) { network = NetworkHandler::Get() ->network_state_handler() ->GetNetworkStateFromServicePath(current_ui_network_, true /* configured_only */); LOG_IF(ERROR, !network) << "Couldn't find NetworkState for network " << current_ui_network_; } if (!network) { current_ui_network_.clear(); current_ui_config_ = UIProxyConfig(); return; } DetermineEffectiveConfig(*network); VLOG(1) << "Current ui network: " << network->name() << ", " << ModeToString(current_ui_config_.mode) << ", " << ProxyPrefs::ConfigStateToDebugString(current_ui_config_.state) << ", modifiable:" << current_ui_config_.user_modifiable; } void UIProxyConfigService::GetProxyConfig(UIProxyConfig* config) const { *config = current_ui_config_; } void UIProxyConfigService::SetProxyConfig(const UIProxyConfig& config) { current_ui_config_ = config; if (current_ui_network_.empty()) return; const NetworkState* network = NetworkHandler::Get() ->network_state_handler() ->GetNetworkStateFromServicePath(current_ui_network_, true /* configured_only */); if (!network) { LOG(ERROR) << "Couldn't find NetworkState for network " << current_ui_network_; return; } // Store config for this network. scoped_ptr proxy_config_value( config.ToPrefProxyConfig()); ProxyConfigDictionary proxy_config_dict(proxy_config_value.get()); VLOG(1) << "Set proxy for " << current_ui_network_ << " to " << *proxy_config_value; proxy_config::SetProxyConfigForNetwork(proxy_config_dict, *network); current_ui_config_.state = ProxyPrefs::CONFIG_SYSTEM; } void UIProxyConfigService::DetermineEffectiveConfig( const NetworkState& network) { DCHECK(local_state_prefs_); // The pref service to read proxy settings that apply to all networks. // Settings from the profile overrule local state. PrefService* top_pref_service = profile_prefs_ ? profile_prefs_ : local_state_prefs_; // Get prefs proxy config if available. net::ProxyConfig pref_config; ProxyPrefs::ConfigState pref_state = ProxyConfigServiceImpl::ReadPrefConfig( top_pref_service, &pref_config); // Get network proxy config if available. net::ProxyConfig network_config; net::ProxyConfigService::ConfigAvailability network_availability = net::ProxyConfigService::CONFIG_UNSET; onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; if (chromeos::GetProxyConfig(profile_prefs_, local_state_prefs_, network, &network_config, &onc_source)) { // Network is private or shared with user using shared proxies. VLOG(1) << this << ": using proxy of network: " << network.path(); network_availability = net::ProxyConfigService::CONFIG_VALID; } // Determine effective proxy config, either from prefs or network. ProxyPrefs::ConfigState effective_config_state; net::ProxyConfig effective_config; ProxyConfigServiceImpl::GetEffectiveProxyConfig( pref_state, pref_config, network_availability, network_config, false, &effective_config_state, &effective_config); // Store effective proxy into |current_ui_config_|. current_ui_config_.FromNetProxyConfig(effective_config); current_ui_config_.state = effective_config_state; if (ProxyConfigServiceImpl::PrefPrecedes(effective_config_state)) { current_ui_config_.user_modifiable = false; } else if (!IsNetworkProxySettingsEditable(onc_source)) { current_ui_config_.state = ProxyPrefs::CONFIG_POLICY; current_ui_config_.user_modifiable = false; } else { current_ui_config_.user_modifiable = !ProxyConfigServiceImpl::IgnoreProxy( profile_prefs_, network.profile_path(), onc_source); } } } // namespace chromeos