Chromium Code Reviews| Index: chrome/browser/policy/cloud/component_cloud_policy_service.cc |
| diff --git a/chrome/browser/policy/cloud/component_cloud_policy_service.cc b/chrome/browser/policy/cloud/component_cloud_policy_service.cc |
| index 8e8cda385fa9d474e23111d3b59c2a64dab9533d..a4e3f4a7bb44bca293fbdd10c24eb7cb7fa607a5 100644 |
| --- a/chrome/browser/policy/cloud/component_cloud_policy_service.cc |
| +++ b/chrome/browser/policy/cloud/component_cloud_policy_service.cc |
| @@ -4,18 +4,16 @@ |
| #include "chrome/browser/policy/cloud/component_cloud_policy_service.h" |
| -#include <map> |
| #include <string> |
| -#include <utility> |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/message_loop/message_loop_proxy.h" |
| -#include "base/pickle.h" |
| #include "base/sequenced_task_runner.h" |
| -#include "base/stl_util.h" |
| +#include "base/time/time.h" |
| +#include "chrome/browser/policy/cloud/cloud_policy_constants.h" |
| #include "chrome/browser/policy/cloud/component_cloud_policy_store.h" |
| #include "chrome/browser/policy/cloud/component_cloud_policy_updater.h" |
| #include "chrome/browser/policy/cloud/external_policy_data_fetcher.h" |
| @@ -29,9 +27,6 @@ namespace em = enterprise_management; |
| namespace policy { |
| -const char ComponentCloudPolicyService::kComponentNamespaceCache[] = |
| - "component-namespace-cache"; |
| - |
| namespace { |
| bool NotInSchemaMap(const scoped_refptr<SchemaMap> schema_map, |
| @@ -40,6 +35,20 @@ bool NotInSchemaMap(const scoped_refptr<SchemaMap> schema_map, |
| return schema_map->GetSchema(PolicyNamespace(domain, component_id)) == NULL; |
| } |
| +bool ToPolicyNamespaceKey(const PolicyNamespace& ns, PolicyNamespaceKey* key) { |
| + if (!ComponentCloudPolicyStore::GetPolicyType(ns.domain, &key->first)) |
| + return false; |
| + key->second = ns.component_id; |
| + return true; |
| +} |
| + |
| +bool ToPolicyNamespace(const PolicyNamespaceKey& key, PolicyNamespace* ns) { |
| + if (!ComponentCloudPolicyStore::GetPolicyDomain(key.first, &ns->domain)) |
| + return false; |
| + ns->component_id = key.second; |
| + return true; |
| +} |
| + |
| } // namespace |
| ComponentCloudPolicyService::Delegate::~Delegate() {} |
| @@ -57,30 +66,19 @@ class ComponentCloudPolicyService::Backend |
| Backend(base::WeakPtr<ComponentCloudPolicyService> service, |
| scoped_refptr<base::SequencedTaskRunner> task_runner, |
| scoped_refptr<base::SequencedTaskRunner> service_task_runner, |
| - scoped_ptr<ResourceCache> cache); |
| - virtual ~Backend(); |
| - |
| - // This is invoked right after the constructor but on the background thread. |
| - // Used to create the store on the right thread. |
| - void Init(); |
| - |
| - // Reads the initial list of components and the initial policy. |
| - void FinalizeInit(); |
| + scoped_ptr<ResourceCache> cache, |
| + scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher); |
| - // Allows downloading of external data via the |external_policy_data_fetcher|. |
| - void Connect( |
| - scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher); |
| - |
| - // Stops updating remote data. Cached policies are still served. |
| - void Disconnect(); |
| + virtual ~Backend(); |
| - // Loads the initial policies from the store. |username| and |dm_token| are |
| - // used to validate the cached policies. |
| + // |username| and |dm_token| will be used to validate the cached policies. |
| void SetCredentials(const std::string& username, const std::string& dm_token); |
| + // Loads the |store_| and starts downloading updates. |
| + void Init(scoped_refptr<SchemaMap> schema_map); |
| + |
| // Passes a policy protobuf to the backend, to start its validation and |
| // eventual download of the policy data on the background thread. |
| - // This is ignored if the backend isn't connected. |
| void UpdateExternalPolicy(scoped_ptr<em::PolicyFetchResponse> response); |
| // ComponentCloudPolicyStore::Delegate implementation: |
| @@ -88,11 +86,12 @@ class ComponentCloudPolicyService::Backend |
| // Passes the current SchemaMap so that the disk cache can purge components |
| // that aren't being tracked anymore. |
| - void OnSchemasUpdated(scoped_refptr<SchemaMap> schema_map); |
| + // |removed| is a list of namespaces that were present in the previous |
| + // schema and have been removed in the updated version. |
| + void OnSchemasUpdated(scoped_refptr<SchemaMap> schema_map, |
| + scoped_ptr<PolicyNamespaceList> removed); |
| private: |
| - scoped_ptr<PolicyNamespaceKeys> ReadCachedComponents(); |
| - |
| // The ComponentCloudPolicyService that owns |this|. Used to inform the |
| // |service_| when policy changes. |
| base::WeakPtr<ComponentCloudPolicyService> service_; |
| @@ -105,7 +104,8 @@ class ComponentCloudPolicyService::Backend |
| scoped_refptr<base::SequencedTaskRunner> service_task_runner_; |
| scoped_ptr<ResourceCache> cache_; |
| - scoped_ptr<ComponentCloudPolicyStore> store_; |
| + scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher_; |
| + ComponentCloudPolicyStore store_; |
| scoped_ptr<ComponentCloudPolicyUpdater> updater_; |
| scoped_refptr<SchemaMap> schema_map_; |
| @@ -116,70 +116,60 @@ ComponentCloudPolicyService::Backend::Backend( |
| base::WeakPtr<ComponentCloudPolicyService> service, |
| scoped_refptr<base::SequencedTaskRunner> task_runner, |
| scoped_refptr<base::SequencedTaskRunner> service_task_runner, |
| - scoped_ptr<ResourceCache> cache) |
| + scoped_ptr<ResourceCache> cache, |
| + scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher) |
| : service_(service), |
| task_runner_(task_runner), |
| service_task_runner_(service_task_runner), |
| - cache_(cache.Pass()) {} |
| + cache_(cache.Pass()), |
| + external_policy_data_fetcher_(external_policy_data_fetcher.Pass()), |
| + store_(this, cache_.get()) {} |
| ComponentCloudPolicyService::Backend::~Backend() {} |
| -void ComponentCloudPolicyService::Backend::Init() { |
| - DCHECK(!store_); |
| - store_.reset(new ComponentCloudPolicyStore(this, cache_.get())); |
| +void ComponentCloudPolicyService::Backend::SetCredentials( |
| + const std::string& username, |
| + const std::string& dm_token) { |
| + store_.SetCredentials(username, dm_token); |
| } |
| -void ComponentCloudPolicyService::Backend::FinalizeInit() { |
| - // Read the components that were cached in the last OnSchemasUpdated() call. |
| - scoped_ptr<PolicyNamespaceKeys> components = ReadCachedComponents(); |
| +void ComponentCloudPolicyService::Backend::Init( |
| + scoped_refptr<SchemaMap> schema_map) { |
| + DCHECK(!schema_map_); |
| + |
| + OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>()); |
| + |
| + // Read the initial policy. Note that this does not trigger notifications |
| + // through OnComponentCloudPolicyStoreUpdated. |
| + store_.Load(); |
| + scoped_ptr<PolicyBundle> bundle(new PolicyBundle); |
| + bundle->CopyFrom(store_.policy()); |
| - // Read the initial policy. |
| - store_->Load(); |
| - scoped_ptr<PolicyBundle> policy(new PolicyBundle); |
| - policy->CopyFrom(store_->policy()); |
| + // Start downloading any pending data. |
| + updater_.reset(new ComponentCloudPolicyUpdater( |
| + task_runner_, external_policy_data_fetcher_.Pass(), &store_)); |
| service_task_runner_->PostTask( |
| FROM_HERE, |
| base::Bind(&ComponentCloudPolicyService::OnBackendInitialized, |
| service_, |
| - base::Passed(&components), |
| - base::Passed(&policy))); |
| -} |
| - |
| -void ComponentCloudPolicyService::Backend::SetCredentials( |
| - const std::string& username, |
| - const std::string& dm_token) { |
| - store_->SetCredentials(username, dm_token); |
| -} |
| - |
| -void ComponentCloudPolicyService::Backend::Connect( |
| - scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher) { |
| - updater_.reset(new ComponentCloudPolicyUpdater( |
| - task_runner_, |
| - external_policy_data_fetcher.Pass(), |
| - store_.get())); |
| -} |
| - |
| -void ComponentCloudPolicyService::Backend::Disconnect() { |
| - updater_.reset(); |
| + base::Passed(&bundle))); |
| } |
| void ComponentCloudPolicyService::Backend::UpdateExternalPolicy( |
| scoped_ptr<em::PolicyFetchResponse> response) { |
| - if (updater_) |
| - updater_->UpdateExternalPolicy(response.Pass()); |
| + updater_->UpdateExternalPolicy(response.Pass()); |
| } |
| void ComponentCloudPolicyService::Backend:: |
| OnComponentCloudPolicyStoreUpdated() { |
| if (!schema_map_) { |
| - // No schemas have been registered yet, so keep serving the initial policy |
| - // obtained from FinalizeInit(). |
| + // Ignore notifications triggered by the initial Purge. |
| return; |
| } |
| scoped_ptr<PolicyBundle> bundle(new PolicyBundle); |
| - bundle->CopyFrom(store_->policy()); |
| + bundle->CopyFrom(store_.policy()); |
| schema_map_->FilterBundle(bundle.get()); |
| service_task_runner_->PostTask( |
| FROM_HERE, |
| @@ -189,94 +179,79 @@ void ComponentCloudPolicyService::Backend:: |
| } |
| void ComponentCloudPolicyService::Backend::OnSchemasUpdated( |
| - scoped_refptr<SchemaMap> schema_map) { |
| - // Store the current list of components in the cache. |
| + scoped_refptr<SchemaMap> schema_map, |
| + scoped_ptr<PolicyNamespaceList> removed) { |
| + // Purge any components that have been removed. |
| const DomainMap& domains = schema_map->GetDomains(); |
| for (DomainMap::const_iterator domain = domains.begin(); |
| domain != domains.end(); ++domain) { |
| - std::string domain_policy_type; |
| - if (!ComponentCloudPolicyStore::GetPolicyType(domain->first, |
| - &domain_policy_type)) { |
| - continue; |
| - } |
| - Pickle pickle; |
| - const ComponentMap& components = domain->second; |
| - for (ComponentMap::const_iterator comp = components.begin(); |
| - comp != components.end(); ++comp) { |
| - pickle.WriteString(comp->first); |
| - } |
| - std::string data(reinterpret_cast<const char*>(pickle.data()), |
| - pickle.size()); |
| - cache_->Store(kComponentNamespaceCache, domain_policy_type, data); |
| - |
| - // Purge any components that have been removed. |
| - if (store_) { |
| - store_->Purge(domain->first, |
| - base::Bind(&NotInSchemaMap, schema_map, domain->first)); |
| - } |
| + store_.Purge(domain->first, |
| + base::Bind(&NotInSchemaMap, schema_map, domain->first)); |
| } |
| - // Serve policies that may have updated while the backend was waiting for |
| - // the schema_map. |
| - const bool trigger_update = !schema_map_; |
| + // 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 (trigger_update) |
| - OnComponentCloudPolicyStoreUpdated(); |
| -} |
| -scoped_ptr<ComponentCloudPolicyService::PolicyNamespaceKeys> |
| - ComponentCloudPolicyService::Backend::ReadCachedComponents() { |
| - scoped_ptr<PolicyNamespaceKeys> keys(new PolicyNamespaceKeys); |
| - std::map<std::string, std::string> contents; |
| - cache_->LoadAllSubkeys(kComponentNamespaceCache, &contents); |
| - for (std::map<std::string, std::string>::iterator it = contents.begin(); |
| - it != contents.end(); ++it) { |
| - PolicyDomain domain; |
| - if (ComponentCloudPolicyStore::GetPolicyDomain(it->first, &domain)) { |
| - const Pickle pickle(it->second.data(), it->second.size()); |
| - PickleIterator pickit(pickle); |
| - std::string id; |
| - while (pickit.ReadString(&id)) |
| - keys->insert(std::make_pair(it->first, id)); |
| - } else { |
| - cache_->Delete(kComponentNamespaceCache, it->first); |
| - } |
| + if (removed) { |
| + for (size_t i = 0; i < removed->size(); ++i) |
| + updater_->CancelUpdate((*removed)[i]); |
| } |
| - return keys.Pass(); |
| } |
| ComponentCloudPolicyService::ComponentCloudPolicyService( |
| Delegate* delegate, |
| + SchemaRegistry* schema_registry, |
| CloudPolicyStore* store, |
| scoped_ptr<ResourceCache> cache, |
| + CloudPolicyClient* client, |
| + scoped_refptr<net::URLRequestContextGetter> request_context, |
| scoped_refptr<base::SequencedTaskRunner> backend_task_runner, |
| scoped_refptr<base::SequencedTaskRunner> io_task_runner) |
| : delegate_(delegate), |
| + schema_registry_(schema_registry), |
| + store_(store), |
| + client_(client), |
| + request_context_(request_context), |
| backend_task_runner_(backend_task_runner), |
| io_task_runner_(io_task_runner), |
| - client_(NULL), |
| - store_(store), |
| + current_schema_map_(new SchemaMap), |
| + schema_update_timer_(false, false), |
|
bartfab (slow)
2013/11/15 12:20:31
Nit: If you used a OneShotTimer instead of a Timer
Joao da Silva
2013/11/15 14:58:08
Dude, I can't read code. I thought again that OneS
|
| is_initialized_(false), |
| - has_initial_keys_(false), |
| + has_credentials_(false), |
| weak_ptr_factory_(this) { |
| + schema_registry_->AddObserver(this); |
| store_->AddObserver(this); |
| + client_->AddObserver(this); |
| - backend_.reset(new Backend(weak_ptr_factory_.GetWeakPtr(), |
| - backend_task_runner_, |
| - base::MessageLoopProxy::current(), |
| - cache.Pass())); |
| - backend_task_runner_->PostTask( |
| - FROM_HERE, base::Bind(&Backend::Init, base::Unretained(backend_.get()))); |
| + external_policy_data_fetcher_backend_.reset( |
| + new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context)); |
| + |
| + backend_.reset( |
| + new Backend(weak_ptr_factory_.GetWeakPtr(), |
| + backend_task_runner_, |
| + base::MessageLoopProxy::current(), |
| + cache.Pass(), |
| + external_policy_data_fetcher_backend_->CreateFrontend( |
| + backend_task_runner_))); |
| if (store_->is_initialized()) |
| - InitializeBackend(); |
| + OnStoreLoaded(store_); |
| } |
| ComponentCloudPolicyService::~ComponentCloudPolicyService() { |
| DCHECK(CalledOnValidThread()); |
| + schema_registry_->RemoveObserver(this); |
| store_->RemoveObserver(this); |
| - if (client_) |
| - client_->RemoveObserver(this); |
| + client_->RemoveObserver(this); |
| + |
| + // Remove all the namespaces from |client_| but don't send this empty schema |
| + // to the backend, to avoid dropping the caches. |
| + if (is_initialized()) { |
| + scoped_refptr<SchemaMap> empty(new SchemaMap); |
| + SetCurrentSchema(empty, false); |
| + } |
| + |
| io_task_runner_->DeleteSoon(FROM_HERE, |
| external_policy_data_fetcher_backend_.release()); |
| backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release()); |
| @@ -287,89 +262,21 @@ bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) { |
| return ComponentCloudPolicyStore::SupportsDomain(domain); |
| } |
| -void ComponentCloudPolicyService::Connect( |
| - CloudPolicyClient* client, |
| - scoped_refptr<net::URLRequestContextGetter> request_context) { |
| - DCHECK(CalledOnValidThread()); |
| - DCHECK(!client_); |
| - client_ = client; |
| - client_->AddObserver(this); |
| - DCHECK(!external_policy_data_fetcher_backend_); |
| - external_policy_data_fetcher_backend_.reset( |
| - new ExternalPolicyDataFetcherBackend(io_task_runner_, |
| - request_context)); |
| - // Create the updater in the backend. |
| - backend_task_runner_->PostTask(FROM_HERE, base::Bind( |
| - &Backend::Connect, |
| - base::Unretained(backend_.get()), |
| - base::Passed(external_policy_data_fetcher_backend_->CreateFrontend( |
| - backend_task_runner_)))); |
| - if (is_initialized()) |
| - InitializeClient(); |
| -} |
| - |
| -void ComponentCloudPolicyService::Disconnect() { |
| - DCHECK(CalledOnValidThread()); |
| - if (client_) { |
| - // Unregister all the current components. |
| - RemoveNamespacesToFetch(keys_); |
| - |
| - client_->RemoveObserver(this); |
| - client_ = NULL; |
| - |
| - io_task_runner_->DeleteSoon( |
| - FROM_HERE, external_policy_data_fetcher_backend_.release()); |
| - backend_task_runner_->PostTask( |
| - FROM_HERE, |
| - base::Bind(&Backend::Disconnect, base::Unretained(backend_.get()))); |
| - } |
| -} |
| - |
| -void ComponentCloudPolicyService::OnSchemasUpdated( |
| - const scoped_refptr<SchemaMap>& schema_map) { |
| - DCHECK(CalledOnValidThread()); |
| - |
| - // Send the new schemas to the backend, to purge the cache. |
| - backend_task_runner_->PostTask(FROM_HERE, |
| - base::Bind(&Backend::OnSchemasUpdated, |
| - base::Unretained(backend_.get()), |
| - schema_map)); |
| - |
| - // Register the current list of components for supported domains at the |
| - // |client_|. |
| - PolicyNamespaceKeys new_keys; |
| - const DomainMap& domains = schema_map->GetDomains(); |
| - for (DomainMap::const_iterator domain = domains.begin(); |
| - domain != domains.end(); ++domain) { |
| - std::string domain_policy_type; |
| - if (!ComponentCloudPolicyStore::GetPolicyType(domain->first, |
| - &domain_policy_type)) { |
| - continue; |
| - } |
| - const ComponentMap& components = domain->second; |
| - for (ComponentMap::const_iterator comp = components.begin(); |
| - comp != components.end(); ++comp) { |
| - new_keys.insert(std::make_pair(domain_policy_type, comp->first)); |
| - } |
| - } |
| - |
| - if (client_ && is_initialized() && UpdateClientNamespaces(keys_, new_keys)) |
| - delegate_->OnComponentCloudPolicyRefreshNeeded(); |
| - |
| - keys_.swap(new_keys); |
| - has_initial_keys_ = true; |
| -} |
| - |
| void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) { |
| DCHECK(CalledOnValidThread()); |
| DCHECK_EQ(client_, client); |
| + |
| + if (!is_initialized() || !has_credentials_) |
| + return; |
| + |
| // Pass each PolicyFetchResponse whose policy type is registered to the |
| // Backend. |
| const CloudPolicyClient::ResponseMap& responses = client_->responses(); |
| for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin(); |
| it != responses.end(); ++it) { |
| - const PolicyNamespaceKey& key(it->first); |
| - if (ContainsKey(keys_, key)) { |
| + PolicyNamespace ns; |
| + if (ToPolicyNamespace(it->first, &ns) && |
| + current_schema_map_->GetSchema(ns)) { |
| scoped_ptr<em::PolicyFetchResponse> response( |
| new em::PolicyFetchResponse(*it->second)); |
| backend_task_runner_->PostTask( |
| @@ -395,16 +302,33 @@ void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) { |
| void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) { |
| DCHECK(CalledOnValidThread()); |
| DCHECK_EQ(store_, store); |
| - if (store_->is_initialized()) { |
| + |
| + if (!store_->is_initialized()) |
| + return; |
| + |
| + // Send the current credentials to the backend, if they haven't been sent |
|
bartfab (slow)
2013/11/15 12:20:31
Nit: This comment says that credentials are sent i
Joao da Silva
2013/11/15 14:58:08
Done.
|
| + // before. Usually this happens at startup if the user already had a cached |
| + // cloud policy; otherwise it happens right after the initial registration |
| + // for cloud policy. |
| + const em::PolicyData* policy = store_->policy(); |
| + if (!has_credentials_ && policy && policy->has_username() && |
| + policy->has_request_token()) { |
| + backend_task_runner_->PostTask(FROM_HERE, |
| + base::Bind(&Backend::SetCredentials, |
| + base::Unretained(backend_.get()), |
| + policy->username(), |
| + policy->request_token())); |
| + has_credentials_ = true; |
| if (is_initialized()) { |
| - // The backend is already initialized; update the credentials, in case |
| - // a new dmtoken or server key became available. |
| - SetCredentialsAndReloadClient(); |
| - } else { |
| - // The |store_| just became ready; initialize the backend now. |
| - InitializeBackend(); |
| + // This was the first policy fetch for this client. Process any |
| + // PolicyFetchResponses that the client may have now; processing them |
| + // before the credentials were sent to the backend would fail validation. |
| + OnPolicyFetched(client_); |
| } |
| } |
| + |
| + if (!is_initialized()) |
| + InitializeIfReady(); |
| } |
| void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) { |
| @@ -412,110 +336,108 @@ void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) { |
| OnStoreLoaded(store); |
| } |
| -void ComponentCloudPolicyService::InitializeBackend() { |
| +void ComponentCloudPolicyService::OnSchemaRegistryReady() { |
| + DCHECK(CalledOnValidThread()); |
| + InitializeIfReady(); |
| +} |
| + |
| +void ComponentCloudPolicyService::OnSchemaRegistryUpdated( |
| + bool has_new_schemas) { |
| DCHECK(CalledOnValidThread()); |
| - DCHECK(!is_initialized()); |
| - DCHECK(store_->is_initialized()); |
| - // Set the credentials for the initial policy load, if available. |
| - SetCredentialsAndReloadClient(); |
| + if (!is_initialized()) |
| + return; |
| - backend_task_runner_->PostTask( |
| + // When an extension is reloaded or updated, it triggers an unregister quickly |
| + // followed by a register in the SchemaRegistry. If the intermediate version |
| + // of the SchemaMap is passed to the backend then it will drop the cached |
| + // policy for that extension and will trigger a new policy fetch soon after. |
| + // Delaying the schema update here coalesces both updates into one, and the |
| + // new schema will equal the older version in case of extension updates. |
| + // |
| + // TODO(joaodasilva): Increase this delay to 10 seconds. For now it's |
| + // immediate so that tests don't get delayed. |
| + schema_update_timer_.Start( |
| FROM_HERE, |
| - base::Bind(&Backend::FinalizeInit, base::Unretained(backend_.get()))); |
| + base::TimeDelta::FromSeconds(0), |
| + base::Bind(&ComponentCloudPolicyService::SetCurrentSchema, |
| + base::Unretained(this), |
| + schema_registry_->schema_map(), |
| + true)); |
| +} |
| + |
| +void ComponentCloudPolicyService::InitializeIfReady() { |
| + DCHECK(CalledOnValidThread()); |
| + if (!schema_registry_->IsReady() || !store_->is_initialized()) |
| + return; |
| + backend_task_runner_->PostTask(FROM_HERE, |
| + base::Bind(&Backend::Init, |
| + base::Unretained(backend_.get()), |
| + schema_registry_->schema_map())); |
| } |
| void ComponentCloudPolicyService::OnBackendInitialized( |
| - scoped_ptr<PolicyNamespaceKeys> initial_keys, |
| scoped_ptr<PolicyBundle> initial_policy) { |
| DCHECK(CalledOnValidThread()); |
| - // InitializeBackend() may be called multiple times if the |store_| fires |
| - // events while the backend is loading. |
| - if (is_initialized()) |
| - return; |
| - // OnSchemasUpdated() may have been called while the backend was initializing; |
| - // in that case ignore the cached keys. |
| - if (!has_initial_keys_) |
| - keys_.swap(*initial_keys); |
| + is_initialized_ = true; |
| - // A client may have already connected while the backend was initializing. |
| - if (client_) |
| - InitializeClient(); |
| + // Send the current schema to the backend, in case it has changed while the |
| + // backend was initializing. |
| + SetCurrentSchema(schema_registry_->schema_map(), true); |
| - // Set the initial policy, and send the initial update callback. |
| - is_initialized_ = true; |
| + // Process any PolicyFetchResponses that the client may already have, or that |
| + // may have been received while the backend was initializing. |
| + OnPolicyFetched(client_); |
| + |
| + // Finally tell the Delegate that the initial policy is available. |
| OnPolicyUpdated(initial_policy.Pass()); |
| } |
| -void ComponentCloudPolicyService::InitializeClient() { |
| +void ComponentCloudPolicyService::SetCurrentSchema( |
| + const scoped_refptr<SchemaMap>& new_schema_map, |
| + bool send_to_backend) { |
| DCHECK(CalledOnValidThread()); |
| - // Register all the current components. |
| - AddNamespacesToFetch(keys_); |
| - // The client may already have PolicyFetchResponses for registered components; |
| - // load them now. |
| - OnPolicyFetched(client_); |
| - if (!keys_.empty() && is_initialized()) |
| - delegate_->OnComponentCloudPolicyRefreshNeeded(); |
| -} |
| + DCHECK(is_initialized()); |
| -void ComponentCloudPolicyService::OnPolicyUpdated( |
| - scoped_ptr<PolicyBundle> policy) { |
| - DCHECK(CalledOnValidThread()); |
| - policy_.Swap(policy.get()); |
| - // Don't propagate updates until the initial store Load() has been done. |
| - if (is_initialized()) |
| - delegate_->OnComponentCloudPolicyUpdated(); |
| -} |
| + scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList); |
| + PolicyNamespaceList added; |
| + new_schema_map->GetChanges(current_schema_map_, removed.get(), &added); |
| -void ComponentCloudPolicyService::SetCredentialsAndReloadClient() { |
| - DCHECK(CalledOnValidThread()); |
| - const em::PolicyData* policy = store_->policy(); |
| - if (!policy || !policy->has_username() || !policy->has_request_token()) |
| - return; |
| - backend_task_runner_->PostTask(FROM_HERE, |
| - base::Bind(&Backend::SetCredentials, |
| - base::Unretained(backend_.get()), |
| - policy->username(), |
| - policy->request_token())); |
| - // If this was the initial register, or if the signing key changed, then the |
| - // previous OnPolicyFetched() call had its PolicyFetchResponses rejected |
| - // because the credentials weren't updated yet. Reload all the responses in |
| - // the client now to handle those cases; if those responses have already been |
| - // validated then they will be ignored. |
| - if (client_) |
| - OnPolicyFetched(client_); |
| -} |
| + current_schema_map_ = new_schema_map; |
| -bool ComponentCloudPolicyService::UpdateClientNamespaces( |
| - const PolicyNamespaceKeys& old_keys, |
| - const PolicyNamespaceKeys& new_keys) { |
| - DCHECK(CalledOnValidThread()); |
| - PolicyNamespaceKeys added = |
| - base::STLSetDifference<PolicyNamespaceKeys>(new_keys, old_keys); |
| - PolicyNamespaceKeys removed = |
| - base::STLSetDifference<PolicyNamespaceKeys>(old_keys, new_keys); |
| - AddNamespacesToFetch(added); |
| - RemoveNamespacesToFetch(removed); |
| - return !added.empty(); |
| -} |
| + for (size_t i = 0; i < removed->size(); ++i) { |
| + PolicyNamespaceKey key; |
| + if (ToPolicyNamespaceKey((*removed)[i], &key)) |
| + client_->RemoveNamespaceToFetch(key); |
| + } |
| -void ComponentCloudPolicyService::AddNamespacesToFetch( |
| - const PolicyNamespaceKeys& keys) { |
| - DCHECK(CalledOnValidThread()); |
| - for (PolicyNamespaceKeys::const_iterator it = keys.begin(); |
| - it != keys.end(); ++it) { |
| - client_->AddNamespaceToFetch(*it); |
| + bool added_namespaces_to_client = false; |
| + for (size_t i = 0; i < added.size(); ++i) { |
| + PolicyNamespaceKey key; |
| + if (ToPolicyNamespaceKey(added[i], &key)) { |
| + client_->AddNamespaceToFetch(key); |
| + added_namespaces_to_client = true; |
| + } |
| + } |
| + |
| + if (added_namespaces_to_client) |
| + delegate_->OnComponentCloudPolicyRefreshNeeded(); |
| + |
| + if (send_to_backend) { |
| + backend_task_runner_->PostTask(FROM_HERE, |
| + base::Bind(&Backend::OnSchemasUpdated, |
| + base::Unretained(backend_.get()), |
| + current_schema_map_, |
| + base::Passed(&removed))); |
| } |
| } |
| -void ComponentCloudPolicyService::RemoveNamespacesToFetch( |
| - const PolicyNamespaceKeys& keys) { |
| +void ComponentCloudPolicyService::OnPolicyUpdated( |
| + scoped_ptr<PolicyBundle> policy) { |
| DCHECK(CalledOnValidThread()); |
| - for (PolicyNamespaceKeys::const_iterator it = keys.begin(); |
| - it != keys.end(); ++it) { |
| - client_->RemoveNamespaceToFetch(*it); |
| - } |
| + policy_.Swap(policy.get()); |
| + delegate_->OnComponentCloudPolicyUpdated(); |
| } |
| } // namespace policy |