By moving the call to Load() up in SearchProvider::Start(), we are giving a chance...
[chromium-blink-merge.git] / net / proxy / proxy_config.cc
blob12acc5a8ea688eac3fffd0db2247b243ec9d373a
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.
5 #include "net/proxy/proxy_config.h"
7 #include "base/logging.h"
8 #include "base/string_tokenizer.h"
9 #include "base/string_util.h"
10 #include "base/values.h"
11 #include "net/proxy/proxy_info.h"
13 namespace net {
15 namespace {
17 // If |proxy| is valid, sets it in |dict| under the key |name|.
18 void AddProxyToValue(const char* name,
19 const ProxyServer& proxy,
20 DictionaryValue* dict) {
21 if (proxy.is_valid())
22 dict->SetString(name, proxy.ToURI());
25 } // namespace
27 ProxyConfig::ProxyRules::ProxyRules()
28 : reverse_bypass(false),
29 type(TYPE_NO_RULES) {
32 ProxyConfig::ProxyRules::~ProxyRules() {
35 void ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) const {
36 if (empty()) {
37 result->UseDirect();
38 return;
41 bool bypass_proxy = bypass_rules.Matches(url);
42 if (reverse_bypass)
43 bypass_proxy = !bypass_proxy;
44 if (bypass_proxy) {
45 result->UseDirectWithBypassedProxy();
46 return;
49 switch (type) {
50 case ProxyRules::TYPE_SINGLE_PROXY: {
51 result->UseProxyServer(single_proxy);
52 return;
54 case ProxyRules::TYPE_PROXY_PER_SCHEME: {
55 const ProxyServer* entry = MapUrlSchemeToProxy(url.scheme());
56 if (entry) {
57 result->UseProxyServer(*entry);
58 } else {
59 // We failed to find a matching proxy server for the current URL
60 // scheme. Default to direct.
61 result->UseDirect();
63 return;
65 default: {
66 result->UseDirect();
67 NOTREACHED();
68 return;
73 void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
74 // Reset.
75 type = TYPE_NO_RULES;
76 single_proxy = ProxyServer();
77 proxy_for_http = ProxyServer();
78 proxy_for_https = ProxyServer();
79 proxy_for_ftp = ProxyServer();
80 fallback_proxy = ProxyServer();
82 StringTokenizer proxy_server_list(proxy_rules, ";");
83 while (proxy_server_list.GetNext()) {
84 StringTokenizer proxy_server_for_scheme(
85 proxy_server_list.token_begin(), proxy_server_list.token_end(), "=");
87 while (proxy_server_for_scheme.GetNext()) {
88 std::string url_scheme = proxy_server_for_scheme.token();
90 // If we fail to get the proxy server here, it means that
91 // this is a regular proxy server configuration, i.e. proxies
92 // are not configured per protocol.
93 if (!proxy_server_for_scheme.GetNext()) {
94 if (type == TYPE_PROXY_PER_SCHEME)
95 continue; // Unexpected.
96 single_proxy = ProxyServer::FromURI(url_scheme,
97 ProxyServer::SCHEME_HTTP);
98 type = TYPE_SINGLE_PROXY;
99 return;
102 // Trim whitespace off the url scheme.
103 TrimWhitespaceASCII(url_scheme, TRIM_ALL, &url_scheme);
105 // Add it to the per-scheme mappings (if supported scheme).
106 type = TYPE_PROXY_PER_SCHEME;
107 ProxyServer* entry = MapUrlSchemeToProxyNoFallback(url_scheme);
108 ProxyServer::Scheme default_scheme = ProxyServer::SCHEME_HTTP;
110 // socks=XXX is inconsistent with the other formats, since "socks"
111 // is not a URL scheme. Rather this means "for everything else, send
112 // it to the SOCKS proxy server XXX".
113 if (url_scheme == "socks") {
114 DCHECK(!entry);
115 entry = &fallback_proxy;
116 default_scheme = ProxyServer::SCHEME_SOCKS4;
119 if (entry) {
120 *entry = ProxyServer::FromURI(proxy_server_for_scheme.token(),
121 default_scheme);
127 const ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxy(
128 const std::string& url_scheme) const {
129 const ProxyServer* proxy_server =
130 const_cast<ProxyRules*>(this)->MapUrlSchemeToProxyNoFallback(url_scheme);
131 if (proxy_server && proxy_server->is_valid())
132 return proxy_server;
133 if (fallback_proxy.is_valid())
134 return &fallback_proxy;
135 return NULL; // No mapping for this scheme. Use direct.
138 bool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const {
139 return type == other.type &&
140 single_proxy == other.single_proxy &&
141 proxy_for_http == other.proxy_for_http &&
142 proxy_for_https == other.proxy_for_https &&
143 proxy_for_ftp == other.proxy_for_ftp &&
144 fallback_proxy == other.fallback_proxy &&
145 bypass_rules.Equals(other.bypass_rules) &&
146 reverse_bypass == other.reverse_bypass;
149 ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
150 const std::string& scheme) {
151 DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type);
152 if (scheme == "http")
153 return &proxy_for_http;
154 if (scheme == "https")
155 return &proxy_for_https;
156 if (scheme == "ftp")
157 return &proxy_for_ftp;
158 return NULL; // No mapping for this scheme.
161 ProxyConfig::ProxyConfig()
162 : auto_detect_(false), pac_mandatory_(false),
163 source_(PROXY_CONFIG_SOURCE_UNKNOWN), id_(kInvalidConfigID) {
166 ProxyConfig::ProxyConfig(const ProxyConfig& config)
167 : auto_detect_(config.auto_detect_),
168 pac_url_(config.pac_url_),
169 pac_mandatory_(config.pac_mandatory_),
170 proxy_rules_(config.proxy_rules_),
171 source_(config.source_),
172 id_(config.id_) {
175 ProxyConfig::~ProxyConfig() {
178 ProxyConfig& ProxyConfig::operator=(const ProxyConfig& config) {
179 auto_detect_ = config.auto_detect_;
180 pac_url_ = config.pac_url_;
181 pac_mandatory_ = config.pac_mandatory_;
182 proxy_rules_ = config.proxy_rules_;
183 source_ = config.source_;
184 id_ = config.id_;
185 return *this;
188 bool ProxyConfig::Equals(const ProxyConfig& other) const {
189 // The two configs can have different IDs and sources. We are just interested
190 // in if they have the same settings.
191 return auto_detect_ == other.auto_detect_ &&
192 pac_url_ == other.pac_url_ &&
193 pac_mandatory_ == other.pac_mandatory_ &&
194 proxy_rules_.Equals(other.proxy_rules());
197 bool ProxyConfig::HasAutomaticSettings() const {
198 return auto_detect_ || has_pac_url();
201 void ProxyConfig::ClearAutomaticSettings() {
202 auto_detect_ = false;
203 pac_url_ = GURL();
206 Value* ProxyConfig::ToValue() const {
207 DictionaryValue* dict = new DictionaryValue();
209 // Output the automatic settings.
210 if (auto_detect_)
211 dict->SetBoolean("auto_detect", auto_detect_);
212 if (has_pac_url()) {
213 dict->SetString("pac_url", pac_url_.possibly_invalid_spec());
214 if (pac_mandatory_)
215 dict->SetBoolean("pac_mandatory", pac_mandatory_);
218 // Output the manual settings.
219 if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) {
220 switch (proxy_rules_.type) {
221 case ProxyRules::TYPE_SINGLE_PROXY:
222 AddProxyToValue("single_proxy", proxy_rules_.single_proxy, dict);
223 break;
224 case ProxyRules::TYPE_PROXY_PER_SCHEME: {
225 DictionaryValue* dict2 = new DictionaryValue();
226 AddProxyToValue("http", proxy_rules_.proxy_for_http, dict2);
227 AddProxyToValue("https", proxy_rules_.proxy_for_https, dict2);
228 AddProxyToValue("ftp", proxy_rules_.proxy_for_ftp, dict2);
229 AddProxyToValue("fallback", proxy_rules_.fallback_proxy, dict2);
230 dict->Set("proxy_per_scheme", dict2);
231 break;
233 default:
234 NOTREACHED();
237 // Output the bypass rules.
238 const ProxyBypassRules& bypass = proxy_rules_.bypass_rules;
239 if (!bypass.rules().empty()) {
240 if (proxy_rules_.reverse_bypass)
241 dict->SetBoolean("reverse_bypass", true);
243 ListValue* list = new ListValue();
245 for (ProxyBypassRules::RuleList::const_iterator it =
246 bypass.rules().begin();
247 it != bypass.rules().end(); ++it) {
248 list->Append(Value::CreateStringValue((*it)->ToString()));
251 dict->Set("bypass_list", list);
255 // Output the source.
256 dict->SetString("source", ProxyConfigSourceToString(source_));
258 return dict;
261 } // namespace net