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 "chrome/browser/chromeos/proxy_cros_settings_parser.h"
7 #include "base/strings/string_util.h"
8 #include "base/values.h"
9 #include "chrome/browser/chromeos/ui_proxy_config.h"
10 #include "chrome/browser/chromeos/ui_proxy_config_service.h"
14 // Common prefix of all proxy prefs.
15 const char kProxyPrefsPrefix
[] = "cros.session.proxy";
17 // Names of proxy preferences.
18 const char kProxyPacUrl
[] = "cros.session.proxy.pacurl";
19 const char kProxySingleHttp
[] = "cros.session.proxy.singlehttp";
20 const char kProxySingleHttpPort
[] = "cros.session.proxy.singlehttpport";
21 const char kProxyHttpUrl
[] = "cros.session.proxy.httpurl";
22 const char kProxyHttpPort
[] = "cros.session.proxy.httpport";
23 const char kProxyHttpsUrl
[] = "cros.session.proxy.httpsurl";
24 const char kProxyHttpsPort
[] = "cros.session.proxy.httpsport";
25 const char kProxyType
[] = "cros.session.proxy.type";
26 const char kProxySingle
[] = "cros.session.proxy.single";
27 const char kProxyFtpUrl
[] = "cros.session.proxy.ftpurl";
28 const char kProxyFtpPort
[] = "cros.session.proxy.ftpport";
29 const char kProxySocks
[] = "cros.session.proxy.socks";
30 const char kProxySocksPort
[] = "cros.session.proxy.socksport";
31 const char kProxyIgnoreList
[] = "cros.session.proxy.ignorelist";
32 const char kProxyUsePacUrl
[] = "cros.session.proxy.usepacurl";
34 const char* const kProxySettings
[] = {
52 // We have to explicitly export this because the arraysize macro doesn't like
53 // extern arrays as their size is not known on compile time.
54 const size_t kProxySettingsCount
= arraysize(kProxySettings
);
58 base::Value
* CreateServerHostValue(const UIProxyConfig::ManualProxy
& proxy
) {
59 return proxy
.server
.is_valid() ?
60 new base::StringValue(proxy
.server
.host_port_pair().host()) :
64 base::Value
* CreateServerPortValue(const UIProxyConfig::ManualProxy
& proxy
) {
65 return proxy
.server
.is_valid()
66 ? new base::FundamentalValue(proxy
.server
.host_port_pair().port())
70 net::ProxyServer
CreateProxyServer(std::string host
,
72 net::ProxyServer::Scheme scheme
) {
73 if (host
.empty() && port
== 0)
74 return net::ProxyServer();
75 uint16 default_port
= net::ProxyServer::GetDefaultPortForScheme(scheme
);
76 net::HostPortPair host_port_pair
;
77 // Check if host is a valid URL or a string of valid format <server>::<port>.
79 if (url
.is_valid()) // See if host is URL.
80 host_port_pair
= net::HostPortPair::FromURL(url
);
81 if (host_port_pair
.host().empty()) // See if host is <server>::<port>.
82 host_port_pair
= net::HostPortPair::FromString(host
);
83 if (host_port_pair
.host().empty()) // Host is not URL or <server>::<port>.
84 host_port_pair
= net::HostPortPair(host
, port
);
85 if (host_port_pair
.port() == 0) // No port in host, use default.
86 host_port_pair
.set_port(default_port
);
87 return net::ProxyServer(scheme
, host_port_pair
);
90 net::ProxyServer
CreateProxyServerFromHost(
91 const std::string
& host
,
92 const UIProxyConfig::ManualProxy
& proxy
,
93 net::ProxyServer::Scheme scheme
) {
95 if (proxy
.server
.is_valid())
96 port
= proxy
.server
.host_port_pair().port();
97 return CreateProxyServer(host
, port
, scheme
);
100 net::ProxyServer
CreateProxyServerFromPort(
102 const UIProxyConfig::ManualProxy
& proxy
,
103 net::ProxyServer::Scheme scheme
) {
105 if (proxy
.server
.is_valid())
106 host
= proxy
.server
.host_port_pair().host();
107 return CreateProxyServer(host
, port
, scheme
);
112 namespace proxy_cros_settings_parser
{
114 bool IsProxyPref(const std::string
& path
) {
115 return base::StartsWith(path
, kProxyPrefsPrefix
,
116 base::CompareCase::SENSITIVE
);
119 void SetProxyPrefValue(const std::string
& path
,
120 const base::Value
* in_value
,
121 UIProxyConfigService
* config_service
) {
127 // Retrieve proxy config.
128 UIProxyConfig config
;
129 config_service
->GetProxyConfig(&config
);
131 if (path
== kProxyPacUrl
) {
133 if (in_value
->GetAsString(&val
)) {
136 config
.SetPacUrl(url
);
138 config
.mode
= UIProxyConfig::MODE_AUTO_DETECT
;
140 } else if (path
== kProxySingleHttp
) {
142 if (in_value
->GetAsString(&val
)) {
143 config
.SetSingleProxy(CreateProxyServerFromHost(
144 val
, config
.single_proxy
, net::ProxyServer::SCHEME_HTTP
));
146 } else if (path
== kProxySingleHttpPort
) {
148 if (in_value
->GetAsInteger(&val
)) {
149 config
.SetSingleProxy(CreateProxyServerFromPort(
150 val
, config
.single_proxy
, net::ProxyServer::SCHEME_HTTP
));
152 } else if (path
== kProxyHttpUrl
) {
154 if (in_value
->GetAsString(&val
)) {
155 config
.SetProxyForScheme(
156 "http", CreateProxyServerFromHost(
157 val
, config
.http_proxy
, net::ProxyServer::SCHEME_HTTP
));
159 } else if (path
== kProxyHttpPort
) {
161 if (in_value
->GetAsInteger(&val
)) {
162 config
.SetProxyForScheme(
163 "http", CreateProxyServerFromPort(
164 val
, config
.http_proxy
, net::ProxyServer::SCHEME_HTTP
));
166 } else if (path
== kProxyHttpsUrl
) {
168 if (in_value
->GetAsString(&val
)) {
169 config
.SetProxyForScheme(
170 "https", CreateProxyServerFromHost(
171 val
, config
.https_proxy
, net::ProxyServer::SCHEME_HTTP
));
173 } else if (path
== kProxyHttpsPort
) {
175 if (in_value
->GetAsInteger(&val
)) {
176 config
.SetProxyForScheme(
177 "https", CreateProxyServerFromPort(
178 val
, config
.https_proxy
, net::ProxyServer::SCHEME_HTTP
));
180 } else if (path
== kProxyType
) {
182 if (in_value
->GetAsInteger(&val
)) {
184 if (config
.automatic_proxy
.pac_url
.is_valid())
185 config
.SetPacUrl(config
.automatic_proxy
.pac_url
);
187 config
.mode
= UIProxyConfig::MODE_AUTO_DETECT
;
188 } else if (val
== 2) {
189 if (config
.single_proxy
.server
.is_valid()) {
190 config
.SetSingleProxy(config
.single_proxy
.server
);
192 bool set_config
= false;
193 if (config
.http_proxy
.server
.is_valid()) {
194 config
.SetProxyForScheme("http", config
.http_proxy
.server
);
197 if (config
.https_proxy
.server
.is_valid()) {
198 config
.SetProxyForScheme("https", config
.https_proxy
.server
);
201 if (config
.ftp_proxy
.server
.is_valid()) {
202 config
.SetProxyForScheme("ftp", config
.ftp_proxy
.server
);
205 if (config
.socks_proxy
.server
.is_valid()) {
206 config
.SetProxyForScheme("socks", config
.socks_proxy
.server
);
210 config
.SetProxyForScheme("http", net::ProxyServer());
213 config
.mode
= UIProxyConfig::MODE_DIRECT
;
216 } else if (path
== kProxySingle
) {
218 if (in_value
->GetAsBoolean(&val
)) {
220 config
.SetSingleProxy(config
.single_proxy
.server
);
222 config
.SetProxyForScheme("http", config
.http_proxy
.server
);
224 } else if (path
== kProxyUsePacUrl
) {
226 if (in_value
->GetAsBoolean(&use_pac_url
)) {
227 if (use_pac_url
&& config
.automatic_proxy
.pac_url
.is_valid())
228 config
.SetPacUrl(config
.automatic_proxy
.pac_url
);
230 config
.mode
= UIProxyConfig::MODE_AUTO_DETECT
;
232 } else if (path
== kProxyFtpUrl
) {
234 if (in_value
->GetAsString(&val
)) {
235 config
.SetProxyForScheme(
236 "ftp", CreateProxyServerFromHost(
237 val
, config
.ftp_proxy
, net::ProxyServer::SCHEME_HTTP
));
239 } else if (path
== kProxyFtpPort
) {
241 if (in_value
->GetAsInteger(&val
)) {
242 config
.SetProxyForScheme(
243 "ftp", CreateProxyServerFromPort(
244 val
, config
.ftp_proxy
, net::ProxyServer::SCHEME_HTTP
));
246 } else if (path
== kProxySocks
) {
248 if (in_value
->GetAsString(&val
)) {
249 config
.SetProxyForScheme(
250 "socks", CreateProxyServerFromHost(
251 val
, config
.socks_proxy
,
252 base::StartsWith(val
, "socks5://",
253 base::CompareCase::INSENSITIVE_ASCII
)
254 ? net::ProxyServer::SCHEME_SOCKS5
255 : net::ProxyServer::SCHEME_SOCKS4
));
257 } else if (path
== kProxySocksPort
) {
259 if (in_value
->GetAsInteger(&val
)) {
260 std::string host
= config
.socks_proxy
.server
.host_port_pair().host();
261 config
.SetProxyForScheme(
262 "socks", CreateProxyServerFromPort(
263 val
, config
.socks_proxy
,
264 base::StartsWith(host
, "socks5://",
265 base::CompareCase::INSENSITIVE_ASCII
)
266 ? net::ProxyServer::SCHEME_SOCKS5
267 : net::ProxyServer::SCHEME_SOCKS4
));
269 } else if (path
== kProxyIgnoreList
) {
270 net::ProxyBypassRules bypass_rules
;
271 if (in_value
->GetType() == base::Value::TYPE_LIST
) {
272 const base::ListValue
* list_value
=
273 static_cast<const base::ListValue
*>(in_value
);
274 for (size_t x
= 0; x
< list_value
->GetSize(); x
++) {
276 if (list_value
->GetString(x
, &val
))
277 bypass_rules
.AddRuleFromString(val
);
279 config
.SetBypassRules(bypass_rules
);
282 LOG(WARNING
) << "Unknown proxy settings path " << path
;
286 config_service
->SetProxyConfig(config
);
289 bool GetProxyPrefValue(const UIProxyConfigService
& config_service
,
290 const std::string
& path
,
291 base::Value
** out_value
) {
292 std::string controlled_by
;
293 base::Value
* data
= NULL
;
294 UIProxyConfig config
;
295 config_service
.GetProxyConfig(&config
);
297 if (path
== kProxyPacUrl
) {
298 // Only show pacurl for pac-script mode.
299 if (config
.mode
== UIProxyConfig::MODE_PAC_SCRIPT
&&
300 config
.automatic_proxy
.pac_url
.is_valid()) {
301 data
= new base::StringValue(config
.automatic_proxy
.pac_url
.spec());
303 } else if (path
== kProxySingleHttp
) {
304 data
= CreateServerHostValue(config
.single_proxy
);
305 } else if (path
== kProxySingleHttpPort
) {
306 data
= CreateServerPortValue(config
.single_proxy
);
307 } else if (path
== kProxyHttpUrl
) {
308 data
= CreateServerHostValue(config
.http_proxy
);
309 } else if (path
== kProxyHttpsUrl
) {
310 data
= CreateServerHostValue(config
.https_proxy
);
311 } else if (path
== kProxyType
) {
312 if (config
.mode
== UIProxyConfig::MODE_AUTO_DETECT
||
313 config
.mode
== UIProxyConfig::MODE_PAC_SCRIPT
) {
314 data
= new base::FundamentalValue(3);
315 } else if (config
.mode
== UIProxyConfig::MODE_SINGLE_PROXY
||
316 config
.mode
== UIProxyConfig::MODE_PROXY_PER_SCHEME
) {
317 data
= new base::FundamentalValue(2);
319 data
= new base::FundamentalValue(1);
321 switch (config
.state
) {
322 case ProxyPrefs::CONFIG_POLICY
:
323 controlled_by
= "policy";
325 case ProxyPrefs::CONFIG_EXTENSION
:
326 controlled_by
= "extension";
328 case ProxyPrefs::CONFIG_OTHER_PRECEDE
:
329 controlled_by
= "other";
332 if (!config
.user_modifiable
)
333 controlled_by
= "shared";
336 } else if (path
== kProxySingle
) {
337 data
= new base::FundamentalValue(config
.mode
==
338 UIProxyConfig::MODE_SINGLE_PROXY
);
339 } else if (path
== kProxyUsePacUrl
) {
340 data
= new base::FundamentalValue(config
.mode
==
341 UIProxyConfig::MODE_PAC_SCRIPT
);
342 } else if (path
== kProxyFtpUrl
) {
343 data
= CreateServerHostValue(config
.ftp_proxy
);
344 } else if (path
== kProxySocks
) {
345 data
= CreateServerHostValue(config
.socks_proxy
);
346 } else if (path
== kProxyHttpPort
) {
347 data
= CreateServerPortValue(config
.http_proxy
);
348 } else if (path
== kProxyHttpsPort
) {
349 data
= CreateServerPortValue(config
.https_proxy
);
350 } else if (path
== kProxyFtpPort
) {
351 data
= CreateServerPortValue(config
.ftp_proxy
);
352 } else if (path
== kProxySocksPort
) {
353 data
= CreateServerPortValue(config
.socks_proxy
);
354 } else if (path
== kProxyIgnoreList
) {
355 base::ListValue
* list
= new base::ListValue();
356 net::ProxyBypassRules::RuleList bypass_rules
= config
.bypass_rules
.rules();
357 for (size_t x
= 0; x
< bypass_rules
.size(); x
++)
358 list
->Append(new base::StringValue(bypass_rules
[x
]->ToString()));
365 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
366 base::DictionaryValue
* dict
= new base::DictionaryValue
;
368 data
= new base::StringValue("");
369 dict
->Set("value", data
);
370 if (path
== kProxyType
) {
371 if (!controlled_by
.empty())
372 dict
->SetString("controlledBy", controlled_by
);
373 dict
->SetBoolean("disabled", !config
.user_modifiable
);
375 dict
->SetBoolean("disabled", false);
381 } // namespace proxy_cros_settings_parser
383 } // namespace chromeos