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, |