Home | History | Annotate | Download | only in chromeos
      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