Commit 9763fae4 authored by Pavol Marko's avatar Pavol Marko Committed by Commit Bot

Improve PolicyService initialization throttling

Instead of using SetInitializationThrottled(bool), initialization
throttling of a PolicyServiceImpl can only be activated at construction
time using CreateWithInitilizationThrottled and deactivated using
UnthrottleInitialization. This is clearer and guarantees that the state
of the service is consistent even when all PolicyProviders are already
initialized at construction time.

To be able to implement this properly, the meaning of the
|initialization_complete_| variable had to be changed - it can now be
true even when initialization is throttled. Initialization throttling
only means that observers are not notified yet.

Also add unit tests to test the behavior of initialization throttling.

Planned follow-up changes:
(*) Timeout to abort initialization throttling after a few seconds to
    protect against coding error.
(*) UMA stat to track initialization throttling time.

Bug: 982936, 1002066
Test: browser_test still pass, new components_unittests test

Change-Id: I32eb7fbac1746d25ab650ba0969e6cb7a1a22241
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1798324Reviewed-by: default avatarLutz Justen <ljusten@chromium.org>
Commit-Queue: Pavol Marko <pmarko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700174}
parent ffdea4a3
...@@ -92,6 +92,24 @@ class ProxiedPoliciesPropagatedWatcher : PolicyService::ProviderUpdateObserver { ...@@ -92,6 +92,24 @@ class ProxiedPoliciesPropagatedWatcher : PolicyService::ProviderUpdateObserver {
}; };
} // namespace internal } // namespace internal
namespace {
// Returns the PolicyService that holds device-wide policies.
PolicyService* GetDeviceWidePolicyService() {
BrowserPolicyConnectorChromeOS* browser_policy_connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
return browser_policy_connector->GetPolicyService();
}
// Returns the ProxyPolicyProvider which is used to forward primary Profile
// policies into the device-wide PolicyService.
ProxyPolicyProvider* GetProxyPolicyProvider() {
BrowserPolicyConnectorChromeOS* browser_policy_connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
return browser_policy_connector->GetGlobalUserCloudPolicyProvider();
}
} // namespace
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
ProfilePolicyConnector::ProfilePolicyConnector() {} ProfilePolicyConnector::ProfilePolicyConnector() {}
...@@ -174,22 +192,40 @@ void ProfilePolicyConnector::Init( ...@@ -174,22 +192,40 @@ void ProfilePolicyConnector::Init(
} }
#endif #endif
policy_service_ = std::make_unique<PolicyServiceImpl>(policy_providers_);
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
ConfigurationPolicyProvider* user_policy_delegate = nullptr; ConfigurationPolicyProvider* user_policy_delegate_candidate =
if (is_primary_user_) { configuration_policy_provider ? configuration_policy_provider
user_policy_delegate = configuration_policy_provider
? configuration_policy_provider
: special_user_policy_provider_.get(); : special_user_policy_provider_.get();
// Only proxy primary user policies to the device_wide policy service if all
// of the following are true:
// (*) This ProfilePolicyConnector has been created for the primary user.
// (*) There is a policy provider for this profile. Note that for unmanaged
// users, |user_policy_delegate_candidate| will be nullptr.
// (*) The ProxyPolicyProvider is actually used by the device-wide policy
// service. This may not be the case e.g. in tests that use
// bBrowserPolicyConnectorBase::SetPolicyProviderForTesting.
if (is_primary_user_ && user_policy_delegate_candidate &&
GetDeviceWidePolicyService()->HasProvider(GetProxyPolicyProvider())) {
GetProxyPolicyProvider()->SetDelegate(user_policy_delegate_candidate);
// When proxying primary user policies to the device-wide PolicyService,
// delay signaling that initialization is complete until the policies have
// propagated. See CreatePolicyServiceWithInitializationThrottled for
// details.
policy_service_ = CreatePolicyServiceWithInitializationThrottled(
policy_providers_, user_policy_delegate_candidate);
} else {
policy_service_ = std::make_unique<PolicyServiceImpl>(policy_providers_);
} }
if (user_policy_delegate) #else // defined(OS_CHROMEOS)
SetGlobalUserPolicyDelegate(user_policy_delegate); policy_service_ = std::make_unique<PolicyServiceImpl>(policy_providers_);
#endif #endif // defined(OS_CHROMEOS)
} }
void ProfilePolicyConnector::InitForTesting( void ProfilePolicyConnector::InitForTesting(
std::unique_ptr<PolicyService> service) { std::unique_ptr<PolicyService> service) {
DCHECK(!policy_service_);
policy_service_ = std::move(service); policy_service_ = std::move(service);
} }
...@@ -200,7 +236,7 @@ void ProfilePolicyConnector::OverrideIsManagedForTesting(bool is_managed) { ...@@ -200,7 +236,7 @@ void ProfilePolicyConnector::OverrideIsManagedForTesting(bool is_managed) {
void ProfilePolicyConnector::Shutdown() { void ProfilePolicyConnector::Shutdown() {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (is_primary_user_) if (is_primary_user_)
SetGlobalUserPolicyDelegate(nullptr); GetProxyPolicyProvider()->SetDelegate(nullptr);
if (special_user_policy_provider_) if (special_user_policy_provider_)
special_user_policy_provider_->Shutdown(); special_user_policy_provider_->Shutdown();
...@@ -256,41 +292,33 @@ ProfilePolicyConnector::DeterminePolicyProviderForPolicy( ...@@ -256,41 +292,33 @@ ProfilePolicyConnector::DeterminePolicyProviderForPolicy(
} }
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
void ProfilePolicyConnector::SetGlobalUserPolicyDelegate( std::unique_ptr<PolicyService>
ProfilePolicyConnector::CreatePolicyServiceWithInitializationThrottled(
const std::vector<ConfigurationPolicyProvider*>& policy_providers,
ConfigurationPolicyProvider* user_policy_delegate) { ConfigurationPolicyProvider* user_policy_delegate) {
BrowserPolicyConnectorChromeOS* browser_policy_connector = DCHECK(user_policy_delegate);
g_browser_process->platform_part()->browser_policy_connector_chromeos();
PolicyService* device_wide_policy_service =
browser_policy_connector->GetPolicyService();
ProxyPolicyProvider* proxy_policy_provider =
browser_policy_connector->GetGlobalUserCloudPolicyProvider();
// The ProxyPolicyProvider may be available from |browser_policy_connector|
// but not actually used by the |device_wide_policy_service| in tests (e.g. if
// BrowserPolicyConnectorBase::SetPolicyProviderForTesting has been used).
if (!device_wide_policy_service->HasProvider(proxy_policy_provider))
return;
if (!user_policy_delegate) { auto policy_service =
proxy_policy_provider->SetDelegate(nullptr); PolicyServiceImpl::CreateWithThrottledInitialization(policy_providers);
return;
}
policy_service_->SetInitializationThrottled(true);
// base::Unretained is OK for |this| because // base::Unretained is OK for |this| because
// |proxied_policies_propagated_watcher_| is guaranteed not to call its // |proxied_policies_propagated_watcher_| is guaranteed not to call its
// callback after it has been destroyed. // callback after it has been destroyed. base::Unretained is also OK for
// |policy_service.get()| because it will be owned by |*this| and is never
// explicitly destroyed.
proxied_policies_propagated_watcher_ = proxied_policies_propagated_watcher_ =
std::make_unique<internal::ProxiedPoliciesPropagatedWatcher>( std::make_unique<internal::ProxiedPoliciesPropagatedWatcher>(
device_wide_policy_service, proxy_policy_provider, GetDeviceWidePolicyService(), GetProxyPolicyProvider(),
user_policy_delegate, user_policy_delegate,
base::BindOnce(&ProfilePolicyConnector::OnProxiedPoliciesPropagated, base::BindOnce(&ProfilePolicyConnector::OnProxiedPoliciesPropagated,
base::Unretained(this))); base::Unretained(this),
proxy_policy_provider->SetDelegate(user_policy_delegate); base::Unretained(policy_service.get())));
return std::move(policy_service);
} }
void ProfilePolicyConnector::OnProxiedPoliciesPropagated() { void ProfilePolicyConnector::OnProxiedPoliciesPropagated(
policy_service_->SetInitializationThrottled(false); PolicyServiceImpl* policy_service) {
policy_service->UnthrottleInitialization();
// Do not delete |proxied_policies_propagated_watcher_| synchronously, as the // Do not delete |proxied_policies_propagated_watcher_| synchronously, as the
// PolicyService it is observing is expected to be iterating its observer // PolicyService it is observing is expected to be iterating its observer
// list. // list.
......
...@@ -27,6 +27,7 @@ class ProxiedPoliciesPropagatedWatcher; ...@@ -27,6 +27,7 @@ class ProxiedPoliciesPropagatedWatcher;
class CloudPolicyStore; class CloudPolicyStore;
class ConfigurationPolicyProvider; class ConfigurationPolicyProvider;
class PolicyService; class PolicyService;
class PolicyServiceImpl;
class SchemaRegistry; class SchemaRegistry;
class ChromeBrowserPolicyConnector; class ChromeBrowserPolicyConnector;
...@@ -81,22 +82,31 @@ class ProfilePolicyConnector final { ...@@ -81,22 +82,31 @@ class ProfilePolicyConnector final {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// On Chrome OS, primary Profile user policies are forwarded to the // On Chrome OS, primary Profile user policies are forwarded to the
// device-global PolicyService[1] using a ProxyPolicyProvider. This function // device-global PolicyService[1] using a ProxyPolicyProvider.
// sets up that forwarding, using |user_policy_delegate| as the policy source. // When that is done, signaling that |policy_service_| is initialized should
// It also delays signaling that |policy_service_| is initialized until the // be delayed until the policies provided by |user_policy_delegate| have
// policies provided by |user_policy_delegate| have propagated to the // propagated to the device-wide PolicyService[1]. This is done so that code
// device-wide PolicyService[1]. This is done so that code that runs early on // that runs early on Profile initialization can rely on the device-wide
// Profile initialization can rely on the device-wide PolicyService[1] and // PolicyService[1] and local state Preferences[2] respecting the proxied
// local state Preferences[2] respecting the proxied primary user policies. // primary user policies.
//
// This function starts watching for the propagation to happen by creating a
// |ProxiedPoliciesPropagatedWatcher| and creates a PolicyService that
// only signals that it is initilalized when the
// |proxied_policies_propagated_watcher_| has fired.
// //
// [1] i.e. g_browser_process->policy_service() // [1] i.e. g_browser_process->policy_service()
// [2] i.e. g_browser_process->local_state() // [2] i.e. g_browser_process->local_state()
void SetGlobalUserPolicyDelegate( std::unique_ptr<PolicyService> CreatePolicyServiceWithInitializationThrottled(
const std::vector<ConfigurationPolicyProvider*>& policy_providers,
ConfigurationPolicyProvider* user_policy_delegate); ConfigurationPolicyProvider* user_policy_delegate);
// Called when primary user policies that are proxied to the device-wide // Called when primary user policies that are proxied to the device-wide
// PolicyService have propagated. // PolicyService have propagated.
void OnProxiedPoliciesPropagated(); // |policy_service| is passed here because UnthrottleInitialization is
// implemented on PolicyServiceImpl, but the |policy_service_| class member is
// a PolicyService for testability.
void OnProxiedPoliciesPropagated(PolicyServiceImpl* policy_service);
// Some of the user policy configuration affects browser global state, and // Some of the user policy configuration affects browser global state, and
// can only come from one Profile. |is_primary_user_| is true if this // can only come from one Profile. |is_primary_user_| is true if this
......
...@@ -45,7 +45,6 @@ class MockPolicyService : public PolicyService { ...@@ -45,7 +45,6 @@ class MockPolicyService : public PolicyService {
MOCK_CONST_METHOD1(GetPolicies, const PolicyMap&(const PolicyNamespace&)); MOCK_CONST_METHOD1(GetPolicies, const PolicyMap&(const PolicyNamespace&));
MOCK_CONST_METHOD1(IsInitializationComplete, bool(PolicyDomain domain)); MOCK_CONST_METHOD1(IsInitializationComplete, bool(PolicyDomain domain));
MOCK_METHOD1(RefreshPolicies, void(const base::Closure&)); MOCK_METHOD1(RefreshPolicies, void(const base::Closure&));
MOCK_METHOD1(SetInitializationThrottled, void(bool initialization_throttled));
}; };
} // namespace policy } // namespace policy
......
...@@ -97,16 +97,6 @@ class POLICY_EXPORT PolicyService { ...@@ -97,16 +97,6 @@ class POLICY_EXPORT PolicyService {
// |callback| is invoked once every source has reloaded its policies, and // |callback| is invoked once every source has reloaded its policies, and
// GetPolicies() is guaranteed to return the updated values at that point. // GetPolicies() is guaranteed to return the updated values at that point.
virtual void RefreshPolicies(const base::Closure& callback) = 0; virtual void RefreshPolicies(const base::Closure& callback) = 0;
// When |initialization_throttled| is set to true, this PolicyService should
// return false in IsInitializationComplete for all domains and should not
// notify observers that it has initialized any domain. When
// |initialization_throttled| is set to false and the
// OnPolicyServiceInitialized notifications for some domains have not been
// sent out due to a previous call to this function with
// |initialization_throttled|=true, this function will notify observers that
// those domains are now initializted.
virtual void SetInitializationThrottled(bool initialization_throttled) = 0;
}; };
// A registrar that only observes changes to particular policies within the // A registrar that only observes changes to particular policies within the
......
...@@ -107,8 +107,14 @@ base::flat_set<std::string> GetStringListPolicyItems( ...@@ -107,8 +107,14 @@ base::flat_set<std::string> GetStringListPolicyItems(
} // namespace } // namespace
PolicyServiceImpl::PolicyServiceImpl(Providers providers) { PolicyServiceImpl::PolicyServiceImpl(Providers providers)
providers_ = std::move(providers); : PolicyServiceImpl(std::move(providers),
/*initialization_throttled=*/false) {}
PolicyServiceImpl::PolicyServiceImpl(Providers providers,
bool initialization_throttled)
: providers_(std::move(providers)),
initialization_throttled_(initialization_throttled) {
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
initialization_complete_[domain] = true; initialization_complete_[domain] = true;
for (auto* provider : providers_) { for (auto* provider : providers_) {
...@@ -123,6 +129,13 @@ PolicyServiceImpl::PolicyServiceImpl(Providers providers) { ...@@ -123,6 +129,13 @@ PolicyServiceImpl::PolicyServiceImpl(Providers providers) {
MergeAndTriggerUpdates(); MergeAndTriggerUpdates();
} }
// static
std::unique_ptr<PolicyServiceImpl>
PolicyServiceImpl::CreateWithThrottledInitialization(Providers providers) {
return base::WrapUnique(new PolicyServiceImpl(
std::move(providers), /*initialization_throttled=*/true));
}
PolicyServiceImpl::~PolicyServiceImpl() { PolicyServiceImpl::~PolicyServiceImpl() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
for (auto* provider : providers_) for (auto* provider : providers_)
...@@ -177,6 +190,8 @@ const PolicyMap& PolicyServiceImpl::GetPolicies( ...@@ -177,6 +190,8 @@ const PolicyMap& PolicyServiceImpl::GetPolicies(
bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const { bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE); DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE);
if (initialization_throttled_)
return false;
return initialization_complete_[domain]; return initialization_complete_[domain];
} }
...@@ -203,12 +218,14 @@ void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) { ...@@ -203,12 +218,14 @@ void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
} }
} }
void PolicyServiceImpl::SetInitializationThrottled( void PolicyServiceImpl::UnthrottleInitialization() {
bool initialization_throttled) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(initialization_throttled != initialization_throttled_); if (!initialization_throttled_)
initialization_throttled_ = initialization_throttled; return;
CheckInitializationComplete();
initialization_throttled_ = false;
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
MaybeNotifyInitializationComplete(static_cast<PolicyDomain>(domain));
} }
void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) { void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
...@@ -355,9 +372,6 @@ void PolicyServiceImpl::MergeAndTriggerUpdates() { ...@@ -355,9 +372,6 @@ void PolicyServiceImpl::MergeAndTriggerUpdates() {
void PolicyServiceImpl::CheckInitializationComplete() { void PolicyServiceImpl::CheckInitializationComplete() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
if (initialization_throttled_)
return;
// Check if all the providers just became initialized for each domain; if so, // Check if all the providers just became initialized for each domain; if so,
// notify that domain's observers. // notify that domain's observers.
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) { for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
...@@ -375,13 +389,22 @@ void PolicyServiceImpl::CheckInitializationComplete() { ...@@ -375,13 +389,22 @@ void PolicyServiceImpl::CheckInitializationComplete() {
} }
if (all_complete) { if (all_complete) {
initialization_complete_[domain] = true; initialization_complete_[domain] = true;
MaybeNotifyInitializationComplete(policy_domain);
}
}
}
void PolicyServiceImpl::MaybeNotifyInitializationComplete(
PolicyDomain policy_domain) {
if (initialization_throttled_)
return;
if (!initialization_complete_[policy_domain])
return;
auto iter = observers_.find(policy_domain); auto iter = observers_.find(policy_domain);
if (iter != observers_.end()) { if (iter != observers_.end()) {
for (auto& observer : *iter->second) for (auto& observer : *iter->second)
observer.OnPolicyServiceInitialized(policy_domain); observer.OnPolicyServiceInitialized(policy_domain);
} }
}
}
} }
void PolicyServiceImpl::CheckRefreshComplete() { void PolicyServiceImpl::CheckRefreshComplete() {
......
...@@ -34,6 +34,15 @@ class POLICY_EXPORT PolicyServiceImpl ...@@ -34,6 +34,15 @@ class POLICY_EXPORT PolicyServiceImpl
// Creates a new PolicyServiceImpl with the list of // Creates a new PolicyServiceImpl with the list of
// ConfigurationPolicyProviders, in order of decreasing priority. // ConfigurationPolicyProviders, in order of decreasing priority.
explicit PolicyServiceImpl(Providers providers); explicit PolicyServiceImpl(Providers providers);
// Creates a new PolicyServiceImpl with the list of
// ConfigurationPolicyProviders, in order of decreasing priority.
// The created PolicyServiceImpl will only notify observers that
// initialization has completed (for any domain) after
// |UnthrottleInitialization| has been called.
static std::unique_ptr<PolicyServiceImpl> CreateWithThrottledInitialization(
Providers providers);
~PolicyServiceImpl() override; ~PolicyServiceImpl() override;
// PolicyService overrides: // PolicyService overrides:
...@@ -47,12 +56,27 @@ class POLICY_EXPORT PolicyServiceImpl ...@@ -47,12 +56,27 @@ class POLICY_EXPORT PolicyServiceImpl
const PolicyMap& GetPolicies(const PolicyNamespace& ns) const override; const PolicyMap& GetPolicies(const PolicyNamespace& ns) const override;
bool IsInitializationComplete(PolicyDomain domain) const override; bool IsInitializationComplete(PolicyDomain domain) const override;
void RefreshPolicies(const base::Closure& callback) override; void RefreshPolicies(const base::Closure& callback) override;
void SetInitializationThrottled(bool initialization_throttled) override;
// If this PolicyServiceImpl has been created using
// |CreateWithThrottledInitialization|, calling UnthrottleInitialization will
// allow notification of observers that initialization has completed. If
// initialization has actually completed previously but observers were not
// notified yet because it was throttled, will notify observers synchronously.
// Has no effect if initialization was not throttled.
void UnthrottleInitialization();
private: private:
using Observers = using Observers =
base::ObserverList<PolicyService::Observer, true>::Unchecked; base::ObserverList<PolicyService::Observer, true>::Unchecked;
// This constructor is not publicly visible so callers that want a
// PolicyServiceImpl with throttled initialization use
// |CreateWithInitializationThrottled| for clarity.
// If |initialization_throttled| is true, this PolicyServiceImpl will only
// notify observers that initialization has completed (for any domain) after
// |UnthrottleInitialization| has been called.
PolicyServiceImpl(Providers providers, bool initialization_throttled);
// ConfigurationPolicyProvider::Observer overrides: // ConfigurationPolicyProvider::Observer overrides:
void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override; void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override;
...@@ -68,10 +92,17 @@ class POLICY_EXPORT PolicyServiceImpl ...@@ -68,10 +92,17 @@ class POLICY_EXPORT PolicyServiceImpl
// of namespaces whose policies have been modified. // of namespaces whose policies have been modified.
void MergeAndTriggerUpdates(); void MergeAndTriggerUpdates();
// Checks if all providers are initialized, and notifies the observers // Checks if all providers are initialized and sets |initialization_complete_|
// if the service just became initialized. // accordingly. If initialization is not throttled, will also notify the
// observers if the service just became initialized.
void CheckInitializationComplete(); void CheckInitializationComplete();
// If initialization is complete for |policy_domain| and initialization is not
// throttled, will notify obserers for |policy_domain| that it has been
// initialized. This function should only be called when |policy_domain| just
// became initialized or when initialization has been unthrottled.
void MaybeNotifyInitializationComplete(PolicyDomain policy_domain);
// Invokes all the refresh callbacks if there are no more refreshes pending. // Invokes all the refresh callbacks if there are no more refreshes pending.
void CheckRefreshComplete(); void CheckRefreshComplete();
...@@ -110,7 +141,7 @@ class POLICY_EXPORT PolicyServiceImpl ...@@ -110,7 +141,7 @@ class POLICY_EXPORT PolicyServiceImpl
// If this is true, IsInitializationComplete should be returning false for all // If this is true, IsInitializationComplete should be returning false for all
// policy domains because the owner of this PolicyService is delaying the // policy domains because the owner of this PolicyService is delaying the
// initialization signal. // initialization signal.
bool initialization_throttled_ = false; bool initialization_throttled_;
// Used to verify thread-safe usage. // Used to verify thread-safe usage.
base::ThreadChecker thread_checker_; base::ThreadChecker thread_checker_;
......
...@@ -611,7 +611,7 @@ TEST_F(PolicyServiceTest, NamespaceMerge) { ...@@ -611,7 +611,7 @@ TEST_F(PolicyServiceTest, NamespaceMerge) {
} }
TEST_F(PolicyServiceTest, IsInitializationComplete) { TEST_F(PolicyServiceTest, IsInitializationComplete) {
// |provider0| has all domains initialized. // |provider0_| has all domains initialized.
Mock::VerifyAndClearExpectations(&provider1_); Mock::VerifyAndClearExpectations(&provider1_);
Mock::VerifyAndClearExpectations(&provider2_); Mock::VerifyAndClearExpectations(&provider2_);
EXPECT_CALL(provider1_, IsInitializationComplete(_)) EXPECT_CALL(provider1_, IsInitializationComplete(_))
...@@ -690,7 +690,7 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) { ...@@ -690,7 +690,7 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) {
EXPECT_FALSE(policy_service_->IsInitializationComplete( EXPECT_FALSE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS)); POLICY_DOMAIN_SIGNIN_EXTENSIONS));
// Initialize the remaining domain. // Initialize the remaining domains.
EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_EXTENSIONS)); EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_EXTENSIONS));
EXPECT_CALL(observer, EXPECT_CALL(observer,
OnPolicyServiceInitialized(POLICY_DOMAIN_SIGNIN_EXTENSIONS)); OnPolicyServiceInitialized(POLICY_DOMAIN_SIGNIN_EXTENSIONS));
...@@ -716,6 +716,137 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) { ...@@ -716,6 +716,137 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) {
policy_service_->RemoveObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer); policy_service_->RemoveObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
} }
// Tests initialization throttling of PolicyServiceImpl.
// This actually tests two cases:
// (1) A domain was initialized before UnthrottleInitialization is called.
// Observers only get notified after calling UntrhottleInitialization.
// This is tested on POLICY_DOMAIN_CHROME.
// (2) A domain becomes initialized after UnthrottleInitialization has already
// been called. Because initialization is not throttled anymore, observers
// get notified immediately when the domain becomes initialized.
// This is tested on POLICY_DOMAIN_EXTENSIONS and
// POLICY_DOMAIN_SIGNIN_EXTENSIONS.
TEST_F(PolicyServiceTest, InitializationThrottled) {
// |provider0_| and |provider1_| has all domains initialized, |provider2_| has
// no domain initialized.
Mock::VerifyAndClearExpectations(&provider2_);
EXPECT_CALL(provider2_, IsInitializationComplete(_))
.WillRepeatedly(Return(false));
PolicyServiceImpl::Providers providers;
providers.push_back(&provider0_);
providers.push_back(&provider1_);
providers.push_back(&provider2_);
policy_service_ = PolicyServiceImpl::CreateWithThrottledInitialization(
std::move(providers));
EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
EXPECT_FALSE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS));
MockPolicyServiceObserver observer;
policy_service_->AddObserver(POLICY_DOMAIN_CHROME, &observer);
policy_service_->AddObserver(POLICY_DOMAIN_EXTENSIONS, &observer);
policy_service_->AddObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
// Now additionally initialize POLICY_DOMAIN_CHROME on |provider2_|.
// Note: VerifyAndClearExpectations is called to reset the previously set
// action for IsInitializtionComplete on |provider_2|.
Mock::VerifyAndClearExpectations(&provider2_);
EXPECT_CALL(provider2_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
.WillRepeatedly(Return(true));
EXPECT_CALL(provider2_, IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS))
.WillRepeatedly(Return(false));
EXPECT_CALL(provider2_,
IsInitializationComplete(POLICY_DOMAIN_SIGNIN_EXTENSIONS))
.WillRepeatedly(Return(false));
// Nothing will happen because initialization is still throttled.
EXPECT_CALL(observer, OnPolicyServiceInitialized(_)).Times(0);
const PolicyMap kPolicyMap;
provider2_.UpdateChromePolicy(kPolicyMap);
Mock::VerifyAndClearExpectations(&observer);
EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
EXPECT_FALSE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS));
// Unthrottle initialization. This will signal that POLICY_DOMAIN_CHROME is
// initialized, the other domains should still not be initialized because
// |provider2_| is returning false in IsInitializationComplete for them.
EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_CHROME));
policy_service_->UnthrottleInitialization();
Mock::VerifyAndClearExpectations(&observer);
EXPECT_TRUE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
EXPECT_FALSE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS));
// Initialize the remaining domains.
// Note: VerifyAndClearExpectations is called to reset the previously set
// action for IsInitializtionComplete on |provider_2|.
Mock::VerifyAndClearExpectations(&provider2_);
EXPECT_CALL(provider2_, IsInitializationComplete(_))
.WillRepeatedly(Return(true));
EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_EXTENSIONS));
EXPECT_CALL(observer,
OnPolicyServiceInitialized(POLICY_DOMAIN_SIGNIN_EXTENSIONS));
provider2_.UpdateChromePolicy(kPolicyMap);
Mock::VerifyAndClearExpectations(&observer);
EXPECT_TRUE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_TRUE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
EXPECT_TRUE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS));
// Cleanup.
policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, &observer);
policy_service_->RemoveObserver(POLICY_DOMAIN_EXTENSIONS, &observer);
policy_service_->RemoveObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
}
TEST_F(PolicyServiceTest, InitializationThrottledProvidersAlreadyInitialized) {
// All providers have all domains initialized.
PolicyServiceImpl::Providers providers;
providers.push_back(&provider0_);
providers.push_back(&provider1_);
providers.push_back(&provider2_);
policy_service_ = PolicyServiceImpl::CreateWithThrottledInitialization(
std::move(providers));
EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
EXPECT_FALSE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS));
MockPolicyServiceObserver observer;
policy_service_->AddObserver(POLICY_DOMAIN_CHROME, &observer);
policy_service_->AddObserver(POLICY_DOMAIN_EXTENSIONS, &observer);
policy_service_->AddObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
// Unthrottle initialization. This will signal that all domains are
// initialized.
EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_CHROME));
EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_EXTENSIONS));
EXPECT_CALL(observer,
OnPolicyServiceInitialized(POLICY_DOMAIN_SIGNIN_EXTENSIONS));
policy_service_->UnthrottleInitialization();
Mock::VerifyAndClearExpectations(&observer);
EXPECT_TRUE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_TRUE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
EXPECT_TRUE(policy_service_->IsInitializationComplete(
POLICY_DOMAIN_SIGNIN_EXTENSIONS));
// Cleanup.
policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, &observer);
policy_service_->RemoveObserver(POLICY_DOMAIN_EXTENSIONS, &observer);
policy_service_->RemoveObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
}
TEST_F(PolicyServiceTest, SeparateProxyPoliciesMerging) { TEST_F(PolicyServiceTest, SeparateProxyPoliciesMerging) {
const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string()); const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
const PolicyNamespace extension_namespace(POLICY_DOMAIN_EXTENSIONS, "xyz"); const PolicyNamespace extension_namespace(POLICY_DOMAIN_EXTENSIONS, "xyz");
......
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