OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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/proxy_config_service_impl.h" |
| 6 |
| 7 #include <ostream> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/string_util.h" |
| 11 #include "base/task.h" |
| 12 #include "base/values.h" |
| 13 #include "chrome/browser/chrome_thread.h" |
| 14 |
| 15 namespace chromeos { |
| 16 |
| 17 namespace { |
| 18 |
| 19 const char* SourceToString(ProxyConfigServiceImpl::ProxyConfig::Source source) { |
| 20 switch (source) { |
| 21 case ProxyConfigServiceImpl::ProxyConfig::SOURCE_NONE: |
| 22 return "SOURCE_NONE"; |
| 23 case ProxyConfigServiceImpl::ProxyConfig::SOURCE_POLICY: |
| 24 return "SOURCE_POLICY"; |
| 25 case ProxyConfigServiceImpl::ProxyConfig::SOURCE_OWNER: |
| 26 return "SOURCE_OWNER"; |
| 27 } |
| 28 NOTREACHED() << "Unrecognized source type"; |
| 29 return ""; |
| 30 } |
| 31 |
| 32 std::ostream& operator<<(std::ostream& out, |
| 33 const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) { |
| 34 out << " " << SourceToString(proxy.source) << "\n" |
| 35 << " server: " << (proxy.server.is_valid() ? proxy.server.ToURI() : "") |
| 36 << "\n"; |
| 37 return out; |
| 38 } |
| 39 |
| 40 std::ostream& operator<<(std::ostream& out, |
| 41 const ProxyConfigServiceImpl::ProxyConfig& config) { |
| 42 switch (config.mode) { |
| 43 case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT: |
| 44 out << "Direct connection:\n " |
| 45 << SourceToString(config.automatic_proxy.source) << "\n"; |
| 46 break; |
| 47 case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT: |
| 48 out << "Auto detection:\n " |
| 49 << SourceToString(config.automatic_proxy.source) << "\n"; |
| 50 break; |
| 51 case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT: |
| 52 out << "Custom PAC script:\n " |
| 53 << SourceToString(config.automatic_proxy.source) |
| 54 << "\n PAC: " << config.automatic_proxy.pac_url << "\n"; |
| 55 break; |
| 56 case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY: |
| 57 out << "Single proxy:\n" << config.single_proxy; |
| 58 break; |
| 59 case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME: |
| 60 out << "HTTP proxy: " << config.http_proxy; |
| 61 out << "HTTPS proxy: " << config.https_proxy; |
| 62 out << "FTP proxy: " << config.ftp_proxy; |
| 63 out << "SOCKS proxy: " << config.socks_proxy; |
| 64 break; |
| 65 default: |
| 66 NOTREACHED() << "Unrecognized proxy config mode"; |
| 67 break; |
| 68 } |
| 69 if (config.mode == ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY || |
| 70 config.mode == |
| 71 ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) { |
| 72 out << "Bypass list: "; |
| 73 if (config.bypass_rules.rules().empty()) { |
| 74 out << "[None]"; |
| 75 } else { |
| 76 const net::ProxyBypassRules& bypass_rules = config.bypass_rules; |
| 77 net::ProxyBypassRules::RuleList::const_iterator it; |
| 78 for (it = bypass_rules.rules().begin(); |
| 79 it != bypass_rules.rules().end(); ++it) { |
| 80 out << "\n " << (*it)->ToString(); |
| 81 } |
| 82 } |
| 83 } |
| 84 return out; |
| 85 } |
| 86 |
| 87 std::string ProxyConfigToString( |
| 88 const ProxyConfigServiceImpl::ProxyConfig& proxy_config) { |
| 89 std::ostringstream stream; |
| 90 stream << proxy_config; |
| 91 return stream.str(); |
| 92 } |
| 93 |
| 94 } // namespace |
| 95 |
| 96 //-------------- ProxyConfigServiceImpl::ProxyConfig methods ------------------- |
| 97 |
| 98 bool ProxyConfigServiceImpl::ProxyConfig::Setting::CanBeWrittenByUser( |
| 99 bool user_is_owner) { |
| 100 // Setting can only be written by user if user is owner and setting is not |
| 101 // from policy. |
| 102 return user_is_owner && source != ProxyConfig::SOURCE_POLICY; |
| 103 } |
| 104 |
| 105 void ProxyConfigServiceImpl::ProxyConfig::ConvertToNetProxyConfig( |
| 106 net::ProxyConfig* net_config) { |
| 107 switch (mode) { |
| 108 case MODE_DIRECT: |
| 109 *net_config = net::ProxyConfig::CreateDirect(); |
| 110 break; |
| 111 case MODE_AUTO_DETECT: |
| 112 *net_config = net::ProxyConfig::CreateAutoDetect(); |
| 113 break; |
| 114 case MODE_PAC_SCRIPT: |
| 115 *net_config = net::ProxyConfig::CreateFromCustomPacURL( |
| 116 automatic_proxy.pac_url); |
| 117 break; |
| 118 case MODE_SINGLE_PROXY: |
| 119 *net_config = net::ProxyConfig(); |
| 120 net_config->proxy_rules().type = |
| 121 net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; |
| 122 net_config->proxy_rules().single_proxy = single_proxy.server; |
| 123 net_config->proxy_rules().bypass_rules = bypass_rules; |
| 124 break; |
| 125 case MODE_PROXY_PER_SCHEME: |
| 126 *net_config = net::ProxyConfig(); |
| 127 net_config->proxy_rules().type = |
| 128 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; |
| 129 net_config->proxy_rules().proxy_for_http = http_proxy.server; |
| 130 net_config->proxy_rules().proxy_for_https = https_proxy.server; |
| 131 net_config->proxy_rules().proxy_for_ftp = ftp_proxy.server; |
| 132 net_config->proxy_rules().socks_proxy = socks_proxy.server; |
| 133 net_config->proxy_rules().bypass_rules = bypass_rules; |
| 134 break; |
| 135 default: |
| 136 NOTREACHED() << "Unrecognized proxy config mode"; |
| 137 break; |
| 138 } |
| 139 } |
| 140 |
| 141 std::string ProxyConfigServiceImpl::ProxyConfig::ToString() const { |
| 142 return ProxyConfigToString(*this); |
| 143 } |
| 144 |
| 145 //------------------- ProxyConfigServiceImpl: public methods ------------------- |
| 146 |
| 147 ProxyConfigServiceImpl::ProxyConfigServiceImpl() { |
| 148 // Fetch and cache proxy config from cros settings persisted on device. |
| 149 // TODO(kuan): retrieve config from policy and owner and merge them |
| 150 // for now, hardcode it as AUTO_DETECT and it'll pick up the PAC script set in |
| 151 // chromeos environment. |
| 152 cached_config_.mode = ProxyConfig::MODE_AUTO_DETECT; |
| 153 cached_config_.automatic_proxy.source = ProxyConfig::SOURCE_OWNER; |
| 154 |
| 155 // Update the thread-private copy in |reference_config_| as well. |
| 156 reference_config_ = cached_config_; |
| 157 } |
| 158 |
| 159 ProxyConfigServiceImpl::ProxyConfigServiceImpl(const ProxyConfig& init_config) { |
| 160 cached_config_ = init_config; |
| 161 // Update the thread-private copy in |reference_config_| as well. |
| 162 reference_config_ = cached_config_; |
| 163 } |
| 164 |
| 165 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() { |
| 166 } |
| 167 |
| 168 void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) { |
| 169 // Should be called from UI thread. |
| 170 CheckCurrentlyOnUIThread(); |
| 171 // Simply returns the copy on the UI thread. |
| 172 *config = reference_config_; |
| 173 } |
| 174 |
| 175 void ProxyConfigServiceImpl::UISetProxyConfigToDirect() { |
| 176 // Should be called from UI thread. |
| 177 CheckCurrentlyOnUIThread(); |
| 178 reference_config_.mode = ProxyConfig::MODE_DIRECT; |
| 179 OnUISetProxyConfig(); |
| 180 } |
| 181 |
| 182 void ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() { |
| 183 // Should be called from UI thread. |
| 184 CheckCurrentlyOnUIThread(); |
| 185 reference_config_.mode = ProxyConfig::MODE_AUTO_DETECT; |
| 186 OnUISetProxyConfig(); |
| 187 } |
| 188 |
| 189 void ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& url) { |
| 190 // Should be called from UI thread. |
| 191 CheckCurrentlyOnUIThread(); |
| 192 reference_config_.mode = ProxyConfig::MODE_PAC_SCRIPT; |
| 193 reference_config_.automatic_proxy.pac_url = url; |
| 194 OnUISetProxyConfig(); |
| 195 } |
| 196 |
| 197 void ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy( |
| 198 const net::ProxyServer& server) { |
| 199 // Should be called from UI thread. |
| 200 CheckCurrentlyOnUIThread(); |
| 201 reference_config_.mode = ProxyConfig::MODE_SINGLE_PROXY; |
| 202 reference_config_.single_proxy.server = server; |
| 203 OnUISetProxyConfig(); |
| 204 } |
| 205 |
| 206 void ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme( |
| 207 const std::string& scheme, const net::ProxyServer& server) { |
| 208 // Should be called from UI thread. |
| 209 CheckCurrentlyOnUIThread(); |
| 210 ProxyConfig::ManualProxy* proxy = NULL; |
| 211 if (scheme == "http") |
| 212 proxy = &reference_config_.http_proxy; |
| 213 else if (scheme == "https") |
| 214 proxy = &reference_config_.https_proxy; |
| 215 else if (scheme == "ftp") |
| 216 proxy = &reference_config_.ftp_proxy; |
| 217 else if (scheme == "socks") |
| 218 proxy = &reference_config_.socks_proxy; |
| 219 else |
| 220 NOTREACHED() << "Unrecognized scheme for setting proxy config"; |
| 221 if (proxy) { |
| 222 reference_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME; |
| 223 proxy->server = server; |
| 224 OnUISetProxyConfig(); |
| 225 } |
| 226 } |
| 227 |
| 228 void ProxyConfigServiceImpl::UISetProxyConfigBypassRules( |
| 229 const net::ProxyBypassRules& bypass_rules) { |
| 230 // Should be called from UI thread. |
| 231 CheckCurrentlyOnUIThread(); |
| 232 DCHECK(reference_config_.mode == ProxyConfig::MODE_SINGLE_PROXY || |
| 233 reference_config_.mode == ProxyConfig::MODE_PROXY_PER_SCHEME); |
| 234 if (reference_config_.mode == ProxyConfig::MODE_SINGLE_PROXY || |
| 235 reference_config_.mode == ProxyConfig::MODE_PROXY_PER_SCHEME) { |
| 236 reference_config_.bypass_rules = bypass_rules; |
| 237 OnUISetProxyConfig(); |
| 238 } |
| 239 } |
| 240 |
| 241 void ProxyConfigServiceImpl::AddObserver( |
| 242 net::ProxyConfigService::Observer* observer) { |
| 243 // Should be called from IO thread. |
| 244 CheckCurrentlyOnIOThread(); |
| 245 observers_.AddObserver(observer); |
| 246 } |
| 247 |
| 248 void ProxyConfigServiceImpl::RemoveObserver( |
| 249 net::ProxyConfigService::Observer* observer) { |
| 250 // Should be called from IO thread. |
| 251 CheckCurrentlyOnIOThread(); |
| 252 observers_.RemoveObserver(observer); |
| 253 } |
| 254 |
| 255 bool ProxyConfigServiceImpl::IOGetProxyConfig(net::ProxyConfig* net_config) { |
| 256 // Should be called from IO thread. |
| 257 CheckCurrentlyOnIOThread(); |
| 258 |
| 259 // Simply return the last cached proxy configuration. |
| 260 cached_config_.ConvertToNetProxyConfig(net_config); |
| 261 |
| 262 // We return true to indicate that *config was filled in. It is always |
| 263 // going to be available since we initialized eagerly on the UI thread. |
| 264 // TODO(kuan): do lazy initialization instead, so we no longer need |
| 265 // to construct ProxyConfigServiceImpl on the UI thread. |
| 266 // In which case, we may return false here. |
| 267 return true; |
| 268 } |
| 269 |
| 270 //------------------ ProxyConfigServiceImpl: private methods ------------------- |
| 271 |
| 272 void ProxyConfigServiceImpl::OnUISetProxyConfig() { |
| 273 // Posts a task to IO thread with the new config, so it can update |
| 274 // |cached_config_|. |
| 275 Task* task = NewRunnableMethod(this, |
| 276 &ProxyConfigServiceImpl::IOSetProxyConfig, reference_config_); |
| 277 if (!ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, task)) { |
| 278 LOG(INFO) << "Couldn't post task to IO thread to set new proxy config"; |
| 279 delete task; |
| 280 } |
| 281 |
| 282 // TODO(kuan): write new config out to cros settings for persistence. |
| 283 } |
| 284 |
| 285 void ProxyConfigServiceImpl::CheckCurrentlyOnIOThread() { |
| 286 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| 287 } |
| 288 |
| 289 void ProxyConfigServiceImpl::CheckCurrentlyOnUIThread() { |
| 290 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 291 } |
| 292 |
| 293 void ProxyConfigServiceImpl::IOSetProxyConfig(const ProxyConfig& new_config) { |
| 294 // This is called on the IO thread (posted from UI thread). |
| 295 CheckCurrentlyOnIOThread(); |
| 296 LOG(INFO) << "Proxy configuration changed"; |
| 297 cached_config_ = new_config; |
| 298 // Notify observers of new proxy config. |
| 299 net::ProxyConfig net_config; |
| 300 cached_config_.ConvertToNetProxyConfig(&net_config); |
| 301 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, |
| 302 OnProxyConfigChanged(net_config)); |
| 303 } |
| 304 |
| 305 } // namespace chromeos |
OLD | NEW |