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 {
};
} // 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)
ProfilePolicyConnector::ProfilePolicyConnector() {}
......@@ -174,22 +192,40 @@ void ProfilePolicyConnector::Init(
}
#endif
policy_service_ = std::make_unique<PolicyServiceImpl>(policy_providers_);
#if defined(OS_CHROMEOS)
ConfigurationPolicyProvider* user_policy_delegate = nullptr;
if (is_primary_user_) {
user_policy_delegate = configuration_policy_provider
? configuration_policy_provider
: special_user_policy_provider_.get();
ConfigurationPolicyProvider* user_policy_delegate_candidate =
configuration_policy_provider ? configuration_policy_provider
: 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)
SetGlobalUserPolicyDelegate(user_policy_delegate);
#endif
#else // defined(OS_CHROMEOS)
policy_service_ = std::make_unique<PolicyServiceImpl>(policy_providers_);
#endif // defined(OS_CHROMEOS)
}
void ProfilePolicyConnector::InitForTesting(
std::unique_ptr<PolicyService> service) {
DCHECK(!policy_service_);
policy_service_ = std::move(service);
}
......@@ -200,7 +236,7 @@ void ProfilePolicyConnector::OverrideIsManagedForTesting(bool is_managed) {
void ProfilePolicyConnector::Shutdown() {
#if defined(OS_CHROMEOS)
if (is_primary_user_)
SetGlobalUserPolicyDelegate(nullptr);
GetProxyPolicyProvider()->SetDelegate(nullptr);
if (special_user_policy_provider_)
special_user_policy_provider_->Shutdown();
......@@ -256,41 +292,33 @@ ProfilePolicyConnector::DeterminePolicyProviderForPolicy(
}
#if defined(OS_CHROMEOS)
void ProfilePolicyConnector::SetGlobalUserPolicyDelegate(
std::unique_ptr<PolicyService>
ProfilePolicyConnector::CreatePolicyServiceWithInitializationThrottled(
const std::vector<ConfigurationPolicyProvider*>& policy_providers,
ConfigurationPolicyProvider* user_policy_delegate) {
BrowserPolicyConnectorChromeOS* browser_policy_connector =
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) {
proxy_policy_provider->SetDelegate(nullptr);
return;
}
DCHECK(user_policy_delegate);
auto policy_service =
PolicyServiceImpl::CreateWithThrottledInitialization(policy_providers);
policy_service_->SetInitializationThrottled(true);
// base::Unretained is OK for |this| because
// |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_ =
std::make_unique<internal::ProxiedPoliciesPropagatedWatcher>(
device_wide_policy_service, proxy_policy_provider,
GetDeviceWidePolicyService(), GetProxyPolicyProvider(),
user_policy_delegate,
base::BindOnce(&ProfilePolicyConnector::OnProxiedPoliciesPropagated,
base::Unretained(this)));
proxy_policy_provider->SetDelegate(user_policy_delegate);
base::Unretained(this),
base::Unretained(policy_service.get())));
return std::move(policy_service);
}
void ProfilePolicyConnector::OnProxiedPoliciesPropagated() {
policy_service_->SetInitializationThrottled(false);
void ProfilePolicyConnector::OnProxiedPoliciesPropagated(
PolicyServiceImpl* policy_service) {
policy_service->UnthrottleInitialization();
// Do not delete |proxied_policies_propagated_watcher_| synchronously, as the
// PolicyService it is observing is expected to be iterating its observer
// list.
......
......@@ -27,6 +27,7 @@ class ProxiedPoliciesPropagatedWatcher;
class CloudPolicyStore;
class ConfigurationPolicyProvider;
class PolicyService;
class PolicyServiceImpl;
class SchemaRegistry;
class ChromeBrowserPolicyConnector;
......@@ -81,22 +82,31 @@ class ProfilePolicyConnector final {
#if defined(OS_CHROMEOS)
// On Chrome OS, primary Profile user policies are forwarded to the
// device-global PolicyService[1] using a ProxyPolicyProvider. This function
// sets up that forwarding, using |user_policy_delegate| as the policy source.
// It also delays signaling that |policy_service_| is initialized until the
// policies provided by |user_policy_delegate| have propagated to the
// device-wide PolicyService[1]. This is done so that code that runs early on
// Profile initialization can rely on the device-wide PolicyService[1] and
// local state Preferences[2] respecting the proxied primary user policies.
// device-global PolicyService[1] using a ProxyPolicyProvider.
// When that is done, signaling that |policy_service_| is initialized should
// be delayed until the policies provided by |user_policy_delegate| have
// propagated to the device-wide PolicyService[1]. This is done so that code
// that runs early on Profile initialization can rely on the device-wide
// PolicyService[1] and local state Preferences[2] respecting the proxied
// 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()
// [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);
// Called when primary user policies that are proxied to the device-wide
// 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
// can only come from one Profile. |is_primary_user_| is true if this
......
......@@ -45,7 +45,6 @@ class MockPolicyService : public PolicyService {
MOCK_CONST_METHOD1(GetPolicies, const PolicyMap&(const PolicyNamespace&));
MOCK_CONST_METHOD1(IsInitializationComplete, bool(PolicyDomain domain));
MOCK_METHOD1(RefreshPolicies, void(const base::Closure&));
MOCK_METHOD1(SetInitializationThrottled, void(bool initialization_throttled));
};
} // namespace policy
......
......@@ -97,16 +97,6 @@ class POLICY_EXPORT PolicyService {
// |callback| is invoked once every source has reloaded its policies, and
// GetPolicies() is guaranteed to return the updated values at that point.
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
......
......@@ -107,8 +107,14 @@ base::flat_set<std::string> GetStringListPolicyItems(
} // namespace
PolicyServiceImpl::PolicyServiceImpl(Providers providers) {
providers_ = std::move(providers);
PolicyServiceImpl::PolicyServiceImpl(Providers 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)
initialization_complete_[domain] = true;
for (auto* provider : providers_) {
......@@ -123,6 +129,13 @@ PolicyServiceImpl::PolicyServiceImpl(Providers providers) {
MergeAndTriggerUpdates();
}
// static
std::unique_ptr<PolicyServiceImpl>
PolicyServiceImpl::CreateWithThrottledInitialization(Providers providers) {
return base::WrapUnique(new PolicyServiceImpl(
std::move(providers), /*initialization_throttled=*/true));
}
PolicyServiceImpl::~PolicyServiceImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
for (auto* provider : providers_)
......@@ -177,6 +190,8 @@ const PolicyMap& PolicyServiceImpl::GetPolicies(
bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE);
if (initialization_throttled_)
return false;
return initialization_complete_[domain];
}
......@@ -203,12 +218,14 @@ void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
}
}
void PolicyServiceImpl::SetInitializationThrottled(
bool initialization_throttled) {
void PolicyServiceImpl::UnthrottleInitialization() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(initialization_throttled != initialization_throttled_);
initialization_throttled_ = initialization_throttled;
CheckInitializationComplete();
if (!initialization_throttled_)
return;
initialization_throttled_ = false;
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
MaybeNotifyInitializationComplete(static_cast<PolicyDomain>(domain));
}
void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
......@@ -355,9 +372,6 @@ void PolicyServiceImpl::MergeAndTriggerUpdates() {
void PolicyServiceImpl::CheckInitializationComplete() {
DCHECK(thread_checker_.CalledOnValidThread());
if (initialization_throttled_)
return;
// Check if all the providers just became initialized for each domain; if so,
// notify that domain's observers.
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
......@@ -375,15 +389,24 @@ void PolicyServiceImpl::CheckInitializationComplete() {
}
if (all_complete) {
initialization_complete_[domain] = true;
auto iter = observers_.find(policy_domain);
if (iter != observers_.end()) {
for (auto& observer : *iter->second)
observer.OnPolicyServiceInitialized(policy_domain);
}
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);
if (iter != observers_.end()) {
for (auto& observer : *iter->second)
observer.OnPolicyServiceInitialized(policy_domain);
}
}
void PolicyServiceImpl::CheckRefreshComplete() {
// Invoke all the callbacks if a refresh has just fully completed.
if (refresh_pending_.empty() && !refresh_callbacks_.empty()) {
......
......@@ -34,6 +34,15 @@ class POLICY_EXPORT PolicyServiceImpl
// Creates a new PolicyServiceImpl with the list of
// ConfigurationPolicyProviders, in order of decreasing priority.
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;
// PolicyService overrides:
......@@ -47,12 +56,27 @@ class POLICY_EXPORT PolicyServiceImpl
const PolicyMap& GetPolicies(const PolicyNamespace& ns) const override;
bool IsInitializationComplete(PolicyDomain domain) const 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:
using Observers =
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:
void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override;
......@@ -68,10 +92,17 @@ class POLICY_EXPORT PolicyServiceImpl
// of namespaces whose policies have been modified.
void MergeAndTriggerUpdates();
// Checks if all providers are initialized, and notifies the observers
// if the service just became initialized.
// Checks if all providers are initialized and sets |initialization_complete_|
// accordingly. If initialization is not throttled, will also notify the
// observers if the service just became initialized.
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.
void CheckRefreshComplete();
......@@ -110,7 +141,7 @@ class POLICY_EXPORT PolicyServiceImpl
// If this is true, IsInitializationComplete should be returning false for all
// policy domains because the owner of this PolicyService is delaying the
// initialization signal.
bool initialization_throttled_ = false;
bool initialization_throttled_;
// Used to verify thread-safe usage.
base::ThreadChecker thread_checker_;
......
......@@ -611,7 +611,7 @@ TEST_F(PolicyServiceTest, NamespaceMerge) {
}
TEST_F(PolicyServiceTest, IsInitializationComplete) {
// |provider0| has all domains initialized.
// |provider0_| has all domains initialized.
Mock::VerifyAndClearExpectations(&provider1_);
Mock::VerifyAndClearExpectations(&provider2_);
EXPECT_CALL(provider1_, IsInitializationComplete(_))
......@@ -690,7 +690,7 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) {
EXPECT_FALSE(policy_service_->IsInitializationComplete(
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_SIGNIN_EXTENSIONS));
......@@ -716,6 +716,137 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) {
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) {
const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
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