component_cloud_policy_service.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/component_cloud_policy_service.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <string>
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/sequenced_task_runner.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_constants.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/component_cloud_policy_store.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/component_cloud_policy_updater.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/external_policy_data_fetcher.h"
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/resource_cache.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/schema.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/schema_map.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/proto/device_management_backend.pb.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace em = enterprise_management;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace policy {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool NotInSchemaMap(const scoped_refptr<SchemaMap> schema_map,
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    PolicyDomain domain,
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    const std::string& component_id) {
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return schema_map->GetSchema(PolicyNamespace(domain, component_id)) == NULL;
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ToPolicyNamespaceKey(const PolicyNamespace& ns, PolicyNamespaceKey* key) {
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ComponentCloudPolicyStore::GetPolicyType(ns.domain, &key->first))
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  key->second = ns.component_id;
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ToPolicyNamespace(const PolicyNamespaceKey& key, PolicyNamespace* ns) {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ComponentCloudPolicyStore::GetPolicyDomain(key.first, &ns->domain))
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ns->component_id = key.second;
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::Delegate::~Delegate() {}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Owns the objects that live on the background thread, and posts back to the
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// thread that the ComponentCloudPolicyService runs on whenever the policy
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// changes.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ComponentCloudPolicyService::Backend
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public ComponentCloudPolicyStore::Delegate {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // This class can be instantiated on any thread but from then on, may be
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // accessed via the |task_runner_| only. Policy changes are posted to the
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |service| via the |service_task_runner|. The |cache| is used to load and
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // store local copies of the downloaded policies.
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Backend(base::WeakPtr<ComponentCloudPolicyService> service,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          scoped_refptr<base::SequencedTaskRunner> task_runner,
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          scoped_refptr<base::SequencedTaskRunner> service_task_runner,
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          scoped_ptr<ResourceCache> cache,
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~Backend();
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |username| and |dm_token| will be  used to validate the cached policies.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetCredentials(const std::string& username, const std::string& dm_token);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Loads the |store_| and starts downloading updates.
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void Init(scoped_refptr<SchemaMap> schema_map);
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Passes a policy protobuf to the backend, to start its validation and
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // eventual download of the policy data on the background thread.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UpdateExternalPolicy(scoped_ptr<em::PolicyFetchResponse> response);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ComponentCloudPolicyStore::Delegate implementation:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnComponentCloudPolicyStoreUpdated() OVERRIDE;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Passes the current SchemaMap so that the disk cache can purge components
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // that aren't being tracked anymore.
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |removed| is a list of namespaces that were present in the previous
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // schema and have been removed in the updated version.
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void OnSchemasUpdated(scoped_refptr<SchemaMap> schema_map,
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        scoped_ptr<PolicyNamespaceList> removed);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The ComponentCloudPolicyService that owns |this|. Used to inform the
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |service_| when policy changes.
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WeakPtr<ComponentCloudPolicyService> service_;
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The thread that |this| runs on. Used to post tasks to be run by |this|.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> task_runner_;
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The thread that the |service_| runs on. Used to post policy changes to the
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // right thread.
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ResourceCache> cache_;
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher_;
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ComponentCloudPolicyStore store_;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ComponentCloudPolicyUpdater> updater_;
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<SchemaMap> schema_map_;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Backend);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::Backend::Backend(
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<ComponentCloudPolicyService> service,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> task_runner,
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> service_task_runner,
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<ResourceCache> cache,
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : service_(service),
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      task_runner_(task_runner),
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      service_task_runner_(service_task_runner),
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cache_(cache.Pass()),
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      external_policy_data_fetcher_(external_policy_data_fetcher.Pass()),
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      store_(this, cache_.get()) {}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::Backend::~Backend() {}
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::Backend::SetCredentials(
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& username,
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& dm_token) {
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (username.empty() || dm_token.empty()) {
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // No sign-in credentials, so drop any cached policy.
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    store_.Clear();
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    store_.SetCredentials(username, dm_token);
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::Backend::Init(
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<SchemaMap> schema_map) {
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!schema_map_);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>());
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Read the initial policy. Note that this does not trigger notifications
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // through OnComponentCloudPolicyStoreUpdated. Note also that the cached
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // data may contain names or values that don't match the schema for that
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // component; the data must be cached without modifications so that its
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // integrity can be verified using the hash, but it must also be filtered
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // right after a Load().
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  store_.Load();
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle->CopyFrom(store_.policy());
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_map_->FilterBundle(bundle.get());
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start downloading any pending data.
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  updater_.reset(new ComponentCloudPolicyUpdater(
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      task_runner_, external_policy_data_fetcher_.Pass(), &store_));
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service_task_runner_->PostTask(
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FROM_HERE,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ComponentCloudPolicyService::OnBackendInitialized,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 service_,
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 base::Passed(&bundle)));
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::Backend::UpdateExternalPolicy(
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<em::PolicyFetchResponse> response) {
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  updater_->UpdateExternalPolicy(response.Pass());
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::Backend::
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnComponentCloudPolicyStoreUpdated() {
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!schema_map_) {
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Ignore notifications triggered by the initial Purge or Clear.
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle->CopyFrom(store_.policy());
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_map_->FilterBundle(bundle.get());
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service_task_runner_->PostTask(
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FROM_HERE,
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated,
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 service_,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Passed(&bundle)));
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::Backend::OnSchemasUpdated(
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<SchemaMap> schema_map,
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<PolicyNamespaceList> removed) {
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Purge any components that have been removed.
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const DomainMap& domains = schema_map->GetDomains();
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (DomainMap::const_iterator domain = domains.begin();
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       domain != domains.end(); ++domain) {
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    store_.Purge(domain->first,
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 base::Bind(&NotInSchemaMap, schema_map, domain->first));
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Set |schema_map_| after purging so that the notifications from the store
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // are ignored on the first OnSchemasUpdated() call from Init().
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_map_ = schema_map;
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (removed) {
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t i = 0; i < removed->size(); ++i)
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      updater_->CancelUpdate((*removed)[i]);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::ComponentCloudPolicyService(
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Delegate* delegate,
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    SchemaRegistry* schema_registry,
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CloudPolicyCore* core,
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_ptr<ResourceCache> cache,
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> request_context,
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : delegate_(delegate),
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      schema_registry_(schema_registry),
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      core_(core),
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      request_context_(request_context),
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      backend_task_runner_(backend_task_runner),
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      io_task_runner_(io_task_runner),
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      current_schema_map_(new SchemaMap),
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      started_loading_initial_policy_(false),
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      loaded_initial_policy_(false),
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      is_registered_for_cloud_policy_(false),
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  external_policy_data_fetcher_backend_.reset(
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context));
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  backend_.reset(
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new Backend(weak_ptr_factory_.GetWeakPtr(),
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  backend_task_runner_,
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  base::MessageLoopProxy::current(),
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  cache.Pass(),
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  external_policy_data_fetcher_backend_->CreateFrontend(
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      backend_task_runner_)));
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_registry_->AddObserver(this);
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->store()->AddObserver(this);
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Wait for the store and the schema registry to become ready before
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // initializing the backend, so that it can get the initial list of
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // components and the cached credentials (if any) to validate the cached
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // policies.
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core_->store()->is_initialized())
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnStoreLoaded(core_->store());
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::~ComponentCloudPolicyService() {
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_registry_->RemoveObserver(this);
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->store()->RemoveObserver(this);
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->RemoveObserver(this);
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core_->client())
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnCoreDisconnecting(core_);
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  io_task_runner_->DeleteSoon(FROM_HERE,
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              external_policy_data_fetcher_backend_.release());
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ComponentCloudPolicyStore::SupportsDomain(domain);
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ComponentCloudPolicyService::ClearCache() {
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(CalledOnValidThread());
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Empty credentials will wipe the cache.
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 base::Bind(&Backend::SetCredentials,
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            base::Unretained(backend_.get()),
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            std::string(), std::string()));
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnSchemaRegistryReady() {
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitializeIfReady();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnSchemaRegistryUpdated(
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool has_new_schemas) {
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ignore schema updates until the backend is initialized.
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // OnBackendInitialized() will send the current schema to the backend again,
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // in case it was updated before the backend initialized.
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!loaded_initial_policy_)
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetCurrentSchema();
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnCoreConnected(CloudPolicyCore* core) {
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_, core);
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->client()->AddObserver(this);
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Immediately load any PolicyFetchResponses that the client may already
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // have.
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnPolicyFetched(core_->client());
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Register the current namespaces at the client.
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  current_schema_map_ = new SchemaMap();
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SetCurrentSchema();
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnCoreDisconnecting(CloudPolicyCore* core) {
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_, core);
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->client()->RemoveObserver(this);
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Remove all the namespaces from the client.
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<SchemaMap> empty = new SchemaMap();
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PolicyNamespaceList removed;
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PolicyNamespaceList added;
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  empty->GetChanges(current_schema_map_, &removed, &added);
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < removed.size(); ++i) {
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PolicyNamespaceKey key;
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (ToPolicyNamespaceKey(removed[i], &key))
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      core_->client()->RemoveNamespaceToFetch(key);
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnRefreshSchedulerStarted(
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CloudPolicyCore* core) {
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ignored.
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_->store(), store);
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const bool was_registered_before = is_registered_for_cloud_policy_;
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Send the current credentials to the backend; do this whenever the store
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // updates, to handle the case of the user registering for policy after the
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // session starts, or the user signing out.
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const em::PolicyData* policy = core_->store()->policy();
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string username;
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string request_token;
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (policy && policy->has_username() && policy->has_request_token()) {
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    is_registered_for_cloud_policy_ = true;
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    username = policy->username();
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    request_token = policy->request_token();
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    is_registered_for_cloud_policy_ = false;
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Empty credentials will wipe the cache.
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 base::Bind(&Backend::SetCredentials,
36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            base::Unretained(backend_.get()),
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            username,
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            request_token));
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!loaded_initial_policy_) {
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // This is the initial load; check if we're ready to initialize the
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // backend, regardless of the signin state.
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InitializeIfReady();
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else if (!was_registered_before && is_registered_for_cloud_policy_) {
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We are already initialized, but just sent credentials to the backend for
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // the first time; this means that the user was not registered for cloud
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // policy on startup but registered during the session.
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    //
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // When that happens, OnPolicyFetched() is sent to observers before the
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // CloudPolicyStore gets a chance to verify the user policy. In those cases,
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // the backend gets the PolicyFetchResponses before it has the credentials
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // and therefore the validation of those responses fails.
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Reload any PolicyFetchResponses that the client may have now so that
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // validation is retried with the credentials in place.
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (core_->client())
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      OnPolicyFetched(core_->client());
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) {
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnStoreLoaded(store);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) {
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_->client(), client);
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!is_registered_for_cloud_policy_) {
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Trying to load any policies now will fail validation. An OnStoreLoaded()
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // notification should follow soon, after the main user policy has been
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // validated and stored.
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Pass each PolicyFetchResponse whose policy type is registered to the
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Backend.
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const CloudPolicyClient::ResponseMap& responses =
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      core_->client()->responses();
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin();
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != responses.end(); ++it) {
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PolicyNamespace ns;
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (ToPolicyNamespace(it->first, &ns) &&
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        current_schema_map_->GetSchema(ns)) {
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<em::PolicyFetchResponse> response(
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new em::PolicyFetchResponse(*it->second));
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      backend_task_runner_->PostTask(
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          FROM_HERE,
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          base::Bind(&Backend::UpdateExternalPolicy,
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     base::Unretained(backend_.get()),
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     base::Passed(&response)));
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnRegistrationStateChanged(
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CloudPolicyClient* client) {
42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ignored; the registration state is tracked by looking at the
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // CloudPolicyStore instead.
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) {
42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ignored.
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::InitializeIfReady() {
43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (started_loading_initial_policy_ || !schema_registry_->IsReady() ||
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      !core_->store()->is_initialized()) {
436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The initial list of components is ready. Initialize the backend now, which
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // will call back to OnBackendInitialized.
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 base::Bind(&Backend::Init,
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            base::Unretained(backend_.get()),
443f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            schema_registry_->schema_map()));
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  started_loading_initial_policy_ = true;
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnBackendInitialized(
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<PolicyBundle> initial_policy) {
44958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!loaded_initial_policy_);
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  loaded_initial_policy_ = true;
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We're now ready to serve the initial policy; notify the policy observers.
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnPolicyUpdated(initial_policy.Pass());
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start observing the core and tracking the state of the client.
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->AddObserver(this);
459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core_->client()) {
461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnCoreConnected(core_);
462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Send the current schema to the backend, in case it has changed while the
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // backend was initializing. OnCoreConnected() also does this if a client is
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // already connected.
466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    SetCurrentSchema();
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::SetCurrentSchema() {
47158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList);
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PolicyNamespaceList added;
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const scoped_refptr<SchemaMap>& new_schema_map =
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      schema_registry_->schema_map();
477f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  new_schema_map->GetChanges(current_schema_map_, removed.get(), &added);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  current_schema_map_ = new_schema_map;
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core_->client()) {
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t i = 0; i < removed->size(); ++i) {
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      PolicyNamespaceKey key;
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (ToPolicyNamespaceKey((*removed)[i], &key))
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        core_->client()->RemoveNamespaceToFetch(key);
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool added_namespaces_to_client = false;
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t i = 0; i < added.size(); ++i) {
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      PolicyNamespaceKey key;
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (ToPolicyNamespaceKey(added[i], &key)) {
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        core_->client()->AddNamespaceToFetch(key);
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        added_namespaces_to_client = true;
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (added_namespaces_to_client)
498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      core_->RefreshSoon();
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
502f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 base::Bind(&Backend::OnSchemasUpdated,
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            base::Unretained(backend_.get()),
504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            current_schema_map_,
505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            base::Passed(&removed)));
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnPolicyUpdated(
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<PolicyBundle> policy) {
51058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  policy_.Swap(policy.get());
512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_->OnComponentCloudPolicyUpdated();
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace policy
516