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 base::Value::CreateIntegerValue(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 StartsWithASCII(path
, kProxyPrefsPrefix
, true);
118 void SetProxyPrefValue(const std::string
& path
,
119 const base::Value
* in_value
,
120 UIProxyConfigService
* config_service
) {
126 // Retrieve proxy config.
127 UIProxyConfig config
;
128 config_service
->GetProxyConfig(&config
);
130 if (path
== kProxyPacUrl
) {
132 if (in_value
->GetAsString(&val
)) {
135 config
.SetPacUrl(url
);
137 config
.mode
= UIProxyConfig::MODE_AUTO_DETECT
;
139 } else if (path
== kProxySingleHttp
) {
141 if (in_value
->GetAsString(&val
)) {
142 config
.SetSingleProxy(CreateProxyServerFromHost(
143 val
, config
.single_proxy
, net::ProxyServer::SCHEME_HTTP
));
145 } else if (path
== kProxySingleHttpPort
) {
147 if (in_value
->GetAsInteger(&val
)) {
148 config
.SetSingleProxy(CreateProxyServerFromPort(
149 val
, config
.single_proxy
, net::ProxyServer::SCHEME_HTTP
));
151 } else if (path
== kProxyHttpUrl
) {
153 if (in_value
->GetAsString(&val
)) {
154 config
.SetProxyForScheme(
155 "http", CreateProxyServerFromHost(
156 val
, config
.http_proxy
, net::ProxyServer::SCHEME_HTTP
));
158 } else if (path
== kProxyHttpPort
) {
160 if (in_value
->GetAsInteger(&val
)) {
161 config
.SetProxyForScheme(
162 "http", CreateProxyServerFromPort(
163 val
, config
.http_proxy
, net::ProxyServer::SCHEME_HTTP
));
165 } else if (path
== kProxyHttpsUrl
) {
167 if (in_value
->GetAsString(&val
)) {
168 config
.SetProxyForScheme(
169 "https", CreateProxyServerFromHost(
170 val
, config
.https_proxy
, net::ProxyServer::SCHEME_HTTP
));
172 } else if (path
== kProxyHttpsPort
) {
174 if (in_value
->GetAsInteger(&val
)) {
175 config
.SetProxyForScheme(
176 "https", CreateProxyServerFromPort(
177 val
, config
.https_proxy
, net::ProxyServer::SCHEME_HTTP
));
179 } else if (path
== kProxyType
) {
181 if (in_value
->GetAsInteger(&val
)) {
183 if (config
.automatic_proxy
.pac_url
.is_valid())
184 config
.SetPacUrl(config
.automatic_proxy
.pac_url
);
186 config
.mode
= UIProxyConfig::MODE_AUTO_DETECT
;
187 } else if (val
== 2) {
188 if (config
.single_proxy
.server
.is_valid()) {
189 config
.SetSingleProxy(config
.single_proxy
.server
);
191 bool set_config
= false;
192 if (config
.http_proxy
.server
.is_valid()) {
193 config
.SetProxyForScheme("http", config
.http_proxy
.server
);
196 if (config
.https_proxy
.server
.is_valid()) {
197 config
.SetProxyForScheme("https", config
.https_proxy
.server
);
200 if (config
.ftp_proxy
.server
.is_valid()) {
201 config
.SetProxyForScheme("ftp", config
.ftp_proxy
.server
);
204 if (config
.socks_proxy
.server
.is_valid()) {
205 config
.SetProxyForScheme("socks", config
.socks_proxy
.server
);
209 config
.SetProxyForScheme("http", net::ProxyServer());
212 config
.mode
= UIProxyConfig::MODE_DIRECT
;
215 } else if (path
== kProxySingle
) {
217 if (in_value
->GetAsBoolean(&val
)) {
219 config
.SetSingleProxy(config
.single_proxy
.server
);
221 config
.SetProxyForScheme("http", config
.http_proxy
.server
);
223 } else if (path
== kProxyUsePacUrl
) {
225 if (in_value
->GetAsBoolean(&use_pac_url
)) {
226 if (use_pac_url
&& config
.automatic_proxy
.pac_url
.is_valid())
227 config
.SetPacUrl(config
.automatic_proxy
.pac_url
);
229 config
.mode
= UIProxyConfig::MODE_AUTO_DETECT
;
231 } else if (path
== kProxyFtpUrl
) {
233 if (in_value
->GetAsString(&val
)) {
234 config
.SetProxyForScheme(
235 "ftp", CreateProxyServerFromHost(
236 val
, config
.ftp_proxy
, net::ProxyServer::SCHEME_HTTP
));
238 } else if (path
== kProxyFtpPort
) {
240 if (in_value
->GetAsInteger(&val
)) {
241 config
.SetProxyForScheme(
242 "ftp", CreateProxyServerFromPort(
243 val
, config
.ftp_proxy
, net::ProxyServer::SCHEME_HTTP
));
245 } else if (path
== kProxySocks
) {
247 if (in_value
->GetAsString(&val
)) {
248 config
.SetProxyForScheme(
249 "socks", CreateProxyServerFromHost(
252 StartsWithASCII(val
, "socks5://", false) ?
253 net::ProxyServer::SCHEME_SOCKS5
:
254 net::ProxyServer::SCHEME_SOCKS4
));
256 } else if (path
== kProxySocksPort
) {
258 if (in_value
->GetAsInteger(&val
)) {
259 std::string host
= config
.socks_proxy
.server
.host_port_pair().host();
260 config
.SetProxyForScheme(
261 "socks", CreateProxyServerFromPort(
264 StartsWithASCII(host
, "socks5://", false) ?
265 net::ProxyServer::SCHEME_SOCKS5
:
266 net::ProxyServer::SCHEME_SOCKS4
));
268 } else if (path
== kProxyIgnoreList
) {
269 net::ProxyBypassRules bypass_rules
;
270 if (in_value
->GetType() == base::Value::TYPE_LIST
) {
271 const ListValue
* list_value
= static_cast<const ListValue
*>(in_value
);
272 for (size_t x
= 0; x
< list_value
->GetSize(); x
++) {
274 if (list_value
->GetString(x
, &val
))
275 bypass_rules
.AddRuleFromString(val
);
277 config
.SetBypassRules(bypass_rules
);
280 LOG(WARNING
) << "Unknown proxy settings path " << path
;
284 config_service
->SetProxyConfig(config
);
287 bool GetProxyPrefValue(const UIProxyConfigService
& config_service
,
288 const std::string
& path
,
289 base::Value
** out_value
) {
290 std::string controlled_by
;
291 base::Value
* data
= NULL
;
292 UIProxyConfig config
;
293 config_service
.GetProxyConfig(&config
);
295 if (path
== kProxyPacUrl
) {
296 // Only show pacurl for pac-script mode.
297 if (config
.mode
== UIProxyConfig::MODE_PAC_SCRIPT
&&
298 config
.automatic_proxy
.pac_url
.is_valid()) {
299 data
= new base::StringValue(config
.automatic_proxy
.pac_url
.spec());
301 } else if (path
== kProxySingleHttp
) {
302 data
= CreateServerHostValue(config
.single_proxy
);
303 } else if (path
== kProxySingleHttpPort
) {
304 data
= CreateServerPortValue(config
.single_proxy
);
305 } else if (path
== kProxyHttpUrl
) {
306 data
= CreateServerHostValue(config
.http_proxy
);
307 } else if (path
== kProxyHttpsUrl
) {
308 data
= CreateServerHostValue(config
.https_proxy
);
309 } else if (path
== kProxyType
) {
310 if (config
.mode
== UIProxyConfig::MODE_AUTO_DETECT
||
311 config
.mode
== UIProxyConfig::MODE_PAC_SCRIPT
) {
312 data
= base::Value::CreateIntegerValue(3);
313 } else if (config
.mode
== UIProxyConfig::MODE_SINGLE_PROXY
||
314 config
.mode
== UIProxyConfig::MODE_PROXY_PER_SCHEME
) {
315 data
= base::Value::CreateIntegerValue(2);
317 data
= base::Value::CreateIntegerValue(1);
319 switch (config
.state
) {
320 case ProxyPrefs::CONFIG_POLICY
:
321 controlled_by
= "policy";
323 case ProxyPrefs::CONFIG_EXTENSION
:
324 controlled_by
= "extension";
326 case ProxyPrefs::CONFIG_OTHER_PRECEDE
:
327 controlled_by
= "other";
330 if (!config
.user_modifiable
)
331 controlled_by
= "shared";
334 } else if (path
== kProxySingle
) {
335 data
= base::Value::CreateBooleanValue(
336 config
.mode
== UIProxyConfig::MODE_SINGLE_PROXY
);
337 } else if (path
== kProxyUsePacUrl
) {
338 data
= base::Value::CreateBooleanValue(
339 config
.mode
== UIProxyConfig::MODE_PAC_SCRIPT
);
340 } else if (path
== kProxyFtpUrl
) {
341 data
= CreateServerHostValue(config
.ftp_proxy
);
342 } else if (path
== kProxySocks
) {
343 data
= CreateServerHostValue(config
.socks_proxy
);
344 } else if (path
== kProxyHttpPort
) {
345 data
= CreateServerPortValue(config
.http_proxy
);
346 } else if (path
== kProxyHttpsPort
) {
347 data
= CreateServerPortValue(config
.https_proxy
);
348 } else if (path
== kProxyFtpPort
) {
349 data
= CreateServerPortValue(config
.ftp_proxy
);
350 } else if (path
== kProxySocksPort
) {
351 data
= CreateServerPortValue(config
.socks_proxy
);
352 } else if (path
== kProxyIgnoreList
) {
353 ListValue
* list
= new ListValue();
354 net::ProxyBypassRules::RuleList bypass_rules
= config
.bypass_rules
.rules();
355 for (size_t x
= 0; x
< bypass_rules
.size(); x
++)
356 list
->Append(new base::StringValue(bypass_rules
[x
]->ToString()));
363 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
364 DictionaryValue
* dict
= new DictionaryValue
;
366 data
= new base::StringValue("");
367 dict
->Set("value", data
);
368 if (path
== kProxyType
) {
369 if (!controlled_by
.empty())
370 dict
->SetString("controlledBy", controlled_by
);
371 dict
->SetBoolean("disabled", !config
.user_modifiable
);
373 dict
->SetBoolean("disabled", false);
379 } // namespace proxy_cros_settings_parser
381 } // namespace chromeos