Commit adcc8b42 authored by Pavol Marko's avatar Pavol Marko Committed by Commit Bot

Signal network policy application done when it's actually done

Wait for network policy application to actually finish before signaling
that it's done. Network policy application is only finished when the
changes sent to shill have been pulled back from shill and are now
reflected in NetworkState objects. This is important because code
evaluating e.g. the OnlyAllowPolicyNetworksToAutoConnect policy uses
NetworkState objects to decide whether a network is policy-managed or
not.

Bug: 936677, 943102
Test: browsertest will be added in a follow-up CL to keep this small.
Change-Id: I734bc75eb8422e934b20cb592ca3fc5c211779b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1539839
Commit-Queue: Pavol Marko <pmarko@chromium.org>
Reviewed-by: default avatarAlexander Hendrich <hendrich@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#667328}
parent f877c4ff
...@@ -127,6 +127,7 @@ class AutoConnectHandlerTest : public testing::Test { ...@@ -127,6 +127,7 @@ class AutoConnectHandlerTest : public testing::Test {
NetworkCertLoader::ForceHardwareBackedForTesting(); NetworkCertLoader::ForceHardwareBackedForTesting();
LoginState::Initialize(); LoginState::Initialize();
LoginState::Get()->set_always_logged_in(false);
network_config_handler_.reset( network_config_handler_.reset(
NetworkConfigurationHandler::InitializeForTest( NetworkConfigurationHandler::InitializeForTest(
...@@ -357,12 +358,14 @@ TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) { ...@@ -357,12 +358,14 @@ TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) {
SetupPolicy(std::string(), // no device policy SetupPolicy(std::string(), // no device policy
base::DictionaryValue(), // no global config base::DictionaryValue(), // no global config
false); // load as device policy false); // load as device policy
EXPECT_EQ(0, test_observer_->num_auto_connect_events());
LoginToRegularUser(); LoginToRegularUser();
StartNetworkCertLoader();
SetupPolicy(kPolicyCertPattern, SetupPolicy(kPolicyCertPattern,
base::DictionaryValue(), // no global config base::DictionaryValue(), // no global config
true); // load as user policy true); // load as user policy
EXPECT_EQ(2, test_observer_->num_auto_connect_events()); StartNetworkCertLoader();
EXPECT_EQ(1, test_observer_->num_auto_connect_events());
EXPECT_EQ(AutoConnectHandler::AUTO_CONNECT_REASON_LOGGED_IN | EXPECT_EQ(AutoConnectHandler::AUTO_CONNECT_REASON_LOGGED_IN |
AutoConnectHandler::AUTO_CONNECT_REASON_POLICY_APPLIED | AutoConnectHandler::AUTO_CONNECT_REASON_POLICY_APPLIED |
AutoConnectHandler::AUTO_CONNECT_REASON_CERTIFICATE_RESOLVED, AutoConnectHandler::AUTO_CONNECT_REASON_CERTIFICATE_RESOLVED,
...@@ -382,7 +385,7 @@ TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) { ...@@ -382,7 +385,7 @@ TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) {
EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0")); EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1")); EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
EXPECT_EQ(3, test_observer_->num_auto_connect_events()); EXPECT_EQ(2, test_observer_->num_auto_connect_events());
EXPECT_EQ(AutoConnectHandler::AUTO_CONNECT_REASON_LOGGED_IN | EXPECT_EQ(AutoConnectHandler::AUTO_CONNECT_REASON_LOGGED_IN |
AutoConnectHandler::AUTO_CONNECT_REASON_POLICY_APPLIED | AutoConnectHandler::AUTO_CONNECT_REASON_POLICY_APPLIED |
AutoConnectHandler::AUTO_CONNECT_REASON_CERTIFICATE_RESOLVED, AutoConnectHandler::AUTO_CONNECT_REASON_CERTIFICATE_RESOLVED,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/guid.h" #include "base/guid.h"
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
...@@ -72,12 +73,15 @@ void InvokeErrorCallback(const std::string& service_path, ...@@ -72,12 +73,15 @@ void InvokeErrorCallback(const std::string& service_path,
error_callback, service_path, error_name, error_msg); error_callback, service_path, error_name, error_msg);
} }
void LogErrorWithDict(const base::Location& from_where, void LogErrorWithDictAndCallCallback(
const std::string& error_name, base::OnceClosure callback,
std::unique_ptr<base::DictionaryValue> error_data) { const base::Location& from_where,
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data) {
device_event_log::AddEntry(from_where.file_name(), from_where.line_number(), device_event_log::AddEntry(from_where.file_name(), from_where.line_number(),
device_event_log::LOG_TYPE_NETWORK, device_event_log::LOG_TYPE_NETWORK,
device_event_log::LOG_LEVEL_ERROR, error_name); device_event_log::LOG_LEVEL_ERROR, error_name);
std::move(callback).Run();
} }
const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies, const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies,
...@@ -677,19 +681,26 @@ void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved( ...@@ -677,19 +681,26 @@ void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved(
} }
void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy( void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy(
const base::DictionaryValue& shill_properties) { const base::DictionaryValue& shill_properties,
base::OnceClosure callback) {
base::RepeatingClosure adapted_callback =
base::AdaptCallbackForRepeating(std::move(callback));
network_configuration_handler_->CreateShillConfiguration( network_configuration_handler_->CreateShillConfiguration(
shill_properties, shill_properties,
base::Bind( base::BindRepeating(
&ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
weak_ptr_factory_.GetWeakPtr()), weak_ptr_factory_.GetWeakPtr(), adapted_callback),
base::Bind(&LogErrorWithDict, FROM_HERE)); base::BindRepeating(&LogErrorWithDictAndCallCallback, adapted_callback,
FROM_HERE));
} }
void ManagedNetworkConfigurationHandlerImpl:: void ManagedNetworkConfigurationHandlerImpl::
UpdateExistingConfigurationWithPropertiesFromPolicy( UpdateExistingConfigurationWithPropertiesFromPolicy(
const base::DictionaryValue& existing_properties, const base::DictionaryValue& existing_properties,
const base::DictionaryValue& new_properties) { const base::DictionaryValue& new_properties,
base::OnceClosure callback) {
base::RepeatingClosure adapted_callback =
base::AdaptCallbackForRepeating(std::move(callback));
base::DictionaryValue shill_properties; base::DictionaryValue shill_properties;
std::string profile; std::string profile;
...@@ -716,10 +727,11 @@ void ManagedNetworkConfigurationHandlerImpl:: ...@@ -716,10 +727,11 @@ void ManagedNetworkConfigurationHandlerImpl::
network_configuration_handler_->CreateShillConfiguration( network_configuration_handler_->CreateShillConfiguration(
shill_properties, shill_properties,
base::Bind( base::BindRepeating(
&ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork,
weak_ptr_factory_.GetWeakPtr()), weak_ptr_factory_.GetWeakPtr(), adapted_callback),
base::Bind(&LogErrorWithDict, FROM_HERE)); base::BindRepeating(&LogErrorWithDictAndCallCallback, adapted_callback,
FROM_HERE));
} }
void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied( void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied(
...@@ -949,12 +961,21 @@ void ManagedNetworkConfigurationHandlerImpl::Init( ...@@ -949,12 +961,21 @@ void ManagedNetworkConfigurationHandlerImpl::Init(
} }
void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork( void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork(
base::OnceClosure callback,
const std::string& service_path, const std::string& service_path,
const std::string& guid) { const std::string& guid) {
if (service_path.empty()) DCHECK(!service_path.empty());
return;
// When this is called, the policy has been fully applied and is reflected in
// NetworkStateHandler, so it is safe to notify obserers.
// Notifying observers is the last step of policy application to
// |service_path|.
for (auto& observer : observers_) for (auto& observer : observers_)
observer.PolicyAppliedToNetwork(service_path); observer.PolicyAppliedToNetwork(service_path);
// Inform the caller that has requested policy application that it has
// finished.
std::move(callback).Run();
} }
// Get{Managed}Properties helpers // Get{Managed}Properties helpers
......
...@@ -116,11 +116,13 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) ManagedNetworkConfigurationHandlerImpl ...@@ -116,11 +116,13 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) ManagedNetworkConfigurationHandlerImpl
// PolicyApplicator::ConfigurationHandler overrides // PolicyApplicator::ConfigurationHandler overrides
void CreateConfigurationFromPolicy( void CreateConfigurationFromPolicy(
const base::DictionaryValue& shill_properties) override; const base::DictionaryValue& shill_properties,
base::OnceClosure callback) override;
void UpdateExistingConfigurationWithPropertiesFromPolicy( void UpdateExistingConfigurationWithPropertiesFromPolicy(
const base::DictionaryValue& existing_properties, const base::DictionaryValue& existing_properties,
const base::DictionaryValue& new_properties) override; const base::DictionaryValue& new_properties,
base::OnceClosure callback) override;
void OnPoliciesApplied(const NetworkProfile& profile) override; void OnPoliciesApplied(const NetworkProfile& profile) override;
...@@ -176,7 +178,10 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) ManagedNetworkConfigurationHandlerImpl ...@@ -176,7 +178,10 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) ManagedNetworkConfigurationHandlerImpl
// user or device policies. // user or device policies.
const Policies* GetPoliciesForProfile(const NetworkProfile& profile) const; const Policies* GetPoliciesForProfile(const NetworkProfile& profile) const;
void OnPolicyAppliedToNetwork(const std::string& service_path, // Called when a policy identified by |guid| has been applied to the network
// identified by |service_path|. Notifies observers and calls |callback|.
void OnPolicyAppliedToNetwork(base::OnceClosure callback,
const std::string& service_path,
const std::string& guid); const std::string& guid);
// Helper method to append associated Device properties to |properties|. // Helper method to append associated Device properties to |properties|.
......
...@@ -523,10 +523,8 @@ void NetworkConfigurationHandler::ConfigurationCompleted( ...@@ -523,10 +523,8 @@ void NetworkConfigurationHandler::ConfigurationCompleted(
// |configure_callbacks_| will get triggered when NetworkStateHandler // |configure_callbacks_| will get triggered when NetworkStateHandler
// notifies this that a state list update has occurred. |service_path| // notifies this that a state list update has occurred. |service_path|
// is unique per configuration. In the unlikely case that an existing // is unique per configuration.
// configuration is reconfigured twice without a NetworkStateHandler update, configure_callbacks_.insert(std::make_pair(service_path.value(), callback));
// (the UI should prevent that) the first callback will not get called.
configure_callbacks_[service_path.value()] = callback;
} }
void NetworkConfigurationHandler::ProfileEntryDeleterCompleted( void NetworkConfigurationHandler::ProfileEntryDeleterCompleted(
......
...@@ -91,6 +91,8 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConfigurationHandler ...@@ -91,6 +91,8 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConfigurationHandler
// Creates a network with the given |properties| in the specified Shill // Creates a network with the given |properties| in the specified Shill
// profile, and returns the new service_path to |callback| if successful. // profile, and returns the new service_path to |callback| if successful.
// |callback| will only be called after the property update has been reflected
// in NetworkStateHandler.
// kProfileProperty must be set in |properties|. This may also be used to // kProfileProperty must be set in |properties|. This may also be used to
// update an existing matching configuration, see Shill documentation for // update an existing matching configuration, see Shill documentation for
// Manager.ConfigureServiceForProfile. NOTE: Normally // Manager.ConfigureServiceForProfile. NOTE: Normally
...@@ -226,8 +228,9 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConfigurationHandler ...@@ -226,8 +228,9 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConfigurationHandler
profile_entry_deleters_; profile_entry_deleters_;
// Map of configuration callbacks to run once the service becomes available // Map of configuration callbacks to run once the service becomes available
// in the NetworkStateHandler cache. // in the NetworkStateHandler cache. This is a multimap because there can be
std::map<std::string, network_handler::ServiceResultCallback> // multiple callbacks for the same network that have to be notified.
std::multimap<std::string, network_handler::ServiceResultCallback>
configure_callbacks_; configure_callbacks_;
base::ObserverList<NetworkConfigurationObserver, true>::Unchecked observers_; base::ObserverList<NetworkConfigurationObserver, true>::Unchecked observers_;
......
This diff is collapsed.
...@@ -11,12 +11,15 @@ ...@@ -11,12 +11,15 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/values.h" #include "base/values.h"
#include "chromeos/network/network_profile.h" #include "chromeos/network/network_profile.h"
namespace chromeos { namespace chromeos {
class NetworkUIData;
// This class compares (entry point is Run()) |modified_policies| with the // This class compares (entry point is Run()) |modified_policies| with the
// existing entries in the provided Shill profile |profile|. It fetches all // existing entries in the provided Shill profile |profile|. It fetches all
...@@ -31,13 +34,18 @@ class PolicyApplicator { ...@@ -31,13 +34,18 @@ class PolicyApplicator {
// Write the new configuration with the properties |shill_properties| to // Write the new configuration with the properties |shill_properties| to
// Shill. This configuration comes from a policy. Any conflicting or // Shill. This configuration comes from a policy. Any conflicting or
// existing configuration for the same network will have been removed // existing configuration for the same network will have been removed
// before. // before. |callback| will be called after the configuration update has been
// reflected in NetworkStateHandler, or on error.
virtual void CreateConfigurationFromPolicy( virtual void CreateConfigurationFromPolicy(
const base::DictionaryValue& shill_properties) = 0; const base::DictionaryValue& shill_properties,
base::OnceClosure callback) = 0;
// before. |callback| will be called after the configuration update has been
// reflected in NetworkStateHandler, or on error.
virtual void UpdateExistingConfigurationWithPropertiesFromPolicy( virtual void UpdateExistingConfigurationWithPropertiesFromPolicy(
const base::DictionaryValue& existing_properties, const base::DictionaryValue& existing_properties,
const base::DictionaryValue& new_properties) = 0; const base::DictionaryValue& new_properties,
base::OnceClosure callback) = 0;
// Called after all policies for |profile| were applied. At this point, the // Called after all policies for |profile| were applied. At this point, the
// list of networks should be updated. // list of networks should be updated.
...@@ -51,23 +59,18 @@ class PolicyApplicator { ...@@ -51,23 +59,18 @@ class PolicyApplicator {
std::map<std::string, std::unique_ptr<base::DictionaryValue>>; std::map<std::string, std::unique_ptr<base::DictionaryValue>>;
// |handler| must outlive this object. // |handler| must outlive this object.
// |modified_policies| must not be NULL and will be empty afterwards. // |modified_policy_guids| must not be nullptr and will be empty afterwards.
PolicyApplicator(const NetworkProfile& profile, PolicyApplicator(const NetworkProfile& profile,
const GuidToPolicyMap& all_policies, const GuidToPolicyMap& all_policies,
const base::DictionaryValue& global_network_config, const base::DictionaryValue& global_network_config,
ConfigurationHandler* handler, ConfigurationHandler* handler,
std::set<std::string>* modified_policies); std::set<std::string>* modified_policy_guids);
~PolicyApplicator(); ~PolicyApplicator();
void Run(); void Run();
private: private:
// Removes |entry| from the list of pending profile entries.
// If all entries were processed, applies the remaining policies and notifies
// |handler_|.
void ProfileEntryFinished(const std::string& entry);
// Called with the properties of the profile |profile_|. Requests the // Called with the properties of the profile |profile_|. Requests the
// properties of each entry, which are processed by GetEntryCallback. // properties of each entry, which are processed by GetEntryCallback.
void GetProfilePropertiesCallback( void GetProfilePropertiesCallback(
...@@ -84,31 +87,68 @@ class PolicyApplicator { ...@@ -84,31 +87,68 @@ class PolicyApplicator {
const std::string& error_name, const std::string& error_name,
const std::string& error_message); const std::string& error_message);
// Applies |new_policy| for |entry|.
// |entry_properties| are the current properties for the entry. |ui_data| is
// the NetworkUIData extracted from |entry_properties| and is passed so it
// doesn't have to be re-extracted. |old_guid| is the current GUID of the
// entry and may be empty.
// |callback| will be called when policy application for |entry| has finished.
void ApplyNewPolicy(const std::string& entry,
const base::Value& entry_properties,
std::unique_ptr<NetworkUIData> ui_data,
const std::string& old_guid,
const std::string& new_guid,
const base::Value& new_policy,
base::OnceClosure callback);
// Applies the global network policy (if any) on |entry|,
// |entry_properties|} are the current properties for the entry.
// |callback| will be called when policy application for |entry| has finished
// or immediately if no global network policy is present.
void ApplyGlobalPolicyOnUnmanagedEntry(
const std::string& entry,
const base::DictionaryValue& entry_properties,
base::OnceClosure callback);
// Sends Shill the command to delete profile entry |entry| from |profile_|. // Sends Shill the command to delete profile entry |entry| from |profile_|.
void DeleteEntry(const std::string& entry); // |callback| will be called when the profile entry has been deleted in shill.
void DeleteEntry(const std::string& entry, base::OnceClosure callback);
// Applies |shill_dictionary| in shill. |policy_ is the ONC policy blob which
// lead to the policy application. |callback| will be called when policy
// application has finished, i.e. when the policy has been applied in shill
// NetworkStateHandler in chrome has reflected the changes.
void WriteNewShillConfiguration(base::Value shill_dictionary,
base::Value policy,
base::OnceClosure callback);
// Sends the Shill configuration |shill_dictionary| to Shill. If |write_later| // Removes |entry| from the list of pending profile entries.
// is true, the configuration is queued for sending until ~PolicyApplicator. // If all entries were processed, applies the remaining policies and notifies
void WriteNewShillConfiguration(const base::DictionaryValue& shill_dictionary, // |handler_|.
const base::DictionaryValue& policy, void ProfileEntryFinished(const std::string& entry);
bool write_later);
// Creates new entries for all remaining policies, i.e. for which no matching // Creates new entries for all remaining policies, i.e. for which no matching
// Profile entry was found. // Profile entry was found.
// This should only be called if all profile entries were processed. // This should only be called if all profile entries were processed.
void ApplyRemainingPolicies(); void ApplyRemainingPolicies();
// This is called when the remaining policy application for |entry| scheduled
// by ApplyRemainingPolicies has finished.
void RemainingPolicyApplied(const std::string& entry);
// Called after all policies are applied or an error occurred. Notifies // Called after all policies are applied or an error occurred. Notifies
// |handler_|. // |handler_|.
void NotifyConfigurationHandlerAndFinish(); void NotifyConfigurationHandlerAndFinish();
std::set<std::string> remaining_policies_; std::set<std::string> remaining_policy_guids_;
std::set<std::string> pending_get_entry_calls_; std::set<std::string> pending_get_entry_calls_;
ConfigurationHandler* handler_; ConfigurationHandler* handler_;
NetworkProfile profile_; NetworkProfile profile_;
GuidToPolicyMap all_policies_; GuidToPolicyMap all_policies_;
base::DictionaryValue global_network_config_; base::DictionaryValue global_network_config_;
std::vector<std::unique_ptr<base::DictionaryValue>> new_shill_configurations_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PolicyApplicator> weak_ptr_factory_; base::WeakPtrFactory<PolicyApplicator> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PolicyApplicator); DISALLOW_COPY_AND_ASSIGN(PolicyApplicator);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment