Home | History | Annotate | Download | only in net
      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/net/onc_utils.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/values.h"
      9 #include "chrome/browser/chromeos/login/user.h"
     10 #include "chrome/browser/chromeos/login/user_manager.h"
     11 #include "chrome/browser/chromeos/ui_proxy_config.h"
     12 #include "chrome/browser/prefs/proxy_config_dictionary.h"
     13 #include "chromeos/network/onc/onc_utils.h"
     14 #include "net/base/host_port_pair.h"
     15 #include "net/proxy/proxy_bypass_rules.h"
     16 #include "net/proxy/proxy_server.h"
     17 #include "url/gurl.h"
     18 
     19 namespace chromeos {
     20 namespace onc {
     21 
     22 namespace {
     23 
     24 net::ProxyServer ConvertOncProxyLocationToHostPort(
     25     net::ProxyServer::Scheme default_proxy_scheme,
     26     const base::DictionaryValue& onc_proxy_location) {
     27   std::string host;
     28   onc_proxy_location.GetStringWithoutPathExpansion(onc::proxy::kHost, &host);
     29   // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>].
     30   net::ProxyServer proxy_server =
     31       net::ProxyServer::FromURI(host, default_proxy_scheme);
     32   int port = 0;
     33   onc_proxy_location.GetIntegerWithoutPathExpansion(onc::proxy::kPort, &port);
     34 
     35   // Replace the port parsed from |host| by the provided |port|.
     36   return net::ProxyServer(
     37       proxy_server.scheme(),
     38       net::HostPortPair(proxy_server.host_port_pair().host(),
     39                         static_cast<uint16>(port)));
     40 }
     41 
     42 void AppendProxyServerForScheme(
     43     const base::DictionaryValue& onc_manual,
     44     const std::string& onc_scheme,
     45     std::string* spec) {
     46   const base::DictionaryValue* onc_proxy_location = NULL;
     47   if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme,
     48                                                     &onc_proxy_location)) {
     49     return;
     50   }
     51 
     52   net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP;
     53   std::string url_scheme;
     54   if (onc_scheme == proxy::kFtp) {
     55     url_scheme = "ftp";
     56   } else if (onc_scheme == proxy::kHttp) {
     57     url_scheme = "http";
     58   } else if (onc_scheme == proxy::kHttps) {
     59     url_scheme = "https";
     60   } else if (onc_scheme == proxy::kSocks) {
     61     default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4;
     62     url_scheme = "socks";
     63   } else {
     64     NOTREACHED();
     65   }
     66 
     67   net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort(
     68       default_proxy_scheme, *onc_proxy_location);
     69 
     70   UIProxyConfig::EncodeAndAppendProxyServer(url_scheme, proxy_server, spec);
     71 }
     72 
     73 net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules(
     74     const base::ListValue& onc_exclude_domains) {
     75   net::ProxyBypassRules rules;
     76   for (base::ListValue::const_iterator it = onc_exclude_domains.begin();
     77        it != onc_exclude_domains.end(); ++it) {
     78     std::string rule;
     79     (*it)->GetAsString(&rule);
     80     rules.AddRuleFromString(rule);
     81   }
     82   return rules;
     83 }
     84 
     85 }  // namespace
     86 
     87 scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
     88     const base::DictionaryValue& onc_proxy_settings) {
     89   std::string type;
     90   onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kType, &type);
     91   scoped_ptr<DictionaryValue> proxy_dict;
     92 
     93   if (type == proxy::kDirect) {
     94     proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
     95   } else if (type == proxy::kWPAD) {
     96     proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
     97   } else if (type == proxy::kPAC) {
     98     std::string pac_url;
     99     onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kPAC, &pac_url);
    100     GURL url(pac_url);
    101     DCHECK(url.is_valid())
    102         << "PAC field is invalid for this ProxySettings.Type";
    103     proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(),
    104                                                             false));
    105   } else if (type == proxy::kManual) {
    106     const base::DictionaryValue* manual_dict = NULL;
    107     onc_proxy_settings.GetDictionaryWithoutPathExpansion(proxy::kManual,
    108                                                          &manual_dict);
    109     std::string manual_spec;
    110     AppendProxyServerForScheme(*manual_dict, proxy::kFtp, &manual_spec);
    111     AppendProxyServerForScheme(*manual_dict, proxy::kHttp, &manual_spec);
    112     AppendProxyServerForScheme(*manual_dict, proxy::kSocks, &manual_spec);
    113     AppendProxyServerForScheme(*manual_dict, proxy::kHttps, &manual_spec);
    114 
    115     const base::ListValue* exclude_domains = NULL;
    116     net::ProxyBypassRules bypass_rules;
    117     if (onc_proxy_settings.GetListWithoutPathExpansion(proxy::kExcludeDomains,
    118                                                        &exclude_domains)) {
    119       bypass_rules.AssignFrom(
    120           ConvertOncExcludeDomainsToBypassRules(*exclude_domains));
    121     }
    122     proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
    123         manual_spec, bypass_rules.ToString()));
    124   } else {
    125     NOTREACHED();
    126   }
    127   return proxy_dict.Pass();
    128 }
    129 
    130 namespace {
    131 
    132 // This class defines which string placeholders of ONC are replaced by which
    133 // user attribute.
    134 class UserStringSubstitution : public chromeos::onc::StringSubstitution {
    135  public:
    136   explicit UserStringSubstitution(const chromeos::User* user) : user_(user) {}
    137   virtual ~UserStringSubstitution() {}
    138 
    139   virtual bool GetSubstitute(const std::string& placeholder,
    140                              std::string* substitute) const OVERRIDE {
    141     if (placeholder == chromeos::onc::substitutes::kLoginIDField)
    142       *substitute = user_->GetAccountName(false);
    143     else if (placeholder == chromeos::onc::substitutes::kEmailField)
    144       *substitute = user_->email();
    145     else
    146       return false;
    147     return true;
    148   }
    149 
    150  private:
    151   const chromeos::User* user_;
    152 
    153   DISALLOW_COPY_AND_ASSIGN(UserStringSubstitution);
    154 };
    155 
    156 const chromeos::User* GetLoggedInUserByHash(const std::string& userhash) {
    157   const chromeos::UserList& users =
    158       chromeos::UserManager::Get()->GetLoggedInUsers();
    159   for (chromeos::UserList::const_iterator it = users.begin(); it != users.end();
    160        ++it) {
    161     if ((*it)->username_hash() == userhash)
    162       return *it;
    163   }
    164   return NULL;
    165 }
    166 
    167 }  // namespace
    168 
    169 void ExpandStringPlaceholdersInNetworksForUser(
    170     const std::string& hashed_username,
    171     base::ListValue* network_configs) {
    172   const chromeos::User* user = GetLoggedInUserByHash(hashed_username);
    173   if (!user) {
    174     // In tests no user may be logged in. It's not harmful if we just don't
    175     // expand the strings.
    176     return;
    177   }
    178   UserStringSubstitution substitution(user);
    179   chromeos::onc::ExpandStringsInNetworks(substitution, network_configs);
    180 }
    181 
    182 }  // namespace onc
    183 }  // namespace chromeos
    184