Index: components/policy/core/common/cloud/component_cloud_policy_service.cc |
diff --git a/components/policy/core/common/cloud/component_cloud_policy_service.cc b/components/policy/core/common/cloud/component_cloud_policy_service.cc |
index cd783abdd25def15c31ed0f8778d4a5337f45815..54db23006191130a175bbf9166a70153638ee0dc 100644 |
--- a/components/policy/core/common/cloud/component_cloud_policy_service.cc |
+++ b/components/policy/core/common/cloud/component_cloud_policy_service.cc |
@@ -100,7 +100,7 @@ class ComponentCloudPolicyService::Backend |
scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher_; |
ComponentCloudPolicyStore store_; |
scoped_ptr<ComponentCloudPolicyUpdater> updater_; |
- scoped_refptr<SchemaMap> schema_map_; |
+ bool initialized_; |
DISALLOW_COPY_AND_ASSIGN(Backend); |
}; |
@@ -116,7 +116,8 @@ ComponentCloudPolicyService::Backend::Backend( |
service_task_runner_(service_task_runner), |
cache_(cache.Pass()), |
external_policy_data_fetcher_(external_policy_data_fetcher.Pass()), |
- store_(this, cache_.get()) {} |
+ store_(this, cache_.get()), |
+ initialized_(false) {} |
ComponentCloudPolicyService::Backend::~Backend() {} |
@@ -133,7 +134,7 @@ void ComponentCloudPolicyService::Backend::SetCredentials( |
void ComponentCloudPolicyService::Backend::Init( |
scoped_refptr<SchemaMap> schema_map) { |
- DCHECK(!schema_map_); |
+ DCHECK(!initialized_); |
OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>()); |
@@ -146,7 +147,6 @@ void ComponentCloudPolicyService::Backend::Init( |
store_.Load(); |
scoped_ptr<PolicyBundle> bundle(new PolicyBundle); |
bundle->CopyFrom(store_.policy()); |
- schema_map_->FilterBundle(bundle.get()); |
// Start downloading any pending data. |
updater_.reset(new ComponentCloudPolicyUpdater( |
@@ -157,6 +157,8 @@ void ComponentCloudPolicyService::Backend::Init( |
base::Bind(&ComponentCloudPolicyService::OnBackendInitialized, |
service_, |
base::Passed(&bundle))); |
+ |
+ initialized_ = true; |
} |
void ComponentCloudPolicyService::Backend::UpdateExternalPolicy( |
@@ -166,14 +168,13 @@ void ComponentCloudPolicyService::Backend::UpdateExternalPolicy( |
void ComponentCloudPolicyService::Backend:: |
OnComponentCloudPolicyStoreUpdated() { |
- if (!schema_map_) { |
+ if (!initialized_) { |
// Ignore notifications triggered by the initial Purge or Clear. |
return; |
} |
scoped_ptr<PolicyBundle> bundle(new PolicyBundle); |
bundle->CopyFrom(store_.policy()); |
- schema_map_->FilterBundle(bundle.get()); |
service_task_runner_->PostTask( |
FROM_HERE, |
base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated, |
@@ -192,10 +193,6 @@ void ComponentCloudPolicyService::Backend::OnSchemasUpdated( |
base::Bind(&NotInSchemaMap, schema_map, domain->first)); |
} |
- // Set |schema_map_| after purging so that the notifications from the store |
- // are ignored on the first OnSchemasUpdated() call from Init(). |
- schema_map_ = schema_map; |
- |
if (removed) { |
for (size_t i = 0; i < removed->size(); ++i) |
updater_->CancelUpdate((*removed)[i]); |
@@ -217,6 +214,7 @@ ComponentCloudPolicyService::ComponentCloudPolicyService( |
backend_task_runner_(backend_task_runner), |
io_task_runner_(io_task_runner), |
current_schema_map_(new SchemaMap), |
+ unfiltered_policy_(new PolicyBundle), |
started_loading_initial_policy_(false), |
loaded_initial_policy_(false), |
is_registered_for_cloud_policy_(false), |
@@ -241,6 +239,11 @@ ComponentCloudPolicyService::ComponentCloudPolicyService( |
// policies. |
if (core_->store()->is_initialized()) |
OnStoreLoaded(core_->store()); |
+ |
+ // Start observing the core and tracking the state of the client. |
+ core_->AddObserver(this); |
+ if (core_->client()) |
+ OnCoreConnected(core_); |
} |
ComponentCloudPolicyService::~ComponentCloudPolicyService() { |
@@ -287,6 +290,11 @@ void ComponentCloudPolicyService::OnSchemaRegistryUpdated( |
return; |
ReloadSchema(); |
+ |
+ // Filter the |unfiltered_policy_| again, now that |current_schema_map_| has |
+ // been updated. We must make sure we never serve invalid policy; we must |
+ // also filter again if an invalid Schema has now been loaded. |
+ OnPolicyUpdated(unfiltered_policy_.Pass()); |
} |
void ComponentCloudPolicyService::OnCoreConnected(CloudPolicyCore* core) { |
@@ -300,8 +308,9 @@ void ComponentCloudPolicyService::OnCoreConnected(CloudPolicyCore* core) { |
PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType, "")); |
// Immediately load any PolicyFetchResponses that the client may already |
- // have. |
- OnPolicyFetched(core_->client()); |
+ // have if the backend is ready. |
+ if (loaded_initial_policy_) |
+ OnPolicyFetched(core_->client()); |
} |
void ComponentCloudPolicyService::OnCoreDisconnecting(CloudPolicyCore* core) { |
@@ -421,6 +430,7 @@ void ComponentCloudPolicyService::InitializeIfReady() { |
!core_->store()->is_initialized()) { |
return; |
} |
+ |
// The initial list of components is ready. Initialize the backend now, which |
// will call back to OnBackendInitialized. |
backend_task_runner_->PostTask(FROM_HERE, |
@@ -437,18 +447,12 @@ void ComponentCloudPolicyService::OnBackendInitialized( |
loaded_initial_policy_ = true; |
- // We're now ready to serve the initial policy; notify the policy observers. |
- OnPolicyUpdated(initial_policy.Pass()); |
- |
// Send the current schema to the backend, in case it has changed while the |
// backend was initializing. |
ReloadSchema(); |
- // Start observing the core and tracking the state of the client. |
- core_->AddObserver(this); |
- |
- if (core_->client()) |
- OnCoreConnected(core_); |
+ // We're now ready to serve the initial policy; notify the policy observers. |
+ OnPolicyUpdated(initial_policy.Pass()); |
} |
void ComponentCloudPolicyService::ReloadSchema() { |
@@ -462,10 +466,6 @@ void ComponentCloudPolicyService::ReloadSchema() { |
current_schema_map_ = new_schema_map; |
- // Schedule a policy refresh if a new managed component was added. |
- if (core_->client() && !added.empty()) |
- core_->RefreshSoon(); |
- |
// Send the updated SchemaMap and a list of removed components to the |
// backend. |
backend_task_runner_->PostTask(FROM_HERE, |
@@ -473,12 +473,28 @@ void ComponentCloudPolicyService::ReloadSchema() { |
base::Unretained(backend_.get()), |
current_schema_map_, |
base::Passed(&removed))); |
+ |
+ // Have another look at the client if the core is already connected. |
+ // The client may have already fetched policy for some component and it was |
+ // previously ignored because the component wasn't listed in the schema map. |
+ // There's no point in fetching policy from the server again; the server |
+ // always pushes all the components it knows about. |
+ if (core_->client()) |
+ OnPolicyFetched(core_->client()); |
} |
void ComponentCloudPolicyService::OnPolicyUpdated( |
scoped_ptr<PolicyBundle> policy) { |
DCHECK(CalledOnValidThread()); |
- policy_.Swap(policy.get()); |
+ |
+ // Store the current unfiltered policies. |
+ unfiltered_policy_ = policy.Pass(); |
+ |
+ // Make a copy in |policy_| and filter it; this is what's passed to the |
+ // outside world. |
+ policy_.CopyFrom(*unfiltered_policy_); |
+ current_schema_map_->FilterBundle(&policy_); |
+ |
delegate_->OnComponentCloudPolicyUpdated(); |
} |