Chromium Code Reviews| Index: extensions/browser/api/networking_private/networking_private_chromeos.cc |
| diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc |
| index 48f13a2ad0f6583d670c19746e57b099d3d785b7..31932bcbf07b4e021e6762adc1bd30cee4ca6e83 100644 |
| --- a/extensions/browser/api/networking_private/networking_private_chromeos.cc |
| +++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc |
| @@ -4,10 +4,13 @@ |
| #include "extensions/browser/api/networking_private/networking_private_chromeos.h" |
| +#include <memory> |
| + |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/callback.h" |
| #include "base/logging.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/values.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "chromeos/dbus/shill_manager_client.h" |
| @@ -25,7 +28,10 @@ |
| #include "chromeos/network/onc/onc_translator.h" |
| #include "chromeos/network/onc/onc_utils.h" |
| #include "chromeos/network/portal_detector/network_portal_detector.h" |
| +#include "chromeos/network/proxy/ui_proxy_config.h" |
| +#include "chromeos/network/proxy/ui_proxy_config_service.h" |
| #include "components/onc/onc_constants.h" |
| +#include "components/proxy_config/proxy_prefs.h" |
| #include "content/public/browser/browser_context.h" |
| #include "extensions/browser/api/networking_private/networking_private_api.h" |
| #include "extensions/browser/extension_registry.h" |
| @@ -40,6 +46,7 @@ using chromeos::NetworkHandler; |
| using chromeos::NetworkStateHandler; |
| using chromeos::NetworkTypePattern; |
| using chromeos::ShillManagerClient; |
| +using chromeos::UIProxyConfig; |
| using extensions::NetworkingPrivateDelegate; |
| namespace private_api = extensions::api::networking_private; |
| @@ -214,6 +221,77 @@ const chromeos::DeviceState* GetCellularDeviceState(const std::string& guid) { |
| return device_state; |
| } |
| +// Ensures that |container| has a DictionaryValue for |key| and returns it. |
| +base::DictionaryValue* EnsureDictionaryValue(const std::string& key, |
| + base::DictionaryValue* container) { |
| + base::DictionaryValue* dict; |
| + if (!container->GetDictionary(key, &dict)) { |
| + container->SetWithoutPathExpansion( |
| + key, base::MakeUnique<base::DictionaryValue>()); |
| + container->GetDictionary(key, &dict); |
| + } |
| + return dict; |
| +} |
| + |
| +// Sets the active and effective ONC dictionary values of |dict| based on |
| +// |state|. Also sets the UserEditable property to false. |
| +void SetProxyEffectiveValue(base::DictionaryValue* dict, |
| + ProxyPrefs::ConfigState state, |
| + std::unique_ptr<base::Value> value) { |
| + // NOTE: ProxyPrefs::ConfigState only exposes 'CONFIG_POLICY' so just use |
| + // 'UserPolicy' here for the effective type. The existing UI does not |
| + // differentiate between policy types. TODO(stevenjb): Eliminate UIProxyConfig |
| + // and instead generate a proper ONC dictionary with the correct policy source |
| + // preserved. crbug.com/662529. |
| + dict->SetStringWithoutPathExpansion(::onc::kAugmentationEffectiveSetting, |
| + state == ProxyPrefs::CONFIG_EXTENSION |
| + ? ::onc::kAugmentationActiveExtension |
| + : ::onc::kAugmentationUserPolicy); |
| + if (state != ProxyPrefs::CONFIG_EXTENSION) { |
| + std::unique_ptr<base::Value> value_copy(value->CreateDeepCopy()); |
| + dict->SetWithoutPathExpansion(::onc::kAugmentationUserPolicy, |
| + std::move(value_copy)); |
| + } |
| + dict->SetWithoutPathExpansion(::onc::kAugmentationActiveSetting, |
| + std::move(value)); |
| + dict->SetBooleanWithoutPathExpansion(::onc::kAugmentationUserEditable, false); |
| +} |
| + |
| +std::string GetProxySettingsType(const UIProxyConfig::Mode& mode) { |
| + switch (mode) { |
| + case UIProxyConfig::MODE_DIRECT: |
| + return ::onc::proxy::kDirect; |
| + case UIProxyConfig::MODE_AUTO_DETECT: |
| + return ::onc::proxy::kWPAD; |
| + case UIProxyConfig::MODE_PAC_SCRIPT: |
| + return ::onc::proxy::kPAC; |
| + case UIProxyConfig::MODE_SINGLE_PROXY: |
| + case UIProxyConfig::MODE_PROXY_PER_SCHEME: |
| + return ::onc::proxy::kManual; |
| + } |
| + NOTREACHED(); |
| + return ::onc::proxy::kDirect; |
| +} |
| + |
| +void SetManualProxy(base::DictionaryValue* manual, |
| + ProxyPrefs::ConfigState state, |
| + const std::string& key, |
| + const UIProxyConfig::ManualProxy& proxy) { |
| + base::DictionaryValue* dict = EnsureDictionaryValue(key, manual); |
| + base::DictionaryValue* host_dict = |
| + EnsureDictionaryValue(::onc::proxy::kHost, dict); |
| + SetProxyEffectiveValue(host_dict, state, |
| + base::WrapUnique<base::Value>(new base::StringValue( |
|
michaelpg
2016/11/14 21:19:23
can WrapUnique become MakeUnique without the `new`
stevenjb
2016/11/15 00:04:23
MakeUnique<Value>(string) doesn't work because Val
|
| + proxy.server.host_port_pair().host()))); |
| + uint16_t port = proxy.server.host_port_pair().port(); |
| + base::DictionaryValue* port_dict = |
| + EnsureDictionaryValue(::onc::proxy::kPort, dict); |
| + SetProxyEffectiveValue( |
| + port_dict, state, |
| + base::WrapUnique<base::Value>( |
| + new base::FundamentalValue(static_cast<int>(port)))); |
|
michaelpg
2016/11/14 21:19:23
dumb noob question: is a static cast necessary?
michaelpg
2016/11/14 21:19:23
same question
stevenjb
2016/11/15 00:04:23
No, I think it's OK, since u16 -> int isn't lossy,
|
| +} |
| + |
| } // namespace |
| //////////////////////////////////////////////////////////////////////////////// |
| @@ -227,8 +305,7 @@ NetworkingPrivateChromeOS::NetworkingPrivateChromeOS( |
| browser_context_(browser_context), |
| weak_ptr_factory_(this) {} |
| -NetworkingPrivateChromeOS::~NetworkingPrivateChromeOS() { |
| -} |
| +NetworkingPrivateChromeOS::~NetworkingPrivateChromeOS() {} |
| void NetworkingPrivateChromeOS::GetProperties( |
| const std::string& guid, |
| @@ -249,7 +326,8 @@ void NetworkingPrivateChromeOS::GetProperties( |
| GetManagedConfigurationHandler()->GetProperties( |
| user_id_hash, service_path, |
| base::Bind(&NetworkingPrivateChromeOS::GetPropertiesCallback, |
| - weak_ptr_factory_.GetWeakPtr(), success_callback), |
| + weak_ptr_factory_.GetWeakPtr(), guid, false /* managed */, |
| + success_callback), |
| base::Bind(&NetworkHandlerFailureCallback, failure_callback)); |
| } |
| @@ -272,7 +350,8 @@ void NetworkingPrivateChromeOS::GetManagedProperties( |
| GetManagedConfigurationHandler()->GetManagedProperties( |
| user_id_hash, service_path, |
| base::Bind(&NetworkingPrivateChromeOS::GetPropertiesCallback, |
| - weak_ptr_factory_.GetWeakPtr(), success_callback), |
| + weak_ptr_factory_.GetWeakPtr(), guid, true /* managed */, |
| + success_callback), |
| base::Bind(&NetworkHandlerFailureCallback, failure_callback)); |
| } |
| @@ -583,11 +662,10 @@ NetworkingPrivateChromeOS::GetDeviceStateList() { |
| } |
| // For any technologies that we do not have a DeviceState entry for, append |
| - // an entry if the technolog is available. |
| - const char* technology_types[] = {::onc::network_type::kEthernet, |
| - ::onc::network_type::kWiFi, |
| - ::onc::network_type::kWimax, |
| - ::onc::network_type::kCellular}; |
| + // an entry if the technology is available. |
| + const char* technology_types[] = { |
| + ::onc::network_type::kEthernet, ::onc::network_type::kWiFi, |
| + ::onc::network_type::kWimax, ::onc::network_type::kCellular}; |
| for (const char* technology : technology_types) { |
| if (base::ContainsValue(technologies_found, technology)) |
| continue; |
| @@ -625,15 +703,18 @@ bool NetworkingPrivateChromeOS::RequestScan() { |
| // Private methods |
| void NetworkingPrivateChromeOS::GetPropertiesCallback( |
| + const std::string& guid, |
| + bool managed, |
| const DictionaryCallback& callback, |
| const std::string& service_path, |
| const base::DictionaryValue& dictionary) { |
| std::unique_ptr<base::DictionaryValue> dictionary_copy(dictionary.DeepCopy()); |
| AppendThirdPartyProviderName(dictionary_copy.get()); |
| + if (managed) |
| + SetManagedActiveProxyValues(guid, dictionary_copy.get()); |
| callback.Run(std::move(dictionary_copy)); |
| } |
| -// Populate ThirdPartyVPN.kProviderName for third-party VPNs. |
| void NetworkingPrivateChromeOS::AppendThirdPartyProviderName( |
| base::DictionaryValue* dictionary) { |
| base::DictionaryValue* third_party_vpn = |
| @@ -656,6 +737,80 @@ void NetworkingPrivateChromeOS::AppendThirdPartyProviderName( |
| } |
| } |
| +void NetworkingPrivateChromeOS::SetManagedActiveProxyValues( |
| + const std::string& guid, |
| + base::DictionaryValue* dictionary) { |
| + // NOTE: We use UIProxyConfigService and UIProxyConfig for historical |
| + // reasons. The model and service were written for a much older UI but |
| + // contain a fair amount of subtle logic which is why we use them. |
| + // TODO(stevenjb): Re-factor this code and eliminate UIProxyConfig once |
| + // the old options UI is abandoned. crbug.com/662529. |
| + chromeos::UIProxyConfigService* ui_proxy_config_service = |
| + NetworkHandler::Get()->ui_proxy_config_service(); |
| + ui_proxy_config_service->UpdateFromPrefs(guid); |
| + UIProxyConfig config; |
| + ui_proxy_config_service->GetProxyConfig(guid, &config); |
| + ProxyPrefs::ConfigState state = config.state; |
| + |
| + VLOG(1) << "CONFIG STATE FOR: " << guid << ": " << state |
|
michaelpg
2016/11/14 21:19:23
intentionally left in?
stevenjb
2016/11/15 00:04:23
Yeah. I'm not convinced I'm done debugging this.
|
| + << " MODE: " << config.mode; |
| + |
| + if (state != ProxyPrefs::CONFIG_POLICY && |
| + state != ProxyPrefs::CONFIG_EXTENSION && |
| + state != ProxyPrefs::CONFIG_OTHER_PRECEDE) { |
| + return; |
| + } |
| + |
| + // Ensure that the ProxySettings dictionary exists. |
| + base::DictionaryValue* proxy_settings = |
| + EnsureDictionaryValue(::onc::network_config::kProxySettings, dictionary); |
| + VLOG(2) << " PROXY: " << *proxy_settings; |
| + |
| + // Ensure that the ProxySettings.Type dictionary exists and set the Type |
| + // value to the value from |ui_proxy_config_service|. |
| + base::DictionaryValue* proxy_type_dict = |
| + EnsureDictionaryValue(::onc::network_config::kType, proxy_settings); |
| + SetProxyEffectiveValue(proxy_type_dict, state, |
| + base::WrapUnique<base::Value>(new base::StringValue( |
| + GetProxySettingsType(config.mode)))); |
| + |
| + // Update any appropriate sub dictionary based on the new type. |
| + switch (config.mode) { |
| + case UIProxyConfig::MODE_SINGLE_PROXY: { |
| + // Use the same proxy value (config.single_proxy) for all proxies. |
| + base::DictionaryValue* manual = |
| + EnsureDictionaryValue(::onc::proxy::kManual, proxy_settings); |
| + SetManualProxy(manual, state, ::onc::proxy::kHttp, config.single_proxy); |
| + SetManualProxy(manual, state, ::onc::proxy::kHttps, config.single_proxy); |
| + SetManualProxy(manual, state, ::onc::proxy::kFtp, config.single_proxy); |
| + SetManualProxy(manual, state, ::onc::proxy::kSocks, config.single_proxy); |
| + break; |
| + } |
| + case UIProxyConfig::MODE_PROXY_PER_SCHEME: { |
| + base::DictionaryValue* manual = |
| + EnsureDictionaryValue(::onc::proxy::kManual, proxy_settings); |
| + SetManualProxy(manual, state, ::onc::proxy::kHttp, config.http_proxy); |
| + SetManualProxy(manual, state, ::onc::proxy::kHttps, config.https_proxy); |
| + SetManualProxy(manual, state, ::onc::proxy::kFtp, config.ftp_proxy); |
| + SetManualProxy(manual, state, ::onc::proxy::kSocks, config.socks_proxy); |
| + break; |
| + } |
| + case UIProxyConfig::MODE_PAC_SCRIPT: { |
| + base::DictionaryValue* pac = |
| + EnsureDictionaryValue(::onc::proxy::kPAC, proxy_settings); |
| + SetProxyEffectiveValue( |
| + pac, state, base::WrapUnique<base::Value>(new base::StringValue( |
| + config.automatic_proxy.pac_url.spec()))); |
| + break; |
| + } |
| + case UIProxyConfig::MODE_DIRECT: |
| + case UIProxyConfig::MODE_AUTO_DETECT: |
| + break; |
| + } |
| + |
| + VLOG(2) << " NEW PROXY: " << *proxy_settings; |
| +} |
| + |
| void NetworkingPrivateChromeOS::ConnectFailureCallback( |
| const std::string& guid, |
| const VoidCallback& success_callback, |