1 // Copyright 2013 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. 4 5 #include "chrome/browser/chromeos/ui_proxy_config_service.h" 6 7 #include "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/values.h" 10 #include "chrome/browser/chromeos/net/proxy_config_handler.h" 11 #include "chrome/browser/chromeos/proxy_config_service_impl.h" 12 #include "chromeos/network/network_state.h" 13 #include "chromeos/network/network_state_handler.h" 14 #include "net/proxy/proxy_config.h" 15 16 namespace chromeos { 17 18 namespace { 19 20 const char* ModeToString(UIProxyConfig::Mode mode) { 21 switch (mode) { 22 case UIProxyConfig::MODE_DIRECT: 23 return "direct"; 24 case UIProxyConfig::MODE_AUTO_DETECT: 25 return "auto-detect"; 26 case UIProxyConfig::MODE_PAC_SCRIPT: 27 return "pacurl"; 28 case UIProxyConfig::MODE_SINGLE_PROXY: 29 return "single-proxy"; 30 case UIProxyConfig::MODE_PROXY_PER_SCHEME: 31 return "proxy-per-scheme"; 32 } 33 NOTREACHED() << "Unrecognized mode type"; 34 return ""; 35 } 36 37 // Writes the proxy config of |network| to |proxy_config|. Sets |onc_source| to 38 // the source of this configuration. Returns false if no proxy was configured 39 // for this network. 40 bool GetProxyConfig(const PrefService* profile_prefs, 41 const PrefService* local_state_prefs, 42 const NetworkState& network, 43 net::ProxyConfig* proxy_config, 44 onc::ONCSource* onc_source) { 45 scoped_ptr<ProxyConfigDictionary> proxy_dict = 46 proxy_config::GetProxyConfigForNetwork( 47 profile_prefs, local_state_prefs, network, onc_source); 48 if (!proxy_dict) 49 return false; 50 return PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(*proxy_dict, 51 proxy_config); 52 } 53 54 // Returns true if proxy settings from |onc_source| are editable. 55 bool IsNetworkProxySettingsEditable(const onc::ONCSource onc_source) { 56 return onc_source != onc::ONC_SOURCE_DEVICE_POLICY && 57 onc_source != onc::ONC_SOURCE_USER_POLICY; 58 } 59 60 } // namespace 61 62 UIProxyConfigService::UIProxyConfigService() 63 : profile_prefs_(NULL), local_state_prefs_(NULL) { 64 } 65 66 UIProxyConfigService::~UIProxyConfigService() { 67 } 68 69 void UIProxyConfigService::SetPrefs(PrefService* profile_prefs, 70 PrefService* local_state_prefs) { 71 profile_prefs_ = profile_prefs; 72 local_state_prefs_ = local_state_prefs; 73 } 74 75 void UIProxyConfigService::SetCurrentNetwork( 76 const std::string& current_network) { 77 current_ui_network_ = current_network; 78 } 79 80 void UIProxyConfigService::UpdateFromPrefs() { 81 const NetworkState* network = NULL; 82 if (!current_ui_network_.empty()) { 83 network = NetworkHandler::Get() 84 ->network_state_handler() 85 ->GetNetworkStateFromServicePath(current_ui_network_, 86 true /* configured_only */); 87 LOG_IF(ERROR, !network) << "Couldn't find NetworkState for network " 88 << current_ui_network_; 89 } 90 if (!network) { 91 current_ui_network_.clear(); 92 current_ui_config_ = UIProxyConfig(); 93 return; 94 } 95 96 DetermineEffectiveConfig(*network); 97 VLOG(1) << "Current ui network: " << network->name() << ", " 98 << ModeToString(current_ui_config_.mode) << ", " 99 << ProxyPrefs::ConfigStateToDebugString(current_ui_config_.state) 100 << ", modifiable:" << current_ui_config_.user_modifiable; 101 } 102 103 void UIProxyConfigService::GetProxyConfig(UIProxyConfig* config) const { 104 *config = current_ui_config_; 105 } 106 107 void UIProxyConfigService::SetProxyConfig(const UIProxyConfig& config) { 108 current_ui_config_ = config; 109 if (current_ui_network_.empty()) 110 return; 111 112 const NetworkState* network = 113 NetworkHandler::Get() 114 ->network_state_handler() 115 ->GetNetworkStateFromServicePath(current_ui_network_, 116 true /* configured_only */); 117 if (!network) { 118 LOG(ERROR) << "Couldn't find NetworkState for network " 119 << current_ui_network_; 120 return; 121 } 122 123 // Store config for this network. 124 scoped_ptr<base::DictionaryValue> proxy_config_value( 125 config.ToPrefProxyConfig()); 126 ProxyConfigDictionary proxy_config_dict(proxy_config_value.get()); 127 128 VLOG(1) << "Set proxy for " << current_ui_network_ 129 << " to " << *proxy_config_value; 130 131 proxy_config::SetProxyConfigForNetwork(proxy_config_dict, *network); 132 current_ui_config_.state = ProxyPrefs::CONFIG_SYSTEM; 133 } 134 135 void UIProxyConfigService::DetermineEffectiveConfig( 136 const NetworkState& network) { 137 DCHECK(local_state_prefs_); 138 139 // The pref service to read proxy settings that apply to all networks. 140 // Settings from the profile overrule local state. 141 PrefService* top_pref_service = 142 profile_prefs_ ? profile_prefs_ : local_state_prefs_; 143 144 // Get prefs proxy config if available. 145 net::ProxyConfig pref_config; 146 ProxyPrefs::ConfigState pref_state = ProxyConfigServiceImpl::ReadPrefConfig( 147 top_pref_service, &pref_config); 148 149 // Get network proxy config if available. 150 net::ProxyConfig network_config; 151 net::ProxyConfigService::ConfigAvailability network_availability = 152 net::ProxyConfigService::CONFIG_UNSET; 153 onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; 154 if (chromeos::GetProxyConfig(profile_prefs_, 155 local_state_prefs_, 156 network, 157 &network_config, 158 &onc_source)) { 159 // Network is private or shared with user using shared proxies. 160 VLOG(1) << this << ": using proxy of network: " << network.path(); 161 network_availability = net::ProxyConfigService::CONFIG_VALID; 162 } 163 164 // Determine effective proxy config, either from prefs or network. 165 ProxyPrefs::ConfigState effective_config_state; 166 net::ProxyConfig effective_config; 167 ProxyConfigServiceImpl::GetEffectiveProxyConfig( 168 pref_state, pref_config, 169 network_availability, network_config, false, 170 &effective_config_state, &effective_config); 171 172 // Store effective proxy into |current_ui_config_|. 173 current_ui_config_.FromNetProxyConfig(effective_config); 174 current_ui_config_.state = effective_config_state; 175 if (ProxyConfigServiceImpl::PrefPrecedes(effective_config_state)) { 176 current_ui_config_.user_modifiable = false; 177 } else if (!IsNetworkProxySettingsEditable(onc_source)) { 178 current_ui_config_.state = ProxyPrefs::CONFIG_POLICY; 179 current_ui_config_.user_modifiable = false; 180 } else { 181 current_ui_config_.user_modifiable = !ProxyConfigServiceImpl::IgnoreProxy( 182 profile_prefs_, network.profile_path(), onc_source); 183 } 184 } 185 186 } // namespace chromeos 187