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