Chromium Code Reviews| Index: chromeos/network/onc/onc_utils.cc |
| diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc |
| index 2e4d384c4985fdde5ef2b0fb49f789fa373654f8..85c2b9d7152f92541a11bf5085c8bfab53ade064 100644 |
| --- a/chromeos/network/onc/onc_utils.cc |
| +++ b/chromeos/network/onc/onc_utils.cc |
| @@ -17,11 +17,17 @@ |
| #include "chromeos/network/onc/onc_utils.h" |
| #include "chromeos/network/onc/onc_validator.h" |
| #include "components/device_event_log/device_event_log.h" |
| +#include "components/proxy_config/proxy_config_dictionary.h" |
| #include "crypto/encryptor.h" |
| #include "crypto/hmac.h" |
| #include "crypto/symmetric_key.h" |
| +#include "net/base/host_port_pair.h" |
| #include "net/cert/pem_tokenizer.h" |
| #include "net/cert/x509_certificate.h" |
| +#include "net/proxy/proxy_bypass_rules.h" |
| +#include "net/proxy/proxy_config.h" |
| +#include "net/proxy/proxy_server.h" |
| +#include "url/url_constants.h" |
| using namespace ::onc; |
| @@ -738,5 +744,245 @@ bool IsRecommendedValue(const base::DictionaryValue* onc, |
| recommended_keys->end()); |
| } |
| +namespace { |
| + |
| +const char kDirectScheme[] = "direct"; |
| +const char kQuicScheme[] = "quic"; |
| +const char kSocksScheme[] = "socks"; |
| +const char kSocks4Scheme[] = "socks4"; |
| +const char kSocks5Scheme[] = "socks5"; |
| + |
| +net::ProxyServer ConvertOncProxyLocationToHostPort( |
| + net::ProxyServer::Scheme default_proxy_scheme, |
| + const base::DictionaryValue& onc_proxy_location) { |
| + std::string host; |
| + onc_proxy_location.GetStringWithoutPathExpansion(::onc::proxy::kHost, &host); |
| + // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>]. |
| + net::ProxyServer proxy_server = |
| + net::ProxyServer::FromURI(host, default_proxy_scheme); |
| + int port = 0; |
| + onc_proxy_location.GetIntegerWithoutPathExpansion(::onc::proxy::kPort, &port); |
| + |
| + // Replace the port parsed from |host| by the provided |port|. |
| + return net::ProxyServer( |
| + proxy_server.scheme(), |
| + net::HostPortPair(proxy_server.host_port_pair().host(), |
| + static_cast<uint16>(port))); |
| +} |
| + |
| +void AppendProxyServerForScheme(const base::DictionaryValue& onc_manual, |
| + const std::string& onc_scheme, |
| + std::string* spec) { |
| + const base::DictionaryValue* onc_proxy_location = nullptr; |
| + if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme, |
| + &onc_proxy_location)) { |
| + return; |
| + } |
| + |
| + net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP; |
| + std::string url_scheme; |
| + if (onc_scheme == ::onc::proxy::kFtp) { |
| + url_scheme = url::kFtpScheme; |
| + } else if (onc_scheme == ::onc::proxy::kHttp) { |
| + url_scheme = url::kHttpScheme; |
| + } else if (onc_scheme == ::onc::proxy::kHttps) { |
| + url_scheme = url::kHttpsScheme; |
| + } else if (onc_scheme == ::onc::proxy::kSocks) { |
| + default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4; |
| + url_scheme = kSocksScheme; |
| + } else { |
| + NOTREACHED(); |
| + } |
| + |
| + net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort( |
| + default_proxy_scheme, *onc_proxy_location); |
| + |
| + ProxyConfigDictionary::EncodeAndAppendProxyServer(url_scheme, proxy_server, |
| + spec); |
| +} |
| + |
| +net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules( |
| + const base::ListValue& onc_exclude_domains) { |
| + net::ProxyBypassRules rules; |
| + for (base::ListValue::const_iterator it = onc_exclude_domains.begin(); |
| + it != onc_exclude_domains.end(); ++it) { |
| + std::string rule; |
| + (*it)->GetAsString(&rule); |
| + rules.AddRuleFromString(rule); |
| + } |
| + return rules; |
| +} |
| + |
| +std::string SchemeToString(net::ProxyServer::Scheme scheme) { |
| + switch (scheme) { |
| + case net::ProxyServer::SCHEME_DIRECT: |
| + return kDirectScheme; |
| + case net::ProxyServer::SCHEME_HTTP: |
| + return url::kHttpScheme; |
| + case net::ProxyServer::SCHEME_SOCKS4: |
| + return kSocks4Scheme; |
| + case net::ProxyServer::SCHEME_SOCKS5: |
| + return kSocks5Scheme; |
| + case net::ProxyServer::SCHEME_HTTPS: |
| + return url::kHttpsScheme; |
| + case net::ProxyServer::SCHEME_QUIC: |
| + return kQuicScheme; |
| + case net::ProxyServer::SCHEME_INVALID: |
| + break; |
| + } |
| + NOTREACHED(); |
| + return ""; |
| +} |
| + |
| +void SetProxyForScheme(const net::ProxyConfig::ProxyRules& proxy_rules, |
| + const std::string& scheme, |
| + const std::string& onc_scheme, |
| + base::DictionaryValue* dict) { |
| + const net::ProxyList* proxy_list = nullptr; |
| + if (proxy_rules.type == net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY) { |
| + proxy_list = &proxy_rules.single_proxies; |
| + } else if (proxy_rules.type == |
| + net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) { |
| + proxy_list = proxy_rules.MapUrlSchemeToProxyList(scheme); |
| + } |
| + if (!proxy_list || proxy_list->IsEmpty()) |
| + return; |
| + const net::ProxyServer& server = proxy_list->Get(); |
| + scoped_ptr<base::DictionaryValue> url_dict(new base::DictionaryValue); |
| + std::string host = server.host_port_pair().host(); |
| + |
| + // For all proxy types except SOCKS, the default scheme of the proxy host is |
| + // HTTP. |
| + net::ProxyServer::Scheme default_scheme = |
| + (onc_scheme == ::onc::proxy::kSocks) ? net::ProxyServer::SCHEME_SOCKS4 |
| + : net::ProxyServer::SCHEME_HTTP; |
| + // Only prefix the host with a non-default scheme. |
| + if (server.scheme() != default_scheme) |
|
pneubeck (no reviews)
2015/07/10 07:20:42
as explained in the other comment, it should also
stevenjb
2015/07/10 16:16:59
I am going to leave it as is for now because it wo
|
| + host = SchemeToString(server.scheme()) + "://" + host; |
| + url_dict->SetStringWithoutPathExpansion(::onc::proxy::kHost, host); |
| + url_dict->SetIntegerWithoutPathExpansion(::onc::proxy::kPort, |
| + server.host_port_pair().port()); |
| + dict->SetWithoutPathExpansion(onc_scheme, url_dict.release()); |
| +} |
| + |
| +} // namespace |
| + |
| +scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig( |
| + const base::DictionaryValue& onc_proxy_settings) { |
| + std::string type; |
| + onc_proxy_settings.GetStringWithoutPathExpansion(::onc::proxy::kType, &type); |
| + scoped_ptr<base::DictionaryValue> proxy_dict; |
| + |
| + if (type == ::onc::proxy::kDirect) { |
| + proxy_dict.reset(ProxyConfigDictionary::CreateDirect()); |
| + } else if (type == ::onc::proxy::kWPAD) { |
| + proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect()); |
| + } else if (type == ::onc::proxy::kPAC) { |
| + std::string pac_url; |
| + onc_proxy_settings.GetStringWithoutPathExpansion(::onc::proxy::kPAC, |
| + &pac_url); |
| + GURL url(pac_url); |
| + DCHECK(url.is_valid()) << "Invalid URL in ProxySettings.PAC"; |
| + proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(), false)); |
| + } else if (type == ::onc::proxy::kManual) { |
| + const base::DictionaryValue* manual_dict = nullptr; |
| + onc_proxy_settings.GetDictionaryWithoutPathExpansion(::onc::proxy::kManual, |
| + &manual_dict); |
| + std::string manual_spec; |
| + AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kFtp, &manual_spec); |
| + AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kHttp, &manual_spec); |
| + AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kSocks, |
| + &manual_spec); |
| + AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kHttps, |
| + &manual_spec); |
| + |
| + const base::ListValue* exclude_domains = nullptr; |
| + net::ProxyBypassRules bypass_rules; |
| + if (onc_proxy_settings.GetListWithoutPathExpansion( |
| + ::onc::proxy::kExcludeDomains, &exclude_domains)) { |
| + bypass_rules.AssignFrom( |
| + ConvertOncExcludeDomainsToBypassRules(*exclude_domains)); |
| + } |
| + proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers( |
| + manual_spec, bypass_rules.ToString())); |
| + } else { |
| + NOTREACHED(); |
| + } |
| + return proxy_dict.Pass(); |
| +} |
| + |
| +scoped_ptr<base::DictionaryValue> ConvertProxyConfigToOncProxySettings( |
| + const base::DictionaryValue& proxy_config_value) { |
| + // Create a ProxyConfigDictionary from the DictionaryValue. |
| + scoped_ptr<ProxyConfigDictionary> proxy_config( |
| + new ProxyConfigDictionary(&proxy_config_value)); |
| + |
| + // Create the result DictionaryValue and populate it. |
| + scoped_ptr<base::DictionaryValue> proxy_settings(new base::DictionaryValue); |
| + ProxyPrefs::ProxyMode mode; |
| + if (!proxy_config->GetMode(&mode)) |
| + return nullptr; |
| + switch (mode) { |
| + case ProxyPrefs::MODE_DIRECT: { |
| + proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kType, |
| + ::onc::proxy::kDirect); |
| + break; |
| + } |
| + case ProxyPrefs::MODE_AUTO_DETECT: { |
| + proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kType, |
| + ::onc::proxy::kWPAD); |
| + break; |
| + } |
| + case ProxyPrefs::MODE_PAC_SCRIPT: { |
| + proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kType, |
| + ::onc::proxy::kPAC); |
| + std::string pac_url; |
| + proxy_config->GetPacUrl(&pac_url); |
| + proxy_settings->SetStringWithoutPathExpansion(::onc::proxy::kPAC, |
| + pac_url); |
| + break; |
| + } |
| + case ProxyPrefs::MODE_FIXED_SERVERS: { |
| + proxy_settings->SetString(::onc::proxy::kType, ::onc::proxy::kManual); |
| + scoped_ptr<base::DictionaryValue> manual(new base::DictionaryValue); |
| + std::string proxy_rules_string; |
| + if (proxy_config->GetProxyServer(&proxy_rules_string)) { |
| + net::ProxyConfig::ProxyRules proxy_rules; |
| + proxy_rules.ParseFromString(proxy_rules_string); |
| + SetProxyForScheme(proxy_rules, url::kFtpScheme, ::onc::proxy::kFtp, |
| + manual.get()); |
| + SetProxyForScheme(proxy_rules, url::kHttpScheme, ::onc::proxy::kHttp, |
| + manual.get()); |
| + SetProxyForScheme(proxy_rules, url::kHttpsScheme, ::onc::proxy::kHttps, |
| + manual.get()); |
| + SetProxyForScheme(proxy_rules, kSocksScheme, ::onc::proxy::kSocks, |
| + manual.get()); |
| + } |
| + proxy_settings->SetWithoutPathExpansion(::onc::proxy::kManual, |
| + manual.release()); |
| + |
| + // Convert the 'bypass_list' string into dictionary entries. |
| + std::string bypass_rules_string; |
| + if (proxy_config->GetBypassList(&bypass_rules_string)) { |
| + net::ProxyBypassRules bypass_rules; |
| + bypass_rules.ParseFromString(bypass_rules_string); |
| + scoped_ptr<base::ListValue> exclude_domains(new base::ListValue); |
| + for (const net::ProxyBypassRules::Rule* rule : bypass_rules.rules()) |
| + exclude_domains->AppendString(rule->ToString()); |
| + if (!exclude_domains->empty()) { |
| + proxy_settings->SetWithoutPathExpansion(::onc::proxy::kExcludeDomains, |
| + exclude_domains.release()); |
| + } |
| + } |
| + break; |
| + } |
| + default: { |
| + LOG(ERROR) << "Unexpected proxy mode in Shill config: " << mode; |
| + return nullptr; |
| + } |
| + } |
| + return proxy_settings.Pass(); |
| +} |
| + |
| } // namespace onc |
| } // namespace chromeos |