| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/crosapi/network_settings_translation.h" |
| |
| #include "base/strings/string_split.h" |
| #include "components/proxy_config/proxy_config_dictionary.h" |
| #include "components/proxy_config/proxy_config_pref_names.h" |
| #include "components/proxy_config/proxy_prefs.h" |
| #include "net/base/host_port_pair.h" |
| #include "net/base/proxy_server.h" |
| #include "net/proxy_resolution/proxy_config.h" |
| #include "net/proxy_resolution/proxy_list.h" |
| #include "net/traffic_annotation/network_traffic_annotation.h" |
| |
| namespace { |
| |
| crosapi::mojom::ProxyLocation::Scheme NetSchemeToCrosapiScheme( |
| net::ProxyServer::Scheme in) { |
| switch (in) { |
| case net::ProxyServer::Scheme::SCHEME_INVALID: |
| return crosapi::mojom::ProxyLocation::Scheme::kInvalid; |
| case net::ProxyServer::Scheme::SCHEME_HTTP: |
| return crosapi::mojom::ProxyLocation::Scheme::kHttp; |
| case net::ProxyServer::Scheme::SCHEME_SOCKS4: |
| return crosapi::mojom::ProxyLocation::Scheme::kSocks4; |
| case net::ProxyServer::Scheme::SCHEME_SOCKS5: |
| return crosapi::mojom::ProxyLocation::Scheme::kSocks5; |
| case net::ProxyServer::Scheme::SCHEME_HTTPS: |
| return crosapi::mojom::ProxyLocation::Scheme::kHttps; |
| case net::ProxyServer::Scheme::SCHEME_QUIC: |
| return crosapi::mojom::ProxyLocation::Scheme::kQuic; |
| } |
| |
| return crosapi::mojom::ProxyLocation::Scheme::kUnknown; |
| } |
| |
| std::vector<crosapi::mojom::ProxyLocationPtr> TranslateProxyLocations( |
| const net::ProxyList& proxy_list) { |
| std::vector<crosapi::mojom::ProxyLocationPtr> proxy_ptr_list; |
| for (const auto& proxy_chain : proxy_list.AllChains()) { |
| // TODO(crbug.com/40284947): Remove single hop check when multi-hop proxy |
| // chains are supported. |
| CHECK(proxy_chain.is_single_proxy()); |
| net::ProxyServer proxy = proxy_chain.First(); |
| crosapi::mojom::ProxyLocationPtr proxy_ptr; |
| proxy_ptr = crosapi::mojom::ProxyLocation::New(); |
| proxy_ptr->host = proxy.host_port_pair().host(); |
| proxy_ptr->port = proxy.host_port_pair().port(); |
| proxy_ptr->scheme = NetSchemeToCrosapiScheme(proxy.scheme()); |
| proxy_ptr_list.push_back(std::move(proxy_ptr)); |
| } |
| return proxy_ptr_list; |
| } |
| |
| crosapi::mojom::ProxySettingsManualPtr TranslateManualProxySettings( |
| ProxyConfigDictionary* proxy_config) { |
| crosapi::mojom::ProxySettingsManualPtr manual_proxy = |
| crosapi::mojom::ProxySettingsManual::New(); |
| |
| ProxyPrefs::ProxyMode mode; |
| DCHECK(proxy_config->GetMode(&mode) && |
| mode == ProxyPrefs::MODE_FIXED_SERVERS); |
| |
| std::string proxy_servers; |
| if (!proxy_config->GetProxyServer(&proxy_servers)) { |
| LOG(ERROR) << "Missing manual proxy servers."; |
| return nullptr; |
| } |
| |
| net::ProxyConfig::ProxyRules rules; |
| rules.ParseFromString(proxy_servers); |
| |
| switch (rules.type) { |
| case net::ProxyConfig::ProxyRules::Type::EMPTY: |
| return nullptr; |
| case net::ProxyConfig::ProxyRules::Type::PROXY_LIST: |
| if (!rules.single_proxies.IsEmpty()) { |
| manual_proxy->http_proxies = |
| TranslateProxyLocations(rules.single_proxies); |
| manual_proxy->secure_http_proxies = |
| TranslateProxyLocations(rules.single_proxies); |
| manual_proxy->socks_proxies = |
| TranslateProxyLocations(rules.single_proxies); |
| } |
| break; |
| case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME: |
| if (!rules.proxies_for_http.IsEmpty()) { |
| manual_proxy->http_proxies = |
| TranslateProxyLocations(rules.proxies_for_http); |
| } |
| if (!rules.proxies_for_https.IsEmpty()) { |
| manual_proxy->secure_http_proxies = |
| TranslateProxyLocations(rules.proxies_for_https); |
| } |
| if (!rules.fallback_proxies.IsEmpty()) { |
| manual_proxy->socks_proxies = |
| TranslateProxyLocations(rules.fallback_proxies); |
| } |
| break; |
| } |
| |
| std::string bypass_list; |
| if (proxy_config->GetBypassList(&bypass_list) && !bypass_list.empty()) { |
| manual_proxy->exclude_domains = base::SplitString( |
| bypass_list, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| } |
| return manual_proxy; |
| } |
| |
| } // namespace |
| |
| namespace crosapi { |
| |
| // static |
| crosapi::mojom::ProxyConfigPtr ProxyConfigToCrosapiProxy( |
| ProxyConfigDictionary* proxy_dict, |
| GURL dhcp_wpad_url) { |
| crosapi::mojom::ProxyConfigPtr proxy_config = |
| crosapi::mojom::ProxyConfig::New(); |
| crosapi::mojom::ProxySettingsDirectPtr direct = |
| crosapi::mojom::ProxySettingsDirect::New(); |
| |
| ProxyPrefs::ProxyMode mode; |
| if (!proxy_dict || !proxy_dict->GetMode(&mode)) { |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewDirect(std::move(direct)); |
| return proxy_config; |
| } |
| switch (mode) { |
| case ProxyPrefs::MODE_DIRECT: |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewDirect(std::move(direct)); |
| break; |
| case ProxyPrefs::MODE_AUTO_DETECT: { |
| crosapi::mojom::ProxySettingsWpadPtr wpad = |
| crosapi::mojom::ProxySettingsWpad::New(); |
| // WPAD with DHCP has a higher priority than DNS. |
| if (dhcp_wpad_url.is_valid()) { |
| wpad->pac_url = std::move(dhcp_wpad_url); |
| } else { |
| // Fallback to WPAD via DNS. |
| wpad->pac_url = GURL("http://wpad/wpad.dat"); |
| } |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewWpad(std::move(wpad)); |
| break; |
| } |
| case ProxyPrefs::MODE_PAC_SCRIPT: { |
| std::string pac_url; |
| if (!proxy_dict->GetPacUrl(&pac_url)) { |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewDirect(std::move(direct)); |
| LOG(ERROR) << "No pac URL for pac_script proxy mode."; |
| break; |
| } |
| bool pac_mandatory = false; |
| proxy_dict->GetPacMandatory(&pac_mandatory); |
| |
| crosapi::mojom::ProxySettingsPacPtr pac = |
| crosapi::mojom::ProxySettingsPac::New(); |
| pac->pac_url = GURL(pac_url); |
| pac->pac_mandatory = pac_mandatory; |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewPac(std::move(pac)); |
| break; |
| } |
| case ProxyPrefs::MODE_FIXED_SERVERS: { |
| crosapi::mojom::ProxySettingsManualPtr manual = |
| TranslateManualProxySettings(proxy_dict); |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewManual(std::move(manual)); |
| break; |
| } |
| case ProxyPrefs::MODE_SYSTEM: |
| // This mode means Chrome is getting the settings from the operating |
| // system. On Chrome OS, ash-chrome is the source of truth for proxy |
| // settings so this mode is never used. |
| NOTREACHED_IN_MIGRATION() |
| << "The system mode doesn't apply to Ash-Chrome"; |
| break; |
| default: |
| LOG(ERROR) << "Incorrect proxy mode."; |
| proxy_config->proxy_settings = |
| crosapi::mojom::ProxySettings::NewDirect(std::move(direct)); |
| } |
| |
| return proxy_config; |
| } |
| |
| } // namespace crosapi |