| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/proxy/proxy_config.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/strings/string_util.h" | |
| 9 #include "base/strings/string_tokenizer.h" | |
| 10 #include "base/values.h" | |
| 11 #include "net/proxy/proxy_info.h" | |
| 12 | |
| 13 namespace net { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // If |proxies| is non-empty, sets it in |dict| under the key |name|. | |
| 18 void AddProxyListToValue(const char* name, | |
| 19 const ProxyList& proxies, | |
| 20 base::DictionaryValue* dict) { | |
| 21 if (!proxies.IsEmpty()) | |
| 22 dict->Set(name, proxies.ToValue()); | |
| 23 } | |
| 24 | |
| 25 // Split the |uri_list| on commas and add each entry to |proxy_list| in turn. | |
| 26 void AddProxyURIListToProxyList(std::string uri_list, | |
| 27 ProxyList* proxy_list, | |
| 28 ProxyServer::Scheme default_scheme) { | |
| 29 base::StringTokenizer proxy_uri_list(uri_list, ","); | |
| 30 while (proxy_uri_list.GetNext()) { | |
| 31 proxy_list->AddProxyServer( | |
| 32 ProxyServer::FromURI(proxy_uri_list.token(), default_scheme)); | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 38 ProxyConfig::ProxyRules::ProxyRules() | |
| 39 : reverse_bypass(false), | |
| 40 type(TYPE_NO_RULES) { | |
| 41 } | |
| 42 | |
| 43 ProxyConfig::ProxyRules::~ProxyRules() { | |
| 44 } | |
| 45 | |
| 46 void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) const { | |
| 47 if (empty()) { | |
| 48 result->UseDirect(); | |
| 49 return; | |
| 50 } | |
| 51 | |
| 52 bool bypass_proxy = bypass_rules.Matches(url); | |
| 53 if (reverse_bypass) | |
| 54 bypass_proxy = !bypass_proxy; | |
| 55 if (bypass_proxy) { | |
| 56 result->UseDirectWithBypassedProxy(); | |
| 57 return; | |
| 58 } | |
| 59 | |
| 60 switch (type) { | |
| 61 case ProxyRules::TYPE_SINGLE_PROXY: { | |
| 62 result->UseProxyList(single_proxies); | |
| 63 return; | |
| 64 } | |
| 65 case ProxyRules::TYPE_PROXY_PER_SCHEME: { | |
| 66 const ProxyList* entry = MapUrlSchemeToProxyList(url.scheme()); | |
| 67 if (entry) { | |
| 68 result->UseProxyList(*entry); | |
| 69 } else { | |
| 70 // We failed to find a matching proxy server for the current URL | |
| 71 // scheme. Default to direct. | |
| 72 result->UseDirect(); | |
| 73 } | |
| 74 return; | |
| 75 } | |
| 76 default: { | |
| 77 result->UseDirect(); | |
| 78 NOTREACHED(); | |
| 79 return; | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) { | |
| 85 // Reset. | |
| 86 type = TYPE_NO_RULES; | |
| 87 single_proxies = ProxyList(); | |
| 88 proxies_for_http = ProxyList(); | |
| 89 proxies_for_https = ProxyList(); | |
| 90 proxies_for_ftp = ProxyList(); | |
| 91 fallback_proxies = ProxyList(); | |
| 92 | |
| 93 base::StringTokenizer proxy_server_list(proxy_rules, ";"); | |
| 94 while (proxy_server_list.GetNext()) { | |
| 95 base::StringTokenizer proxy_server_for_scheme( | |
| 96 proxy_server_list.token_begin(), proxy_server_list.token_end(), "="); | |
| 97 | |
| 98 while (proxy_server_for_scheme.GetNext()) { | |
| 99 std::string url_scheme = proxy_server_for_scheme.token(); | |
| 100 | |
| 101 // If we fail to get the proxy server here, it means that | |
| 102 // this is a regular proxy server configuration, i.e. proxies | |
| 103 // are not configured per protocol. | |
| 104 if (!proxy_server_for_scheme.GetNext()) { | |
| 105 if (type == TYPE_PROXY_PER_SCHEME) | |
| 106 continue; // Unexpected. | |
| 107 AddProxyURIListToProxyList(url_scheme, | |
| 108 &single_proxies, | |
| 109 ProxyServer::SCHEME_HTTP); | |
| 110 type = TYPE_SINGLE_PROXY; | |
| 111 return; | |
| 112 } | |
| 113 | |
| 114 // Trim whitespace off the url scheme. | |
| 115 base::TrimWhitespaceASCII(url_scheme, base::TRIM_ALL, &url_scheme); | |
| 116 | |
| 117 // Add it to the per-scheme mappings (if supported scheme). | |
| 118 type = TYPE_PROXY_PER_SCHEME; | |
| 119 ProxyList* entry = MapUrlSchemeToProxyListNoFallback(url_scheme); | |
| 120 ProxyServer::Scheme default_scheme = ProxyServer::SCHEME_HTTP; | |
| 121 | |
| 122 // socks=XXX is inconsistent with the other formats, since "socks" | |
| 123 // is not a URL scheme. Rather this means "for everything else, send | |
| 124 // it to the SOCKS proxy server XXX". | |
| 125 if (url_scheme == "socks") { | |
| 126 DCHECK(!entry); | |
| 127 entry = &fallback_proxies; | |
| 128 // Note that here 'socks' is understood to be SOCKS4, even though | |
| 129 // 'socks' maps to SOCKS5 in ProxyServer::GetSchemeFromURIInternal. | |
| 130 default_scheme = ProxyServer::SCHEME_SOCKS4; | |
| 131 } | |
| 132 | |
| 133 if (entry) { | |
| 134 AddProxyURIListToProxyList(proxy_server_for_scheme.token(), | |
| 135 entry, | |
| 136 default_scheme); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 const ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyList( | |
| 143 const std::string& url_scheme) const { | |
| 144 const ProxyList* proxy_server_list = const_cast<ProxyRules*>(this)-> | |
| 145 MapUrlSchemeToProxyListNoFallback(url_scheme); | |
| 146 if (proxy_server_list && !proxy_server_list->IsEmpty()) | |
| 147 return proxy_server_list; | |
| 148 if (url_scheme == "ws" || url_scheme == "wss") | |
| 149 return GetProxyListForWebSocketScheme(); | |
| 150 if (!fallback_proxies.IsEmpty()) | |
| 151 return &fallback_proxies; | |
| 152 return NULL; // No mapping for this scheme. Use direct. | |
| 153 } | |
| 154 | |
| 155 bool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const { | |
| 156 return type == other.type && | |
| 157 single_proxies.Equals(other.single_proxies) && | |
| 158 proxies_for_http.Equals(other.proxies_for_http) && | |
| 159 proxies_for_https.Equals(other.proxies_for_https) && | |
| 160 proxies_for_ftp.Equals(other.proxies_for_ftp) && | |
| 161 fallback_proxies.Equals(other.fallback_proxies) && | |
| 162 bypass_rules.Equals(other.bypass_rules) && | |
| 163 reverse_bypass == other.reverse_bypass; | |
| 164 } | |
| 165 | |
| 166 ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyListNoFallback( | |
| 167 const std::string& scheme) { | |
| 168 DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type); | |
| 169 if (scheme == "http") | |
| 170 return &proxies_for_http; | |
| 171 if (scheme == "https") | |
| 172 return &proxies_for_https; | |
| 173 if (scheme == "ftp") | |
| 174 return &proxies_for_ftp; | |
| 175 return NULL; // No mapping for this scheme. | |
| 176 } | |
| 177 | |
| 178 const ProxyList* ProxyConfig::ProxyRules::GetProxyListForWebSocketScheme() | |
| 179 const { | |
| 180 if (!fallback_proxies.IsEmpty()) | |
| 181 return &fallback_proxies; | |
| 182 if (!proxies_for_https.IsEmpty()) | |
| 183 return &proxies_for_https; | |
| 184 if (!proxies_for_http.IsEmpty()) | |
| 185 return &proxies_for_http; | |
| 186 return NULL; | |
| 187 } | |
| 188 | |
| 189 ProxyConfig::ProxyConfig() | |
| 190 : auto_detect_(false), pac_mandatory_(false), | |
| 191 source_(PROXY_CONFIG_SOURCE_UNKNOWN), id_(kInvalidConfigID) { | |
| 192 } | |
| 193 | |
| 194 ProxyConfig::ProxyConfig(const ProxyConfig& config) | |
| 195 : auto_detect_(config.auto_detect_), | |
| 196 pac_url_(config.pac_url_), | |
| 197 pac_mandatory_(config.pac_mandatory_), | |
| 198 proxy_rules_(config.proxy_rules_), | |
| 199 source_(config.source_), | |
| 200 id_(config.id_) { | |
| 201 } | |
| 202 | |
| 203 ProxyConfig::~ProxyConfig() { | |
| 204 } | |
| 205 | |
| 206 ProxyConfig& ProxyConfig::operator=(const ProxyConfig& config) { | |
| 207 auto_detect_ = config.auto_detect_; | |
| 208 pac_url_ = config.pac_url_; | |
| 209 pac_mandatory_ = config.pac_mandatory_; | |
| 210 proxy_rules_ = config.proxy_rules_; | |
| 211 source_ = config.source_; | |
| 212 id_ = config.id_; | |
| 213 return *this; | |
| 214 } | |
| 215 | |
| 216 bool ProxyConfig::Equals(const ProxyConfig& other) const { | |
| 217 // The two configs can have different IDs and sources. We are just interested | |
| 218 // in if they have the same settings. | |
| 219 return auto_detect_ == other.auto_detect_ && | |
| 220 pac_url_ == other.pac_url_ && | |
| 221 pac_mandatory_ == other.pac_mandatory_ && | |
| 222 proxy_rules_.Equals(other.proxy_rules()); | |
| 223 } | |
| 224 | |
| 225 bool ProxyConfig::HasAutomaticSettings() const { | |
| 226 return auto_detect_ || has_pac_url(); | |
| 227 } | |
| 228 | |
| 229 void ProxyConfig::ClearAutomaticSettings() { | |
| 230 auto_detect_ = false; | |
| 231 pac_url_ = GURL(); | |
| 232 } | |
| 233 | |
| 234 base::DictionaryValue* ProxyConfig::ToValue() const { | |
| 235 base::DictionaryValue* dict = new base::DictionaryValue(); | |
| 236 | |
| 237 // Output the automatic settings. | |
| 238 if (auto_detect_) | |
| 239 dict->SetBoolean("auto_detect", auto_detect_); | |
| 240 if (has_pac_url()) { | |
| 241 dict->SetString("pac_url", pac_url_.possibly_invalid_spec()); | |
| 242 if (pac_mandatory_) | |
| 243 dict->SetBoolean("pac_mandatory", pac_mandatory_); | |
| 244 } | |
| 245 | |
| 246 // Output the manual settings. | |
| 247 if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) { | |
| 248 switch (proxy_rules_.type) { | |
| 249 case ProxyRules::TYPE_SINGLE_PROXY: | |
| 250 AddProxyListToValue("single_proxy", | |
| 251 proxy_rules_.single_proxies, dict); | |
| 252 break; | |
| 253 case ProxyRules::TYPE_PROXY_PER_SCHEME: { | |
| 254 base::DictionaryValue* dict2 = new base::DictionaryValue(); | |
| 255 AddProxyListToValue("http", proxy_rules_.proxies_for_http, dict2); | |
| 256 AddProxyListToValue("https", proxy_rules_.proxies_for_https, dict2); | |
| 257 AddProxyListToValue("ftp", proxy_rules_.proxies_for_ftp, dict2); | |
| 258 AddProxyListToValue("fallback", proxy_rules_.fallback_proxies, dict2); | |
| 259 dict->Set("proxy_per_scheme", dict2); | |
| 260 break; | |
| 261 } | |
| 262 default: | |
| 263 NOTREACHED(); | |
| 264 } | |
| 265 | |
| 266 // Output the bypass rules. | |
| 267 const ProxyBypassRules& bypass = proxy_rules_.bypass_rules; | |
| 268 if (!bypass.rules().empty()) { | |
| 269 if (proxy_rules_.reverse_bypass) | |
| 270 dict->SetBoolean("reverse_bypass", true); | |
| 271 | |
| 272 base::ListValue* list = new base::ListValue(); | |
| 273 | |
| 274 for (ProxyBypassRules::RuleList::const_iterator it = | |
| 275 bypass.rules().begin(); | |
| 276 it != bypass.rules().end(); ++it) { | |
| 277 list->Append(new base::StringValue((*it)->ToString())); | |
| 278 } | |
| 279 | |
| 280 dict->Set("bypass_list", list); | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 // Output the source. | |
| 285 dict->SetString("source", ProxyConfigSourceToString(source_)); | |
| 286 | |
| 287 return dict; | |
| 288 } | |
| 289 | |
| 290 } // namespace net | |
| OLD | NEW |