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              ? new base::FundamentalValue(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 = new base::FundamentalValue(3);
    314     } else if (config.mode == UIProxyConfig::MODE_SINGLE_PROXY ||
    315                config.mode == UIProxyConfig::MODE_PROXY_PER_SCHEME) {
    316       data = new base::FundamentalValue(2);
    317     } else {
    318       data = new base::FundamentalValue(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 = new base::FundamentalValue(config.mode ==
    337                                       UIProxyConfig::MODE_SINGLE_PROXY);
    338   } else if (path == kProxyUsePacUrl) {
    339     data = new base::FundamentalValue(config.mode ==
    340                                       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