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 base::ListValue* list_value = 272 static_cast<const base::ListValue*>(in_value); 273 for (size_t x = 0; x < list_value->GetSize(); x++) { 274 std::string val; 275 if (list_value->GetString(x, &val)) 276 bypass_rules.AddRuleFromString(val); 277 } 278 config.SetBypassRules(bypass_rules); 279 } 280 } else { 281 LOG(WARNING) << "Unknown proxy settings path " << path; 282 return; 283 } 284 285 config_service->SetProxyConfig(config); 286 } 287 288 bool GetProxyPrefValue(const UIProxyConfigService& config_service, 289 const std::string& path, 290 base::Value** out_value) { 291 std::string controlled_by; 292 base::Value* data = NULL; 293 UIProxyConfig config; 294 config_service.GetProxyConfig(&config); 295 296 if (path == kProxyPacUrl) { 297 // Only show pacurl for pac-script mode. 298 if (config.mode == UIProxyConfig::MODE_PAC_SCRIPT && 299 config.automatic_proxy.pac_url.is_valid()) { 300 data = new base::StringValue(config.automatic_proxy.pac_url.spec()); 301 } 302 } else if (path == kProxySingleHttp) { 303 data = CreateServerHostValue(config.single_proxy); 304 } else if (path == kProxySingleHttpPort) { 305 data = CreateServerPortValue(config.single_proxy); 306 } else if (path == kProxyHttpUrl) { 307 data = CreateServerHostValue(config.http_proxy); 308 } else if (path == kProxyHttpsUrl) { 309 data = CreateServerHostValue(config.https_proxy); 310 } else if (path == kProxyType) { 311 if (config.mode == UIProxyConfig::MODE_AUTO_DETECT || 312 config.mode == UIProxyConfig::MODE_PAC_SCRIPT) { 313 data = base::Value::CreateIntegerValue(3); 314 } else if (config.mode == UIProxyConfig::MODE_SINGLE_PROXY || 315 config.mode == UIProxyConfig::MODE_PROXY_PER_SCHEME) { 316 data = base::Value::CreateIntegerValue(2); 317 } else { 318 data = base::Value::CreateIntegerValue(1); 319 } 320 switch (config.state) { 321 case ProxyPrefs::CONFIG_POLICY: 322 controlled_by = "policy"; 323 break; 324 case ProxyPrefs::CONFIG_EXTENSION: 325 controlled_by = "extension"; 326 break; 327 case ProxyPrefs::CONFIG_OTHER_PRECEDE: 328 controlled_by = "other"; 329 break; 330 default: 331 if (!config.user_modifiable) 332 controlled_by = "shared"; 333 break; 334 } 335 } else if (path == kProxySingle) { 336 data = base::Value::CreateBooleanValue( 337 config.mode == UIProxyConfig::MODE_SINGLE_PROXY); 338 } else if (path == kProxyUsePacUrl) { 339 data = base::Value::CreateBooleanValue( 340 config.mode == UIProxyConfig::MODE_PAC_SCRIPT); 341 } else if (path == kProxyFtpUrl) { 342 data = CreateServerHostValue(config.ftp_proxy); 343 } else if (path == kProxySocks) { 344 data = CreateServerHostValue(config.socks_proxy); 345 } else if (path == kProxyHttpPort) { 346 data = CreateServerPortValue(config.http_proxy); 347 } else if (path == kProxyHttpsPort) { 348 data = CreateServerPortValue(config.https_proxy); 349 } else if (path == kProxyFtpPort) { 350 data = CreateServerPortValue(config.ftp_proxy); 351 } else if (path == kProxySocksPort) { 352 data = CreateServerPortValue(config.socks_proxy); 353 } else if (path == kProxyIgnoreList) { 354 base::ListValue* list = new base::ListValue(); 355 net::ProxyBypassRules::RuleList bypass_rules = config.bypass_rules.rules(); 356 for (size_t x = 0; x < bypass_rules.size(); x++) 357 list->Append(new base::StringValue(bypass_rules[x]->ToString())); 358 data = list; 359 } else { 360 *out_value = NULL; 361 return false; 362 } 363 364 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does. 365 base::DictionaryValue* dict = new base::DictionaryValue; 366 if (!data) 367 data = new base::StringValue(""); 368 dict->Set("value", data); 369 if (path == kProxyType) { 370 if (!controlled_by.empty()) 371 dict->SetString("controlledBy", controlled_by); 372 dict->SetBoolean("disabled", !config.user_modifiable); 373 } else { 374 dict->SetBoolean("disabled", false); 375 } 376 *out_value = dict; 377 return true; 378 } 379 380 } // namespace proxy_cros_settings_parser 381 382 } // namespace chromeos 383