| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/json/json_writer.h" |
| #include "base/macros.h" |
| #include "base/run_loop.h" |
| #include "base/test/task_environment.h" |
| #include "base/test/values_test_util.h" |
| #include "base/values.h" |
| #include "chromeos/dbus/shill/shill_clients.h" |
| #include "chromeos/dbus/shill/shill_profile_client.h" |
| #include "chromeos/dbus/shill/shill_service_client.h" |
| #include "chromeos/network/managed_network_configuration_handler_impl.h" |
| #include "chromeos/network/mock_network_state_handler.h" |
| #include "chromeos/network/network_configuration_handler.h" |
| #include "chromeos/network/network_policy_observer.h" |
| #include "chromeos/network/network_profile_handler.h" |
| #include "chromeos/network/network_state.h" |
| #include "chromeos/network/onc/onc_signature.h" |
| #include "chromeos/network/onc/onc_test_utils.h" |
| #include "chromeos/network/onc/onc_utils.h" |
| #include "chromeos/network/onc/onc_validator.h" |
| #include "chromeos/network/proxy/ui_proxy_config_service.h" |
| #include "components/onc/onc_pref_names.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "components/proxy_config/pref_proxy_config_tracker_impl.h" |
| #include "components/proxy_config/proxy_config_dictionary.h" |
| #include "components/proxy_config/proxy_config_pref_names.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| |
| namespace test_utils = ::chromeos::onc::test_utils; |
| using base::test::DictionaryHasValues; |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| constexpr char kUser1[] = "user1"; |
| constexpr char kUser1ProfilePath[] = "/profile/user1/shill"; |
| |
| // The GUID used by chromeos/test/data/network/policy/*.{json,onc} files for a |
| // VPN. |
| constexpr char kTestGuidVpn[] = "{a3860e83-f03d-4cb1-bafa-b22c9e746950}"; |
| |
| // The GUID used by chromeos/test/data/network/policy/*.{json,onc} files for a |
| // managed Wifi service. |
| constexpr char kTestGuidManagedWifi[] = "policy_wifi1"; |
| |
| // The GUID used by chromeos/test/data/network/policy/*.{json,onc} files for an |
| // unmanaged Wifi service. |
| constexpr char kTestGuidUnmanagedWifi2[] = "wifi2"; |
| |
| // The GUID used by chromeos/test/data/network/policy/*.{json,onc} files for a |
| // Wifi service. |
| constexpr char kTestGuidEthernetEap[] = "policy_ethernet_eap"; |
| |
| std::string PrettyJson(const base::DictionaryValue& value) { |
| std::string pretty; |
| base::JSONWriter::WriteWithOptions( |
| value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &pretty); |
| return pretty; |
| } |
| |
| void ErrorCallback(const std::string& error_name, |
| std::unique_ptr<base::DictionaryValue> error_data) { |
| ADD_FAILURE() << "Unexpected error: " << error_name |
| << " with associated data: \n" |
| << PrettyJson(*error_data); |
| } |
| |
| class TestNetworkProfileHandler : public NetworkProfileHandler { |
| public: |
| TestNetworkProfileHandler() { Init(); } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TestNetworkProfileHandler); |
| }; |
| |
| class TestNetworkPolicyObserver : public NetworkPolicyObserver { |
| public: |
| TestNetworkPolicyObserver() = default; |
| |
| void PoliciesApplied(const std::string& userhash) override { |
| policies_applied_count_++; |
| } |
| |
| int GetPoliciesAppliedCountAndReset() { |
| int count = policies_applied_count_; |
| policies_applied_count_ = 0; |
| return count; |
| } |
| |
| private: |
| int policies_applied_count_ = 0; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestNetworkPolicyObserver); |
| }; |
| |
| } // namespace |
| |
| class ManagedNetworkConfigurationHandlerTest : public testing::Test { |
| public: |
| ManagedNetworkConfigurationHandlerTest() { |
| shill_clients::InitializeFakes(); |
| |
| network_state_handler_ = MockNetworkStateHandler::InitializeForTest(); |
| network_profile_handler_ = std::make_unique<TestNetworkProfileHandler>(); |
| network_configuration_handler_.reset( |
| NetworkConfigurationHandler::InitializeForTest( |
| network_state_handler_.get(), |
| nullptr /* no NetworkDeviceHandler */)); |
| |
| // ManagedNetworkConfigurationHandlerImpl's ctor is private. |
| managed_network_configuration_handler_.reset( |
| new ManagedNetworkConfigurationHandlerImpl()); |
| |
| PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry()); |
| PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry()); |
| ::onc::RegisterProfilePrefs(user_prefs_.registry()); |
| ::onc::RegisterPrefs(local_state_.registry()); |
| |
| ui_proxy_config_service_ = std::make_unique<UIProxyConfigService>( |
| &user_prefs_, &local_state_, network_state_handler_.get(), |
| network_profile_handler_.get()); |
| managed_network_configuration_handler_->Init( |
| network_state_handler_.get(), network_profile_handler_.get(), |
| network_configuration_handler_.get(), nullptr /* no DeviceHandler */, |
| nullptr /* no ProhibitedTechnologiesHandler */); |
| managed_network_configuration_handler_->set_ui_proxy_config_service( |
| ui_proxy_config_service_.get()); |
| managed_network_configuration_handler_->AddObserver(&policy_observer_); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| ~ManagedNetworkConfigurationHandlerTest() override { |
| network_state_handler_->Shutdown(); |
| ResetManagedNetworkConfigurationHandler(); |
| network_configuration_handler_.reset(); |
| network_profile_handler_.reset(); |
| network_state_handler_.reset(); |
| ui_proxy_config_service_.reset(); |
| shill_clients::Shutdown(); |
| } |
| |
| TestNetworkPolicyObserver* policy_observer() { return &policy_observer_; } |
| |
| ManagedNetworkConfigurationHandler* managed_handler() { |
| return managed_network_configuration_handler_.get(); |
| } |
| |
| ShillServiceClient::TestInterface* GetShillServiceClient() { |
| return ShillServiceClient::Get()->GetTestInterface(); |
| } |
| |
| ShillProfileClient::TestInterface* GetShillProfileClient() { |
| return ShillProfileClient::Get()->GetTestInterface(); |
| } |
| |
| void InitializeStandardProfiles() { |
| GetShillProfileClient()->AddProfile(kUser1ProfilePath, kUser1); |
| GetShillProfileClient()->AddProfile( |
| NetworkProfileHandler::GetSharedProfilePath(), |
| std::string() /* no userhash */); |
| } |
| |
| void SetPolicy(::onc::ONCSource onc_source, |
| const std::string& userhash, |
| const std::string& path_to_onc) { |
| base::Value policy = |
| path_to_onc.empty() |
| ? onc::ReadDictionaryFromJson(onc::kEmptyUnencryptedConfiguration) |
| : test_utils::ReadTestDictionaryValue(path_to_onc); |
| |
| onc::Validator validator(true, // error_on_unknown_field |
| true, // error_on_wrong_recommended |
| false, // error_on_missing_field |
| true, // managed_onc |
| true); // log_warnings |
| validator.SetOncSource(onc_source); |
| onc::Validator::Result validation_result; |
| std::unique_ptr<base::DictionaryValue> validated_policy = |
| validator.ValidateAndRepairObject(&onc::kToplevelConfigurationSignature, |
| policy, &validation_result); |
| if (validation_result == onc::Validator::INVALID) { |
| ADD_FAILURE() << "Network configuration invalid."; |
| return; |
| } |
| |
| base::ListValue network_configs; |
| const base::Value* found_network_configs = validated_policy->FindKeyOfType( |
| ::onc::toplevel_config::kNetworkConfigurations, |
| base::Value::Type::LIST); |
| if (found_network_configs) { |
| for (const auto& network_config : found_network_configs->GetList()) { |
| network_configs.Append(network_config.Clone()); |
| } |
| } |
| |
| base::DictionaryValue global_config; |
| const base::Value* found_global_config = validated_policy->FindKeyOfType( |
| ::onc::toplevel_config::kGlobalNetworkConfiguration, |
| base::Value::Type::DICTIONARY); |
| if (found_global_config) { |
| global_config = std::move(*base::DictionaryValue::From( |
| base::Value::ToUniquePtrValue(found_global_config->Clone()))); |
| } |
| |
| managed_network_configuration_handler_->SetPolicy( |
| onc_source, userhash, network_configs, global_config); |
| } |
| |
| void SetUpEntry(const std::string& path_to_shill_json, |
| const std::string& profile_path, |
| const std::string& entry_path) { |
| std::unique_ptr<base::DictionaryValue> entry = |
| test_utils::ReadTestDictionary(path_to_shill_json); |
| GetShillProfileClient()->AddEntry(profile_path, entry_path, *entry); |
| } |
| |
| void ResetManagedNetworkConfigurationHandler() { |
| if (!managed_network_configuration_handler_) |
| return; |
| managed_network_configuration_handler_->RemoveObserver(&policy_observer_); |
| managed_network_configuration_handler_.reset(); |
| } |
| |
| bool PropertiesMatch(const base::Value& v1, const base::Value& v2) { |
| if (v1 == v2) |
| return true; |
| // EXPECT_EQ does not recursively log dictionaries, so use LOG instead. |
| LOG(ERROR) << "v1=" << v1; |
| LOG(ERROR) << "v2=" << v2; |
| return false; |
| } |
| |
| protected: |
| base::test::SingleThreadTaskEnvironment task_environment_; |
| |
| TestNetworkPolicyObserver policy_observer_; |
| std::unique_ptr<MockNetworkStateHandler> network_state_handler_; |
| std::unique_ptr<TestNetworkProfileHandler> network_profile_handler_; |
| std::unique_ptr<NetworkConfigurationHandler> network_configuration_handler_; |
| std::unique_ptr<UIProxyConfigService> ui_proxy_config_service_; |
| std::unique_ptr<ManagedNetworkConfigurationHandlerImpl> |
| managed_network_configuration_handler_; |
| sync_preferences::TestingPrefServiceSyncable user_prefs_; |
| TestingPrefServiceSimple local_state_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ManagedNetworkConfigurationHandlerTest); |
| }; |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, RemoveIrrelevantFields) { |
| InitializeStandardProfiles(); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unconfigured_wifi1.json"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_wifi1_with_redundant_fields.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnconfigured) { |
| InitializeStandardProfiles(); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unconfigured_wifi1.json"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, EnableManagedCredentialsWiFi) { |
| InitializeStandardProfiles(); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_autoconnect_on_unconfigured_wifi1.json"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_wifi1_autoconnect.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, EnableManagedCredentialsVPN) { |
| InitializeStandardProfiles(); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_autoconnect_on_unconfigured_vpn.json"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_vpn_autoconnect.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidVpn); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_EQ(*expected_shill_properties, *properties); |
| } |
| |
| // Ensure that EAP settings for ethernet are matched with the right profile |
| // entry and written to the dedicated EthernetEAP service. |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| SetPolicyManageUnmanagedEthernetEAP) { |
| InitializeStandardProfiles(); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/" |
| "shill_policy_on_unmanaged_ethernet_eap.json"); |
| |
| GetShillServiceClient()->AddService( |
| "eth_entry", std::string() /* guid */, std::string() /* name */, |
| "etherneteap", std::string() /* state */, true /* visible */); |
| GetShillProfileClient()->AddService(kUser1ProfilePath, "eth_entry"); |
| SetUpEntry("policy/shill_unmanaged_ethernet_eap.json", kUser1ProfilePath, |
| "eth_entry"); |
| |
| // Also setup an unrelated WiFi configuration to verify that the right entry |
| // is matched. |
| GetShillServiceClient()->AddService( |
| "wifi_entry", std::string() /* guid */, "wifi1", shill::kTypeWifi, |
| std::string() /* state */, true /* visible */); |
| SetUpEntry("policy/shill_unmanaged_wifi1.json", kUser1ProfilePath, |
| "wifi_entry"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_ethernet_eap.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidEthernetEap); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmodified) { |
| InitializeStandardProfiles(); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, policy_observer()->GetPoliciesAppliedCountAndReset()); |
| |
| SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json", kUser1ProfilePath, |
| "some_entry_path"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, policy_observer()->GetPoliciesAppliedCountAndReset()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, PolicyApplicationRunning) { |
| InitializeStandardProfiles(); |
| |
| EXPECT_FALSE(managed_handler()->IsAnyPolicyApplicationRunning()); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| managed_handler()->SetPolicy( |
| ::onc::ONC_SOURCE_DEVICE_POLICY, |
| std::string(), // no userhash |
| base::ListValue(), // no device network policy |
| base::DictionaryValue()); // no device global config |
| |
| EXPECT_TRUE(managed_handler()->IsAnyPolicyApplicationRunning()); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(managed_handler()->IsAnyPolicyApplicationRunning()); |
| |
| SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json", kUser1ProfilePath, |
| "some_entry_path"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_wifi1_update.onc"); |
| EXPECT_TRUE(managed_handler()->IsAnyPolicyApplicationRunning()); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(managed_handler()->IsAnyPolicyApplicationRunning()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, UpdatePolicyAfterFinished) { |
| InitializeStandardProfiles(); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, policy_observer()->GetPoliciesAppliedCountAndReset()); |
| |
| SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json", kUser1ProfilePath, |
| "some_entry_path"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_wifi1_update.onc"); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, policy_observer()->GetPoliciesAppliedCountAndReset()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, UpdatePolicyBeforeFinished) { |
| InitializeStandardProfiles(); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| // Usually the first call will cause a profile entry to be created, which we |
| // don't fake here. |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_wifi1_update.onc"); |
| |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, policy_observer()->GetPoliciesAppliedCountAndReset()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnmanaged) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_unmanaged_wifi1.json", kUser1ProfilePath, |
| "old_entry_path"); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unmanaged_wifi1.json"); |
| |
| // Before setting policy, old_entry_path should exist. |
| ASSERT_TRUE(GetShillProfileClient()->HasService("old_entry_path")); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Verify old_entry_path is deleted. |
| EXPECT_FALSE(GetShillProfileClient()->HasService("old_entry_path")); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedNewGUID) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_managed_wifi1.json", kUser1ProfilePath, |
| "old_entry_path"); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unmanaged_wifi1.json"); |
| |
| // The passphrase isn't sent again, because it's configured by the user and |
| // Shill doesn't send it on GetProperties calls. |
| expected_shill_properties->RemoveKey(shill::kPassphraseProperty); |
| expected_shill_properties->RemoveKey(shill::kPassphraseRequiredProperty); |
| |
| // Before setting policy, old_entry_path should exist. |
| ASSERT_TRUE(GetShillProfileClient()->HasService("old_entry_path")); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Verify old_entry_path is deleted. |
| EXPECT_FALSE(GetShillProfileClient()->HasService("old_entry_path")); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedVPN) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_managed_vpn.json", kUser1ProfilePath, "entry_path"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_vpn.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidVpn); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary("policy/shill_policy_on_managed_vpn.json"); |
| EXPECT_EQ(*expected_shill_properties, *properties); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| SetPolicyUpdateManagedVPNOpenVPNPlusUi) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_managed_vpn.json", kUser1ProfilePath, "entry_path"); |
| |
| // Apply a policy that does not provide an authenticaiton type. |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_vpn_no_auth.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Apply additional configuration (e.g. from the UI). This includes password |
| // and OTP which should be allowed when authentication type is not explicitly |
| // set. See https://crbug.com/817617 for details. |
| const NetworkState* network_state = |
| network_state_handler_->GetNetworkStateFromGuid(kTestGuidVpn); |
| ASSERT_TRUE(network_state); |
| std::unique_ptr<base::DictionaryValue> ui_config = |
| test_utils::ReadTestDictionary("policy/policy_vpn_ui.json"); |
| managed_network_configuration_handler_->SetProperties( |
| network_state->path(), *ui_config, base::DoNothing(), |
| base::BindOnce(&ErrorCallback)); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidVpn); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_managed_vpn_plus_ui.json"); |
| EXPECT_EQ(*expected_shill_properties, *properties); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| SetPolicyUpdateManagedVPNL2TPIPsecPlusUi) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_managed_vpn_ipsec.json", kUser1ProfilePath, |
| "entry_path"); |
| |
| // Apply the VPN L2TP-IPsec policy that will be updated. |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_vpn_ipsec.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Update the VPN L2TP-IPsec policy. |
| const NetworkState* network_state = |
| network_state_handler_->GetNetworkStateFromGuid(kTestGuidVpn); |
| ASSERT_TRUE(network_state); |
| std::unique_ptr<base::DictionaryValue> ui_config = |
| test_utils::ReadTestDictionary("policy/policy_vpn_ipsec_ui.json"); |
| managed_network_configuration_handler_->SetProperties( |
| network_state->path(), *ui_config, base::DoNothing(), |
| base::BindOnce(&ErrorCallback)); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Get shill service properties after the update. |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidVpn); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_managed_vpn_ipsec_plus_ui.json"); |
| EXPECT_EQ(*expected_shill_properties, *properties); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| SetPolicyUpdateManagedVPNNoUserAuthType) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_managed_vpn.json", kUser1ProfilePath, "entry_path"); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary("policy/shill_policy_on_managed_vpn.json"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_vpn_no_user_auth_type.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidVpn); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_EQ(*expected_shill_properties, *properties); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyReapplyToManaged) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json", kUser1ProfilePath, |
| "old_entry_path"); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unmanaged_wifi1.json"); |
| |
| // The passphrase isn't sent again, because it's configured by the user and |
| // Shill doesn't send it on GetProperties calls. |
| expected_shill_properties->RemoveKey(shill::kPassphraseProperty); |
| expected_shill_properties->RemoveKey(shill::kPassphraseRequiredProperty); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| { |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| // If we apply the policy again, without change, then the Shill profile will |
| // not be modified. |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| { |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUnmanageManaged) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_policy_on_unmanaged_wifi1.json", kUser1ProfilePath, |
| "old_entry_path"); |
| |
| // Before setting policy, old_entry_path should exist. |
| ASSERT_TRUE(GetShillProfileClient()->HasService("old_entry_path")); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| std::string() /* path_to_onc */); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Verify old_entry_path is deleted. |
| EXPECT_FALSE(GetShillProfileClient()->HasService("old_entry_path")); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetEmptyPolicyIgnoreUnmanaged) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_unmanaged_wifi1.json", kUser1ProfilePath, |
| "old_entry_path"); |
| |
| // Before setting policy, old_entry_path should exist. |
| ASSERT_TRUE(GetShillProfileClient()->HasService("old_entry_path")); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| std::string() /* path_to_onc */); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Verify old_entry_path is kept. |
| EXPECT_TRUE(GetShillProfileClient()->HasService("old_entry_path")); |
| EXPECT_EQ(1, policy_observer()->GetPoliciesAppliedCountAndReset()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmanaged) { |
| InitializeStandardProfiles(); |
| SetUpEntry("policy/shill_unmanaged_wifi2.json", kUser1ProfilePath, |
| "wifi2_entry_path"); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unconfigured_wifi1.json"); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, AutoConnectDisallowed) { |
| InitializeStandardProfiles(); |
| |
| // Setup an unmanaged network. |
| SetUpEntry("policy/shill_unmanaged_wifi2.json", kUser1ProfilePath, |
| "wifi2_entry_path"); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_disallow_autoconnect_on_unmanaged_wifi2.json"); |
| |
| // Apply the user policy with global autoconnect config and expect that |
| // autoconnect is disabled in the network's profile entry. |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_allow_only_policy_networks_to_autoconnect.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string wifi2_service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidUnmanagedWifi2); |
| ASSERT_FALSE(wifi2_service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(wifi2_service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_TRUE(PropertiesMatch(*expected_shill_properties, *properties)); |
| |
| // Verify that GetManagedProperties correctly augments the properties with the |
| // global config from the user policy. |
| // GetManagedProperties requires the device policy to be set or explicitly |
| // unset. |
| managed_handler()->SetPolicy( |
| ::onc::ONC_SOURCE_DEVICE_POLICY, |
| std::string(), // no userhash |
| base::ListValue(), // no device network policy |
| base::DictionaryValue()); // no device global config |
| |
| base::RunLoop get_properties_run_loop; |
| std::unique_ptr<base::DictionaryValue> dictionary; |
| managed_handler()->GetManagedProperties( |
| kUser1, wifi2_service_path, |
| base::BindOnce( |
| [](std::unique_ptr<base::DictionaryValue>* dictionary_out, |
| base::RepeatingClosure quit_closure, |
| const std::string& service_path, |
| base::Optional<base::Value> dictionary, |
| base::Optional<std::string> error) { |
| if (dictionary) { |
| *dictionary_out = base::DictionaryValue::From( |
| base::Value::ToUniquePtrValue(std::move(*dictionary))); |
| } else { |
| FAIL(); |
| } |
| quit_closure.Run(); |
| }, |
| &dictionary, get_properties_run_loop.QuitClosure())); |
| |
| get_properties_run_loop.Run(); |
| |
| ASSERT_TRUE(dictionary.get()); |
| std::unique_ptr<base::DictionaryValue> expected_managed_onc = |
| test_utils::ReadTestDictionary( |
| "policy/" |
| "managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc"); |
| EXPECT_TRUE(PropertiesMatch(*expected_managed_onc, *dictionary)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, LateProfileLoading) { |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::unique_ptr<base::DictionaryValue> expected_shill_properties = |
| test_utils::ReadTestDictionary( |
| "policy/shill_policy_on_unconfigured_wifi1.json"); |
| |
| InitializeStandardProfiles(); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(service_path.empty()); |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(service_path); |
| ASSERT_TRUE(properties); |
| EXPECT_THAT(*properties, DictionaryHasValues(*expected_shill_properties)); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| ShutdownDuringPolicyApplication) { |
| InitializeStandardProfiles(); |
| |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| |
| // Reset the network configuration manager after setting policy and before |
| // calling RunUntilIdle to simulate shutdown during policy application. |
| ResetManagedNetworkConfigurationHandler(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| AllowOnlyPolicyNetworksToConnect) { |
| InitializeStandardProfiles(); |
| |
| // Check transfer to NetworkStateHandler |
| EXPECT_CALL( |
| *network_state_handler_, |
| UpdateBlockedWifiNetworks(true, false, std::vector<std::string>())) |
| .Times(1); |
| |
| // Set 'AllowOnlyPolicyNetworksToConnect' policy and a random user policy. |
| SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY, std::string(), |
| "policy/policy_allow_only_policy_networks_to_connect.onc"); |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Check ManagedNetworkConfigurationHandler policy accessors. |
| EXPECT_TRUE(managed_handler()->AllowOnlyPolicyNetworksToConnect()); |
| EXPECT_FALSE( |
| managed_handler()->AllowOnlyPolicyNetworksToConnectIfAvailable()); |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToAutoconnect()); |
| EXPECT_TRUE(managed_handler()->GetBlockedHexSSIDs().empty()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| AllowOnlyPolicyNetworksToConnectIfAvailable) { |
| InitializeStandardProfiles(); |
| |
| // Check transfer to NetworkStateHandler |
| EXPECT_CALL( |
| *network_state_handler_, |
| UpdateBlockedWifiNetworks(false, true, std::vector<std::string>())) |
| .Times(1); |
| |
| // Set 'AllowOnlyPolicyNetworksToConnect' policy and a random user policy. |
| SetPolicy( |
| ::onc::ONC_SOURCE_DEVICE_POLICY, std::string(), |
| "policy/policy_allow_only_policy_networks_to_connect_if_available.onc"); |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Check ManagedNetworkConfigurationHandler policy accessors. |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToConnect()); |
| EXPECT_TRUE(managed_handler()->AllowOnlyPolicyNetworksToConnectIfAvailable()); |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToAutoconnect()); |
| EXPECT_TRUE(managed_handler()->GetBlockedHexSSIDs().empty()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, |
| AllowOnlyPolicyNetworksToAutoconnect) { |
| InitializeStandardProfiles(); |
| |
| // Check transfer to NetworkStateHandler |
| EXPECT_CALL( |
| *network_state_handler_, |
| UpdateBlockedWifiNetworks(false, false, std::vector<std::string>())) |
| .Times(1); |
| |
| // Set 'AllowOnlyPolicyNetworksToAutoconnect' policy and a random user policy. |
| SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY, std::string(), |
| "policy/policy_allow_only_policy_networks_to_autoconnect.onc"); |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Check ManagedNetworkConfigurationHandler policy accessors. |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToConnect()); |
| EXPECT_FALSE( |
| managed_handler()->AllowOnlyPolicyNetworksToConnectIfAvailable()); |
| EXPECT_TRUE(managed_handler()->AllowOnlyPolicyNetworksToAutoconnect()); |
| EXPECT_TRUE(managed_handler()->GetBlockedHexSSIDs().empty()); |
| } |
| |
| // Test deprecated BlacklistedHexSSIDs property. |
| TEST_F(ManagedNetworkConfigurationHandlerTest, GetBlacklistedHexSSIDs) { |
| InitializeStandardProfiles(); |
| std::vector<std::string> blocked = {"476F6F676C65477565737450534B"}; |
| |
| // Check transfer to NetworkStateHandler |
| EXPECT_CALL(*network_state_handler_, |
| UpdateBlockedWifiNetworks(false, false, blocked)) |
| .Times(1); |
| |
| // Set 'BlacklistedHexSSIDs' policy and a random user policy. |
| SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY, std::string(), |
| "policy/policy_deprecated_blacklisted_hex_ssids.onc"); |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Check ManagedNetworkConfigurationHandler policy accessors. |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToConnect()); |
| EXPECT_FALSE( |
| managed_handler()->AllowOnlyPolicyNetworksToConnectIfAvailable()); |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToAutoconnect()); |
| EXPECT_EQ(blocked, managed_handler()->GetBlockedHexSSIDs()); |
| } |
| |
| TEST_F(ManagedNetworkConfigurationHandlerTest, GetBlockedHexSSIDs) { |
| InitializeStandardProfiles(); |
| std::vector<std::string> blocked = {"476F6F676C65477565737450534B"}; |
| |
| // Check transfer to NetworkStateHandler |
| EXPECT_CALL(*network_state_handler_, |
| UpdateBlockedWifiNetworks(false, false, blocked)) |
| .Times(1); |
| |
| // Set 'BlockedHexSSIDs' policy and a random user policy. |
| SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY, std::string(), |
| "policy/policy_blocked_hex_ssids.onc"); |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Check ManagedNetworkConfigurationHandler policy accessors. |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToConnect()); |
| EXPECT_FALSE( |
| managed_handler()->AllowOnlyPolicyNetworksToConnectIfAvailable()); |
| EXPECT_FALSE(managed_handler()->AllowOnlyPolicyNetworksToAutoconnect()); |
| EXPECT_EQ(blocked, managed_handler()->GetBlockedHexSSIDs()); |
| } |
| |
| // Proxy settings can come from different sources. Proxy enforced by user policy |
| // (provided by kProxy prefence) should have precedence over configurations set |
| // by ONC policy. This test verifies that the order of preference is respected. |
| TEST_F(ManagedNetworkConfigurationHandlerTest, ActiveProxySettingsPreference) { |
| // Configure network. |
| InitializeStandardProfiles(); |
| GetShillServiceClient()->AddService( |
| "wifi_entry", std::string() /* guid */, "wifi1", shill::kTypeWifi, |
| std::string() /* state */, true /* visible */); |
| |
| // Use proxy configured network. |
| SetPolicy(::onc::ONC_SOURCE_USER_POLICY, kUser1, |
| "policy/policy_wifi1_proxy.onc"); |
| base::RunLoop().RunUntilIdle(); |
| |
| std::string wifi_service_path = |
| GetShillServiceClient()->FindServiceMatchingGUID(kTestGuidManagedWifi); |
| ASSERT_FALSE(wifi_service_path.empty()); |
| |
| const base::Value* properties = |
| GetShillServiceClient()->GetServiceProperties(wifi_service_path); |
| ASSERT_TRUE(properties); |
| |
| managed_handler()->SetPolicy( |
| ::onc::ONC_SOURCE_DEVICE_POLICY, |
| std::string(), // no userhash |
| base::ListValue(), // no device network policy |
| base::DictionaryValue()); // no device global config |
| |
| std::unique_ptr<base::DictionaryValue> dictionary_before_pref, |
| dictionary_after_pref; |
| |
| base::RunLoop get_initial_properties_run_loop; |
| // Get properties and verify that proxy is used. |
| managed_handler()->GetManagedProperties( |
| kUser1, wifi_service_path, |
| base::BindOnce( |
| [](std::unique_ptr<base::DictionaryValue>* dictionary_out, |
| base::RepeatingClosure quit_closure, |
| const std::string& service_path, |
| base::Optional<base::Value> dictionary, |
| base::Optional<std::string> error) { |
| if (dictionary) { |
| *dictionary_out = base::DictionaryValue::From( |
| base::Value::ToUniquePtrValue(std::move(*dictionary))); |
| } else { |
| ADD_FAILURE() << error.value_or("Failed"); |
| } |
| quit_closure.Run(); |
| }, |
| &dictionary_before_pref, |
| get_initial_properties_run_loop.QuitClosure())); |
| |
| get_initial_properties_run_loop.Run(); |
| |
| std::string policy_before_pref = |
| dictionary_before_pref->FindPath("ProxySettings.Type.UserPolicy") |
| ->GetString(); |
| ASSERT_TRUE(dictionary_before_pref.get()); |
| ASSERT_EQ(policy_before_pref, "PAC"); |
| |
| // Set pref not to use proxy. |
| base::Value policy_prefs_config = ProxyConfigDictionary::CreateDirect(); |
| user_prefs_.SetManagedPref( |
| proxy_config::prefs::kProxy, |
| base::Value::ToUniquePtrValue(std::move(policy_prefs_config))); |
| |
| base::RunLoop get_merged_properties_run_loop; |
| // Fetch managed properties after preference is set. |
| managed_handler()->GetManagedProperties( |
| kUser1, wifi_service_path, |
| base::BindOnce( |
| [](std::unique_ptr<base::DictionaryValue>* dictionary_out, |
| base::RepeatingClosure quit_closure, |
| const std::string& service_path, |
| base::Optional<base::Value> dictionary, |
| base::Optional<std::string> error) { |
| if (dictionary) { |
| *dictionary_out = base::DictionaryValue::From( |
| base::Value::ToUniquePtrValue(std::move(*dictionary))); |
| } else { |
| ADD_FAILURE() << error.value_or("Failed"); |
| } |
| quit_closure.Run(); |
| }, |
| &dictionary_after_pref, |
| get_merged_properties_run_loop.QuitClosure())); |
| |
| get_merged_properties_run_loop.Run(); |
| |
| std::string policy_after_pref = |
| dictionary_after_pref->FindPath("ProxySettings.Type.UserPolicy") |
| ->GetString(); |
| |
| ASSERT_TRUE(dictionary_after_pref.get()); |
| ASSERT_NE(dictionary_before_pref, dictionary_after_pref); |
| ASSERT_EQ(policy_after_pref, "Direct"); |
| } |
| |
| } // namespace chromeos |