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 "chrome/browser/chromeos/proxy_cros_settings_parser.h" 6 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" 11 12 namespace chromeos { 13 14 // Common prefix of all proxy prefs. 15 const char kProxyPrefsPrefix[] = "cros.session.proxy"; 16 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"; 33 34 const char* const kProxySettings[] = { 35 kProxyPacUrl, 36 kProxySingleHttp, 37 kProxySingleHttpPort, 38 kProxyHttpUrl, 39 kProxyHttpPort, 40 kProxyHttpsUrl, 41 kProxyHttpsPort, 42 kProxyType, 43 kProxySingle, 44 kProxyFtpUrl, 45 kProxyFtpPort, 46 kProxySocks, 47 kProxySocksPort, 48 kProxyIgnoreList, 49 kProxyUsePacUrl, 50 }; 51 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); 55 56 namespace { 57 58 base::Value* CreateServerHostValue(const UIProxyConfig::ManualProxy& proxy) { 59 return proxy.server.is_valid() ? 60 new base::StringValue(proxy.server.host_port_pair().host()) : 61 NULL; 62 } 63 64 base::Value* CreateServerPortValue(const UIProxyConfig::ManualProxy& proxy) { 65 return proxy.server.is_valid() ? 66 base::Value::CreateIntegerValue(proxy.server.host_port_pair().port()) : 67 NULL; 68 } 69 70 net::ProxyServer CreateProxyServer(std::string host, 71 uint16 port, 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>. 78 GURL url(host); 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); 88 } 89 90 net::ProxyServer CreateProxyServerFromHost( 91 const std::string& host, 92 const UIProxyConfig::ManualProxy& proxy, 93 net::ProxyServer::Scheme scheme) { 94 uint16 port = 0; 95 if (proxy.server.is_valid()) 96 port = proxy.server.host_port_pair().port(); 97 return CreateProxyServer(host, port, scheme); 98 } 99 100 net::ProxyServer CreateProxyServerFromPort( 101 uint16 port, 102 const UIProxyConfig::ManualProxy& proxy, 103 net::ProxyServer::Scheme scheme) { 104 std::string host; 105 if (proxy.server.is_valid()) 106 host = proxy.server.host_port_pair().host(); 107 return CreateProxyServer(host, port, scheme); 108 } 109 110 } // namespace 111 112 namespace proxy_cros_settings_parser { 113 114 bool IsProxyPref(const std::string& path) { 115 return StartsWithASCII(path, kProxyPrefsPrefix, true); 116 } 117 118 void SetProxyPrefValue(const std::string& path, 119 const base::Value* in_value, 120 UIProxyConfigService* config_service) { 121 if (!in_value) { 122 NOTREACHED(); 123 return; 124 } 125 126 // Retrieve proxy config. 127 UIProxyConfig config; 128 config_service->GetProxyConfig(&config); 129 130 if (path == kProxyPacUrl) { 131 std::string val; 132 if (in_value->GetAsString(&val)) { 133 GURL url(val); 134 if (url.is_valid()) 135 config.SetPacUrl(url); 136 else 137 config.mode = UIProxyConfig::MODE_AUTO_DETECT; 138 } 139 } else if (path == kProxySingleHttp) { 140 std::string val; 141 if (in_value->GetAsString(&val)) { 142 config.SetSingleProxy(CreateProxyServerFromHost( 143 val, config.single_proxy, net::ProxyServer::SCHEME_HTTP)); 144 } 145 } else if (path == kProxySingleHttpPort) { 146 int val; 147 if (in_value->GetAsInteger(&val)) { 148 config.SetSingleProxy(CreateProxyServerFromPort( 149 val, config.single_proxy, net::ProxyServer::SCHEME_HTTP)); 150 } 151 } else if (path == kProxyHttpUrl) { 152 std::string val; 153 if (in_value->GetAsString(&val)) { 154 config.SetProxyForScheme( 155 "http", CreateProxyServerFromHost( 156 val, config.http_proxy, net::ProxyServer::SCHEME_HTTP)); 157 } 158 } else if (path == kProxyHttpPort) { 159 int val; 160 if (in_value->GetAsInteger(&val)) { 161 config.SetProxyForScheme( 162 "http", CreateProxyServerFromPort( 163 val, config.http_proxy, net::ProxyServer::SCHEME_HTTP)); 164 } 165 } else if (path == kProxyHttpsUrl) { 166 std::string val; 167 if (in_value->GetAsString(&val)) { 168 config.SetProxyForScheme( 169 "https", CreateProxyServerFromHost( 170 val, config.https_proxy, net::ProxyServer::SCHEME_HTTP)); 171 } 172 } else if (path == kProxyHttpsPort) { 173 int val; 174 if (in_value->GetAsInteger(&val)) { 175 config.SetProxyForScheme( 176 "https", CreateProxyServerFromPort( 177 val, config.https_proxy, net::ProxyServer::SCHEME_HTTP)); 178 } 179 } else if (path == kProxyType) { 180 int val; 181 if (in_value->GetAsInteger(&val)) { 182 if (val == 3) { 183 if (config.automatic_proxy.pac_url.is_valid()) 184 config.SetPacUrl(config.automatic_proxy.pac_url); 185 else 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); 190 } else { 191 bool set_config = false; 192 if (config.http_proxy.server.is_valid()) { 193 config.SetProxyForScheme("http", config.http_proxy.server); 194 set_config = true; 195 } 196 if (config.https_proxy.server.is_valid()) { 197 config.SetProxyForScheme("https", config.https_proxy.server); 198 set_config = true; 199 } 200 if (config.ftp_proxy.server.is_valid()) { 201 config.SetProxyForScheme("ftp", config.ftp_proxy.server); 202 set_config = true; 203 } 204 if (config.socks_proxy.server.is_valid()) { 205 config.SetProxyForScheme("socks", config.socks_proxy.server); 206 set_config = true; 207 } 208 if (!set_config) 209 config.SetProxyForScheme("http", net::ProxyServer()); 210 } 211 } else { 212 config.mode = UIProxyConfig::MODE_DIRECT; 213 } 214 } 215 } else if (path == kProxySingle) { 216 bool val; 217 if (in_value->GetAsBoolean(&val)) { 218 if (val) 219 config.SetSingleProxy(config.single_proxy.server); 220 else 221 config.SetProxyForScheme("http", config.http_proxy.server); 222 } 223 } else if (path == kProxyUsePacUrl) { 224 bool use_pac_url; 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); 228 else 229 config.mode = UIProxyConfig::MODE_AUTO_DETECT; 230 } 231 } else if (path == kProxyFtpUrl) { 232 std::string val; 233 if (in_value->GetAsString(&val)) { 234 config.SetProxyForScheme( 235 "ftp", CreateProxyServerFromHost( 236 val, config.ftp_proxy, net::ProxyServer::SCHEME_HTTP)); 237 } 238 } else if (path == kProxyFtpPort) { 239 int val; 240 if (in_value->GetAsInteger(&val)) { 241 config.SetProxyForScheme( 242 "ftp", CreateProxyServerFromPort( 243 val, config.ftp_proxy, net::ProxyServer::SCHEME_HTTP)); 244 } 245 } else if (path == kProxySocks) { 246 std::string val; 247 if (in_value->GetAsString(&val)) { 248 config.SetProxyForScheme( 249 "socks", CreateProxyServerFromHost( 250 val, 251 config.socks_proxy, 252 StartsWithASCII(val, "socks5://", false) ? 253 net::ProxyServer::SCHEME_SOCKS5 : 254 net::ProxyServer::SCHEME_SOCKS4)); 255 } 256 } else if (path == kProxySocksPort) { 257 int val; 258 if (in_value->GetAsInteger(&val)) { 259 std::string host = config.socks_proxy.server.host_port_pair().host(); 260 config.SetProxyForScheme( 261 "socks", CreateProxyServerFromPort( 262 val, 263 config.socks_proxy, 264 StartsWithASCII(host, "socks5://", false) ? 265 net::ProxyServer::SCHEME_SOCKS5 : 266 net::ProxyServer::SCHEME_SOCKS4)); 267 } 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++) { 273 std::string val; 274 if (list_value->GetString(x, &val)) 275 bypass_rules.AddRuleFromString(val); 276 } 277 config.SetBypassRules(bypass_rules); 278 } 279 } else { 280 LOG(WARNING) << "Unknown proxy settings path " << path; 281 return; 282 } 283 284 config_service->SetProxyConfig(config); 285 } 286 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); 294 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()); 300 } 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); 316 } else { 317 data = base::Value::CreateIntegerValue(1); 318 } 319 switch (config.state) { 320 case ProxyPrefs::CONFIG_POLICY: 321 controlled_by = "policy"; 322 break; 323 case ProxyPrefs::CONFIG_EXTENSION: 324 controlled_by = "extension"; 325 break; 326 case ProxyPrefs::CONFIG_OTHER_PRECEDE: 327 controlled_by = "other"; 328 break; 329 default: 330 if (!config.user_modifiable) 331 controlled_by = "shared"; 332 break; 333 } 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())); 357 data = list; 358 } else { 359 *out_value = NULL; 360 return false; 361 } 362 363 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. 364 DictionaryValue* dict = new DictionaryValue; 365 if (!data) 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); 372 } else { 373 dict->SetBoolean("disabled", false); 374 } 375 *out_value = dict; 376 return true; 377 } 378 379 } // namespace proxy_cros_settings_parser 380 381 } // namespace chromeos 382