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 ToPolicyNamespace(const PolicyNamespaceKey& key, PolicyNamespace* ns) {
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ComponentCloudPolicyStore::GetPolicyDomain(key.first, &ns->domain))
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ns->component_id = key.second;
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::Delegate::~Delegate() {}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Owns the objects that live on the background thread, and posts back to the
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// thread that the ComponentCloudPolicyService runs on whenever the policy
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// changes.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ComponentCloudPolicyService::Backend
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public ComponentCloudPolicyStore::Delegate {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // This class can be instantiated on any thread but from then on, may be
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // accessed via the |task_runner_| only. Policy changes are posted to the
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |service| via the |service_task_runner|. The |cache| is used to load and
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // store local copies of the downloaded policies.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Backend(base::WeakPtr<ComponentCloudPolicyService> service,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          scoped_refptr<base::SequencedTaskRunner> task_runner,
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          scoped_refptr<base::SequencedTaskRunner> service_task_runner,
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          scoped_ptr<ResourceCache> cache,
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~Backend();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |username| and |dm_token| will be  used to validate the cached policies.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetCredentials(const std::string& username, const std::string& dm_token);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Loads the |store_| and starts downloading updates.
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void Init(scoped_refptr<SchemaMap> schema_map);
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Passes a policy protobuf to the backend, to start its validation and
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // eventual download of the policy data on the background thread.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UpdateExternalPolicy(scoped_ptr<em::PolicyFetchResponse> response);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ComponentCloudPolicyStore::Delegate implementation:
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnComponentCloudPolicyStoreUpdated() OVERRIDE;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Passes the current SchemaMap so that the disk cache can purge components
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // that aren't being tracked anymore.
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |removed| is a list of namespaces that were present in the previous
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // schema and have been removed in the updated version.
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void OnSchemasUpdated(scoped_refptr<SchemaMap> schema_map,
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        scoped_ptr<PolicyNamespaceList> removed);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The ComponentCloudPolicyService that owns |this|. Used to inform the
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |service_| when policy changes.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WeakPtr<ComponentCloudPolicyService> service_;
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The thread that |this| runs on. Used to post tasks to be run by |this|.
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> task_runner_;
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The thread that the |service_| runs on. Used to post policy changes to the
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // right thread.
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ResourceCache> cache_;
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher_;
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ComponentCloudPolicyStore store_;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ComponentCloudPolicyUpdater> updater_;
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool initialized_;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Backend);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::Backend::Backend(
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<ComponentCloudPolicyService> service,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> task_runner,
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> service_task_runner,
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<ResourceCache> cache,
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : service_(service),
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      task_runner_(task_runner),
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      service_task_runner_(service_task_runner),
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cache_(cache.Pass()),
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      external_policy_data_fetcher_(external_policy_data_fetcher.Pass()),
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      store_(this, cache_.get()),
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      initialized_(false) {}
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::Backend::~Backend() {}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::Backend::SetCredentials(
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& username,
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& dm_token) {
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (username.empty() || dm_token.empty()) {
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // No sign-in credentials, so drop any cached policy.
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    store_.Clear();
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    store_.SetCredentials(username, dm_token);
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::Backend::Init(
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<SchemaMap> schema_map) {
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!initialized_);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>());
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Read the initial policy. Note that this does not trigger notifications
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // through OnComponentCloudPolicyStoreUpdated. Note also that the cached
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // data may contain names or values that don't match the schema for that
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // component; the data must be cached without modifications so that its
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // integrity can be verified using the hash, but it must also be filtered
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // right after a Load().
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  store_.Load();
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle->CopyFrom(store_.policy());
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start downloading any pending data.
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  updater_.reset(new ComponentCloudPolicyUpdater(
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      task_runner_, external_policy_data_fetcher_.Pass(), &store_));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service_task_runner_->PostTask(
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FROM_HERE,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ComponentCloudPolicyService::OnBackendInitialized,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 service_,
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 base::Passed(&bundle)));
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  initialized_ = true;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::Backend::UpdateExternalPolicy(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<em::PolicyFetchResponse> response) {
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  updater_->UpdateExternalPolicy(response.Pass());
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::Backend::
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnComponentCloudPolicyStoreUpdated() {
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!initialized_) {
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Ignore notifications triggered by the initial Purge or Clear.
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle->CopyFrom(store_.policy());
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service_task_runner_->PostTask(
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FROM_HERE,
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated,
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 service_,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Passed(&bundle)));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::Backend::OnSchemasUpdated(
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<SchemaMap> schema_map,
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<PolicyNamespaceList> removed) {
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Purge any components that have been removed.
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const DomainMap& domains = schema_map->GetDomains();
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (DomainMap::const_iterator domain = domains.begin();
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       domain != domains.end(); ++domain) {
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    store_.Purge(domain->first,
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 base::Bind(&NotInSchemaMap, schema_map, domain->first));
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (removed) {
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t i = 0; i < removed->size(); ++i)
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      updater_->CancelUpdate((*removed)[i]);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::ComponentCloudPolicyService(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Delegate* delegate,
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    SchemaRegistry* schema_registry,
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CloudPolicyCore* core,
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_ptr<ResourceCache> cache,
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> request_context,
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : delegate_(delegate),
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      schema_registry_(schema_registry),
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      core_(core),
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      request_context_(request_context),
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      backend_task_runner_(backend_task_runner),
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      io_task_runner_(io_task_runner),
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      current_schema_map_(new SchemaMap),
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      unfiltered_policy_(new PolicyBundle),
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      started_loading_initial_policy_(false),
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      loaded_initial_policy_(false),
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      is_registered_for_cloud_policy_(false),
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  external_policy_data_fetcher_backend_.reset(
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context));
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  backend_.reset(
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new Backend(weak_ptr_factory_.GetWeakPtr(),
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  backend_task_runner_,
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  base::MessageLoopProxy::current(),
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  cache.Pass(),
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  external_policy_data_fetcher_backend_->CreateFrontend(
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      backend_task_runner_)));
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_registry_->AddObserver(this);
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->store()->AddObserver(this);
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Wait for the store and the schema registry to become ready before
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // initializing the backend, so that it can get the initial list of
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // components and the cached credentials (if any) to validate the cached
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // policies.
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core_->store()->is_initialized())
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnStoreLoaded(core_->store());
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Start observing the core and tracking the state of the client.
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  core_->AddObserver(this);
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (core_->client())
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    OnCoreConnected(core_);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ComponentCloudPolicyService::~ComponentCloudPolicyService() {
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema_registry_->RemoveObserver(this);
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->store()->RemoveObserver(this);
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->RemoveObserver(this);
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (core_->client())
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnCoreDisconnecting(core_);
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  io_task_runner_->DeleteSoon(FROM_HERE,
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              external_policy_data_fetcher_backend_.release());
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ComponentCloudPolicyStore::SupportsDomain(domain);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ComponentCloudPolicyService::ClearCache() {
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(CalledOnValidThread());
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Empty credentials will wipe the cache.
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 base::Bind(&Backend::SetCredentials,
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            base::Unretained(backend_.get()),
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            std::string(), std::string()));
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnSchemaRegistryReady() {
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitializeIfReady();
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnSchemaRegistryUpdated(
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool has_new_schemas) {
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ignore schema updates until the backend is initialized.
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // OnBackendInitialized() will send the current schema to the backend again,
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // in case it was updated before the backend initialized.
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!loaded_initial_policy_)
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ReloadSchema();
293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Filter the |unfiltered_policy_| again, now that |current_schema_map_| has
295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // been updated. We must make sure we never serve invalid policy; we must
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // also filter again if an invalid Schema has now been loaded.
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  OnPolicyUpdated(unfiltered_policy_.Pass());
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnCoreConnected(CloudPolicyCore* core) {
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_, core);
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->client()->AddObserver(this);
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Register the supported policy domains at the client.
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  core_->client()->AddNamespaceToFetch(
3085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType, ""));
3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Immediately load any PolicyFetchResponses that the client may already
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // have if the backend is ready.
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (loaded_initial_policy_)
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    OnPolicyFetched(core_->client());
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnCoreDisconnecting(CloudPolicyCore* core) {
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_, core);
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  core_->client()->RemoveObserver(this);
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Remove all the namespaces from the client.
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  core_->client()->RemoveNamespaceToFetch(
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType, ""));
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnRefreshSchedulerStarted(
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CloudPolicyCore* core) {
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ignored.
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_->store(), store);
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const bool was_registered_before = is_registered_for_cloud_policy_;
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Send the current credentials to the backend; do this whenever the store
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // updates, to handle the case of the user registering for policy after the
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // session starts, or the user signing out.
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const em::PolicyData* policy = core_->store()->policy();
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string username;
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string request_token;
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (policy && policy->has_username() && policy->has_request_token()) {
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    is_registered_for_cloud_policy_ = true;
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    username = policy->username();
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    request_token = policy->request_token();
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    is_registered_for_cloud_policy_ = false;
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Empty credentials will wipe the cache.
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 base::Bind(&Backend::SetCredentials,
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            base::Unretained(backend_.get()),
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            username,
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            request_token));
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!loaded_initial_policy_) {
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // This is the initial load; check if we're ready to initialize the
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // backend, regardless of the signin state.
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InitializeIfReady();
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else if (!was_registered_before && is_registered_for_cloud_policy_) {
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We are already initialized, but just sent credentials to the backend for
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // the first time; this means that the user was not registered for cloud
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // policy on startup but registered during the session.
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    //
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // When that happens, OnPolicyFetched() is sent to observers before the
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // CloudPolicyStore gets a chance to verify the user policy. In those cases,
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // the backend gets the PolicyFetchResponses before it has the credentials
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // and therefore the validation of those responses fails.
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Reload any PolicyFetchResponses that the client may have now so that
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // validation is retried with the credentials in place.
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (core_->client())
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      OnPolicyFetched(core_->client());
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) {
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnStoreLoaded(store);
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) {
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(core_->client(), client);
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!is_registered_for_cloud_policy_) {
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Trying to load any policies now will fail validation. An OnStoreLoaded()
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // notification should follow soon, after the main user policy has been
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // validated and stored.
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Pass each PolicyFetchResponse whose policy type is registered to the
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Backend.
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const CloudPolicyClient::ResponseMap& responses =
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      core_->client()->responses();
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin();
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != responses.end(); ++it) {
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    PolicyNamespace ns;
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (ToPolicyNamespace(it->first, &ns) &&
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        current_schema_map_->GetSchema(ns)) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<em::PolicyFetchResponse> response(
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new em::PolicyFetchResponse(*it->second));
40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      backend_task_runner_->PostTask(
40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          FROM_HERE,
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          base::Bind(&Backend::UpdateExternalPolicy,
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     base::Unretained(backend_.get()),
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     base::Passed(&response)));
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnRegistrationStateChanged(
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CloudPolicyClient* client) {
41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Ignored; the registration state is tracked by looking at the
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // CloudPolicyStore instead.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) {
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ignored.
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::InitializeIfReady() {
42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (started_loading_initial_policy_ || !schema_registry_->IsReady() ||
430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      !core_->store()->is_initialized()) {
431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The initial list of components is ready. Initialize the backend now, which
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // will call back to OnBackendInitialized.
436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 base::Bind(&Backend::Init,
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            base::Unretained(backend_.get()),
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            schema_registry_->schema_map()));
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  started_loading_initial_policy_ = true;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ComponentCloudPolicyService::OnBackendInitialized(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<PolicyBundle> initial_policy) {
44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!loaded_initial_policy_);
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  loaded_initial_policy_ = true;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Send the current schema to the backend, in case it has changed while the
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // backend was initializing.
4525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ReloadSchema();
4535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // We're now ready to serve the initial policy; notify the policy observers.
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  OnPolicyUpdated(initial_policy.Pass());
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ComponentCloudPolicyService::ReloadSchema() {
45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList);
462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PolicyNamespaceList added;
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const scoped_refptr<SchemaMap>& new_schema_map =
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      schema_registry_->schema_map();
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  new_schema_map->GetChanges(current_schema_map_, removed.get(), &added);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  current_schema_map_ = new_schema_map;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Send the updated SchemaMap and a list of removed components to the
4705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // backend.
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  backend_task_runner_->PostTask(FROM_HERE,
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 base::Bind(&Backend::OnSchemasUpdated,
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            base::Unretained(backend_.get()),
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            current_schema_map_,
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            base::Passed(&removed)));
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Have another look at the client if the core is already connected.
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The client may have already fetched policy for some component and it was
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // previously ignored because the component wasn't listed in the schema map.
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // There's no point in fetching policy from the server again; the server
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // always pushes all the components it knows about.
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (core_->client())
483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    OnPolicyFetched(core_->client());
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ComponentCloudPolicyService::OnPolicyUpdated(
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<PolicyBundle> policy) {
48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Store the current unfiltered policies.
491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  unfiltered_policy_ = policy.Pass();
492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Make a copy in |policy_| and filter it; this is what's passed to the
494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // outside world.
495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  policy_.CopyFrom(*unfiltered_policy_);
496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  current_schema_map_->FilterBundle(&policy_);
497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_->OnComponentCloudPolicyUpdated();
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace policy
502