cloud_external_data_manager_base.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
13240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
23240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
33240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// found in the LICENSE file.
43240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base.h"
63240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
73240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <map>
83240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <string>
93240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <vector>
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/bind.h"
123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/bind_helpers.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback.h"
143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/location.h"
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/logging.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/sequenced_task_runner.h"
183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/strings/string_number_conversions.h"
193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/values.h"
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/chromeos/policy/cloud_external_data_store.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_store.h"
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/external_policy_data_fetcher.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/external_policy_data_updater.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/external_data_fetcher.h"
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_map.h"
263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "net/url_request/url_request_context_getter.h"
273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochnamespace policy {
293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochnamespace {
313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Fetch data for at most two external data references at the same time.
333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochconst int kMaxParallelFetches = 2;
343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Allows policies to reference |max_external_data_size_for_testing| bytes of
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// external data even if no |max_size| was specified in policy_templates.json.
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int max_external_data_size_for_testing = 0;
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}  // namespace
403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Backend for the CloudExternalDataManagerBase that handles all data download,
423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// verification, caching and retrieval.
433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochclass CloudExternalDataManagerBase::Backend {
443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch public:
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |get_policy_details| is used to determine the maximum size that the
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // data referenced by each policy can have. This class can be instantiated on
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // any thread but from then on, may be accessed via the |task_runner_| only.
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // All FetchCallbacks will be invoked via |callback_task_runner|.
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Backend(const GetChromePolicyDetailsCallback& get_policy_details,
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          scoped_refptr<base::SequencedTaskRunner> task_runner,
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Allows downloaded external data to be cached in |external_data_store|.
543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Ownership of the store is taken. The store can be destroyed by calling
553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // SetExternalDataStore(scoped_ptr<CloudExternalDataStore>()).
563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void SetExternalDataStore(
573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      scoped_ptr<CloudExternalDataStore> external_data_store);
583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Allows downloading of external data via the |external_policy_data_fetcher|.
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void Connect(
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher);
623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Prevents further external data downloads and aborts any downloads currently
643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // in progress
653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void Disconnect();
663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Called when the external data references that this backend is responsible
683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // for change. |metadata| maps from policy names to the metadata specifying
693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // the external data that each of the policies references.
703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void OnMetadataUpdated(scoped_ptr<Metadata> metadata);
713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Called by the |updater_| when the external |data| referenced by |policy|
733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // has been successfully downloaded and verified to match |hash|.
743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  bool OnDownloadSuccess(const std::string& policy,
753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                         const std::string& hash,
763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                         const std::string& data);
773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Retrieves the external data referenced by |policy| and invokes |callback|
793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // with the result. If |policy| does not reference any external data, the
803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // |callback| is invoked with a NULL pointer. Otherwise, the |callback| is
813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // invoked with the referenced data once it has been successfully retrieved.
823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // If retrieval is temporarily impossible (e.g. the data is not cached yet and
833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // there is no network connectivity), the |callback| will be invoked when the
843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // temporary hindrance is resolved. If retrieval is permanently impossible
853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // (e.g. |policy| references data that does not exist on the server), the
863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // |callback| will never be invoked.
873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // If the data for |policy| is not cached yet, only one download is started,
883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // even if this method is invoked multiple times. The |callback|s passed are
893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // enqueued and all invoked once the data has been successfully retrieved.
903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void Fetch(const std::string& policy,
913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch             const ExternalDataFetcher::FetchCallback& callback);
923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Try to download and cache all external data referenced by |metadata_|.
943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void FetchAll();
953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch private:
973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // List of callbacks to invoke when the attempt to retrieve external data
983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // referenced by a policy completes successfully or fails permanently.
993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  typedef std::vector<ExternalDataFetcher::FetchCallback> FetchCallbackList;
1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Map from policy names to the lists of callbacks defined above.
1023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  typedef std::map<std::string, FetchCallbackList> FetchCallbackMap;
1033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Looks up the maximum size that the data referenced by |policy| can have.
1053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t GetMaxExternalDataSize(const std::string& policy) const;
1063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Invokes |callback| via the |callback_task_runner_|, passing |data| as a
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // parameter.
1093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void RunCallback(const ExternalDataFetcher::FetchCallback& callback,
1103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                   scoped_ptr<std::string> data) const;
1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Tells the |updater_| to download the external data referenced by |policy|.
1133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // If Connect() was not called yet and no |updater_| exists, does nothing.
1143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void StartDownload(const std::string& policy);
1153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Used to determine the maximum size that the data referenced by each policy
1173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // can have.
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetChromePolicyDetailsCallback get_policy_details_;
1193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_refptr<base::SequencedTaskRunner> task_runner_;
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
1223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Contains the policies for which a download of the referenced external data
1243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // has been requested. Each policy is mapped to a list of callbacks to invoke
1253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // when the download completes successfully or fails permanently. If no
1263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // callback needs to be invoked (because the download was requested via
1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // FetchAll()), a map entry will still exist but the list of callbacks it maps
1283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // to will be empty.
1293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  FetchCallbackMap pending_downloads_;
1303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Indicates that OnMetadataUpdated() has been called at least once and the
1323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // contents of |metadata_| is initialized.
1333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  bool metadata_set_;
1343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Maps from policy names to the metadata specifying the external data that
1363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // each of the policies references.
1373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Metadata metadata_;
1383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Used to cache external data referenced by policies.
1403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<CloudExternalDataStore> external_data_store_;
1413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Used to download external data referenced by policies.
1433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<ExternalPolicyDataUpdater> updater_;
1443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(Backend);
1463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch};
1473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochCloudExternalDataManagerBase::Backend::Backend(
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const GetChromePolicyDetailsCallback& get_policy_details,
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> task_runner,
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> callback_task_runner)
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : get_policy_details_(get_policy_details),
1533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      task_runner_(task_runner),
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback_task_runner_(callback_task_runner),
1553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      metadata_set_(false) {
1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::SetExternalDataStore(
1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<CloudExternalDataStore> external_data_store) {
1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  external_data_store_.reset(external_data_store.release());
1613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (metadata_set_ && external_data_store_)
1623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    external_data_store_->Prune(metadata_);
1633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::Connect(
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher) {
1673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(!updater_);
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  updater_.reset(new ExternalPolicyDataUpdater(
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      task_runner_,
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      external_policy_data_fetcher.Pass(),
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kMaxParallelFetches));
1723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (FetchCallbackMap::const_iterator it = pending_downloads_.begin();
1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != pending_downloads_.end(); ++it) {
1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    StartDownload(it->first);
1753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::Disconnect() {
1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  updater_.reset();
1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::OnMetadataUpdated(
1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<Metadata> metadata) {
1843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  metadata_set_ = true;
1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Metadata old_metadata;
1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  metadata_.swap(old_metadata);
1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (metadata)
1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    metadata_.swap(*metadata);
1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (external_data_store_)
1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    external_data_store_->Prune(metadata_);
1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (FetchCallbackMap::iterator it = pending_downloads_.begin();
1943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != pending_downloads_.end(); ) {
1953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string policy = it->first;
1963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    Metadata::const_iterator metadata = metadata_.find(policy);
1973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (metadata == metadata_.end()) {
1983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // |policy| no longer references external data.
1993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (updater_) {
2003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        // Cancel the external data download.
2013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        updater_->CancelExternalDataFetch(policy);
2023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
2033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      for (FetchCallbackList::const_iterator callback = it->second.begin();
2043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch           callback != it->second.end(); ++callback) {
2053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        // Invoke all callbacks for |policy|, indicating permanent failure.
2063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        RunCallback(*callback, scoped_ptr<std::string>());
2073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
2083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      pending_downloads_.erase(it++);
2093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
2103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
2113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (updater_ && metadata->second != old_metadata[policy]) {
2133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // |policy| still references external data but the reference has changed.
2143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // Cancel the external data download and start a new one.
2153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      updater_->CancelExternalDataFetch(policy);
2163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      StartDownload(policy);
2173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
2183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ++it;
2193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochbool CloudExternalDataManagerBase::Backend::OnDownloadSuccess(
2233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy,
2243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& hash,
2253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& data) {
2263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(metadata_.find(policy) != metadata_.end());
2273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK_EQ(hash, metadata_[policy].hash);
2283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (external_data_store_)
2293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    external_data_store_->Store(policy, hash, data);
2303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const FetchCallbackList& pending_callbacks = pending_downloads_[policy];
2323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (FetchCallbackList::const_iterator it = pending_callbacks.begin();
2333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != pending_callbacks.end(); ++it) {
2343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RunCallback(*it, make_scoped_ptr(new std::string(data)));
2353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  pending_downloads_.erase(policy);
2373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return true;
2383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::Fetch(
2413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy,
2423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ExternalDataFetcher::FetchCallback& callback) {
2433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Metadata::const_iterator metadata = metadata_.find(policy);
2443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (metadata == metadata_.end()) {
2453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If |policy| does not reference any external data, indicate permanent
2463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // failure.
2473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RunCallback(callback, scoped_ptr<std::string>());
2483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (pending_downloads_.find(policy) != pending_downloads_.end()) {
2523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If a download of the external data referenced by |policy| has already
2533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // been requested, add |callback| to the list of callbacks for |policy| and
2543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // return.
2553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pending_downloads_[policy].push_back(callback);
2563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<std::string> data(new std::string);
2603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (external_data_store_ && external_data_store_->Load(
2613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          policy, metadata->second.hash, GetMaxExternalDataSize(policy),
2623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          data.get())) {
2633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the external data referenced by |policy| exists in the cache and
2643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // matches the expected hash, pass it to the callback.
2653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RunCallback(callback, data.Pass());
2663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Request a download of the the external data referenced by |policy| and
2703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // initialize the list of callbacks by adding |callback|.
2713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  pending_downloads_[policy].push_back(callback);
2723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  StartDownload(policy);
2733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::FetchAll() {
2763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Loop through all external data references.
2773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (Metadata::const_iterator it = metadata_.begin(); it != metadata_.end();
2783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       ++it) {
2793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy = it->first;
2803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<std::string> data(new std::string);
2813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (pending_downloads_.find(policy) != pending_downloads_.end() ||
2823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        (external_data_store_ && external_data_store_->Load(
2833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch             policy, it->second.hash, GetMaxExternalDataSize(policy),
2843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch             data.get()))) {
2853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // If a download of the external data referenced by |policy| has already
2863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // been requested or the data exists in the cache and matches the expected
2873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // hash, there is nothing to be done.
2883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
2893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
2903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Request a download of the the external data referenced by |policy| and
2913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // initialize the list of callbacks to an empty list.
2923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pending_downloads_[policy];
2933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    StartDownload(policy);
2943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochsize_t CloudExternalDataManagerBase::Backend::GetMaxExternalDataSize(
2983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy) const {
299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (max_external_data_size_for_testing)
300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return max_external_data_size_for_testing;
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Look up the maximum size that the data referenced by |policy| can have in
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // get_policy_details, which is constructed from the information in
3043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // policy_templates.json, allowing the maximum data size to be specified as
3053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // part of the policy definition.
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const PolicyDetails* details = get_policy_details_.Run(policy);
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (details)
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return details->max_external_data_size;
3093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NOTREACHED();
3103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return 0;
3113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::RunCallback(
3143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ExternalDataFetcher::FetchCallback& callback,
3153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<std::string> data) const {
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  callback_task_runner_->PostTask(FROM_HERE,
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  base::Bind(callback, base::Passed(&data)));
3183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::StartDownload(
3213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy) {
3223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(pending_downloads_.find(policy) != pending_downloads_.end());
3233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (!updater_)
3243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
3253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const MetadataEntry& metadata = metadata_[policy];
3273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  updater_->FetchExternalData(
3283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      policy,
3293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      ExternalPolicyDataUpdater::Request(metadata.url,
3303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                         metadata.hash,
3313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                         GetMaxExternalDataSize(policy)),
3323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      base::Bind(&CloudExternalDataManagerBase::Backend::OnDownloadSuccess,
3333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 base::Unretained(this),
3343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 policy,
3353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 metadata.hash));
3363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochCloudExternalDataManagerBase::CloudExternalDataManagerBase(
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const GetChromePolicyDetailsCallback& get_policy_details,
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
3423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    : backend_task_runner_(backend_task_runner),
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      io_task_runner_(io_task_runner),
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      backend_(new Backend(get_policy_details,
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           backend_task_runner_,
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           base::MessageLoopProxy::current())) {
3473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochCloudExternalDataManagerBase::~CloudExternalDataManagerBase() {
35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  io_task_runner_->DeleteSoon(FROM_HERE,
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              external_policy_data_fetcher_backend_.release());
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
3543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::SetExternalDataStore(
3573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<CloudExternalDataStore> external_data_store) {
35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
3603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      &Backend::SetExternalDataStore,
36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Unretained(backend_.get()),
3623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      base::Passed(&external_data_store)));
3633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::SetPolicyStore(
3663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    CloudPolicyStore* policy_store) {
36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  CloudExternalDataManager::SetPolicyStore(policy_store);
3693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (policy_store_ && policy_store_->is_initialized())
3703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    OnPolicyStoreLoaded();
3713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::OnPolicyStoreLoaded() {
3743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Collect all external data references made by policies in |policy_store_|
3753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // and pass them to the |backend_|.
37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<Metadata> metadata(new Metadata);
3783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const PolicyMap& policy_map = policy_store_->policy_map();
3793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (PolicyMap::const_iterator it = policy_map.begin();
3803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != policy_map.end(); ++it) {
3813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!it->second.external_data_fetcher) {
3823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // Skip policies that do not reference external data.
3833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
3843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
3853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const base::DictionaryValue* dict = NULL;
3863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string url;
3873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string hex_hash;
3883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::vector<uint8> hash;
3893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (it->second.value && it->second.value->GetAsDictionary(&dict) &&
3903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        dict->GetStringWithoutPathExpansion("url", &url) &&
3913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        dict->GetStringWithoutPathExpansion("hash", &hex_hash) &&
3923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        !url.empty() && !hex_hash.empty() &&
3933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        base::HexStringToBytes(hex_hash, &hash)) {
3943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // Add the external data reference to |metadata| if it is valid (URL and
3953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // hash are not empty, hash can be decoded as a hex string).
3963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      (*metadata)[it->first] =
3973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          MetadataEntry(url, std::string(hash.begin(), hash.end()));
3983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
3993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
4003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
4023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      &Backend::OnMetadataUpdated,
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Unretained(backend_.get()),
4043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      base::Passed(&metadata)));
4053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Connect(
4083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_refptr<net::URLRequestContextGetter> request_context) {
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(!external_policy_data_fetcher_backend_);
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  external_policy_data_fetcher_backend_.reset(
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new ExternalPolicyDataFetcherBackend(io_task_runner_,
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                           request_context));
4143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::Connect,
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Unretained(backend_.get()),
41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Passed(external_policy_data_fetcher_backend_->CreateFrontend(
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          backend_task_runner_))));
4193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Disconnect() {
42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  io_task_runner_->DeleteSoon(FROM_HERE,
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              external_policy_data_fetcher_backend_.release());
4253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::Disconnect, base::Unretained(backend_.get())));
4273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Fetch(
4303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy,
4313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ExternalDataFetcher::FetchCallback& callback) {
43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::Fetch, base::Unretained(backend_.get()), policy, callback));
4353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// static
438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CloudExternalDataManagerBase::SetMaxExternalDataSizeForTesting(
439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int max_size) {
440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  max_external_data_size_for_testing = max_size;
441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::FetchAll() {
44458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
44658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::FetchAll, base::Unretained(backend_.get())));
4473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}  // namespace policy
450