cloud_external_data_manager_base.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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"
133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/location.h"
143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/logging.h"
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/sequenced_task_runner.h"
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/strings/string_number_conversions.h"
183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/values.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/chromeos/policy/cloud_external_data_store.h"
203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chrome/browser/policy/cloud/cloud_policy_store.h"
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/policy/cloud/external_policy_data_fetcher.h"
223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chrome/browser/policy/cloud/external_policy_data_updater.h"
233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chrome/browser/policy/external_data_fetcher.h"
243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chrome/browser/policy/policy_map.h"
253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "net/url_request/url_request_context_getter.h"
263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "policy/policy_constants.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:
453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // The |policy_definitions| are 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|.
493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Backend(const PolicyDefinitionList* policy_definitions,
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
1043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Looks up the maximum size that the data referenced by |policy| can have in
1053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // |policy_definitions_|.
1063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t GetMaxExternalDataSize(const std::string& policy) const;
1073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Invokes |callback| via the |callback_task_runner_|, passing |data| as a
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // parameter.
1103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void RunCallback(const ExternalDataFetcher::FetchCallback& callback,
1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                   scoped_ptr<std::string> data) const;
1123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Tells the |updater_| to download the external data referenced by |policy|.
1143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // If Connect() was not called yet and no |updater_| exists, does nothing.
1153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void StartDownload(const std::string& policy);
1163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Used to determine the maximum size that the data referenced by each policy
1183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // can have.
1193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const PolicyDefinitionList* policy_definitions_;
1203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_refptr<base::SequencedTaskRunner> task_runner_;
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
1233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Contains the policies for which a download of the referenced external data
1253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // has been requested. Each policy is mapped to a list of callbacks to invoke
1263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // when the download completes successfully or fails permanently. If no
1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // callback needs to be invoked (because the download was requested via
1283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // FetchAll()), a map entry will still exist but the list of callbacks it maps
1293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // to will be empty.
1303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  FetchCallbackMap pending_downloads_;
1313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Indicates that OnMetadataUpdated() has been called at least once and the
1333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // contents of |metadata_| is initialized.
1343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  bool metadata_set_;
1353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Maps from policy names to the metadata specifying the external data that
1373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // each of the policies references.
1383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Metadata metadata_;
1393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Used to cache external data referenced by policies.
1413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<CloudExternalDataStore> external_data_store_;
1423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Used to download external data referenced by policies.
1443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<ExternalPolicyDataUpdater> updater_;
1453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(Backend);
1473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch};
1483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochCloudExternalDataManagerBase::Backend::Backend(
1503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const PolicyDefinitionList* policy_definitions,
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> task_runner,
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> callback_task_runner)
1533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    : policy_definitions_(policy_definitions),
1543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      task_runner_(task_runner),
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback_task_runner_(callback_task_runner),
1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      metadata_set_(false) {
1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::SetExternalDataStore(
1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<CloudExternalDataStore> external_data_store) {
1613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  external_data_store_.reset(external_data_store.release());
1623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (metadata_set_ && external_data_store_)
1633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    external_data_store_->Prune(metadata_);
1643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::Connect(
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher) {
1683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(!updater_);
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  updater_.reset(new ExternalPolicyDataUpdater(
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      task_runner_,
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      external_policy_data_fetcher.Pass(),
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kMaxParallelFetches));
1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (FetchCallbackMap::const_iterator it = pending_downloads_.begin();
1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != pending_downloads_.end(); ++it) {
1753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    StartDownload(it->first);
1763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::Disconnect() {
1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  updater_.reset();
1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::OnMetadataUpdated(
1843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<Metadata> metadata) {
1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  metadata_set_ = true;
1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Metadata old_metadata;
1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  metadata_.swap(old_metadata);
1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (metadata)
1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    metadata_.swap(*metadata);
1903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (external_data_store_)
1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    external_data_store_->Prune(metadata_);
1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (FetchCallbackMap::iterator it = pending_downloads_.begin();
1953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != pending_downloads_.end(); ) {
1963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string policy = it->first;
1973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    Metadata::const_iterator metadata = metadata_.find(policy);
1983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (metadata == metadata_.end()) {
1993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // |policy| no longer references external data.
2003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (updater_) {
2013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        // Cancel the external data download.
2023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        updater_->CancelExternalDataFetch(policy);
2033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
2043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      for (FetchCallbackList::const_iterator callback = it->second.begin();
2053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch           callback != it->second.end(); ++callback) {
2063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        // Invoke all callbacks for |policy|, indicating permanent failure.
2073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        RunCallback(*callback, scoped_ptr<std::string>());
2083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
2093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      pending_downloads_.erase(it++);
2103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
2113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
2123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (updater_ && metadata->second != old_metadata[policy]) {
2143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // |policy| still references external data but the reference has changed.
2153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // Cancel the external data download and start a new one.
2163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      updater_->CancelExternalDataFetch(policy);
2173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      StartDownload(policy);
2183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
2193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ++it;
2203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochbool CloudExternalDataManagerBase::Backend::OnDownloadSuccess(
2243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy,
2253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& hash,
2263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& data) {
2273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(metadata_.find(policy) != metadata_.end());
2283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK_EQ(hash, metadata_[policy].hash);
2293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (external_data_store_)
2303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    external_data_store_->Store(policy, hash, data);
2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const FetchCallbackList& pending_callbacks = pending_downloads_[policy];
2333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (FetchCallbackList::const_iterator it = pending_callbacks.begin();
2343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != pending_callbacks.end(); ++it) {
2353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RunCallback(*it, make_scoped_ptr(new std::string(data)));
2363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  pending_downloads_.erase(policy);
2383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return true;
2393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::Fetch(
2423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy,
2433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ExternalDataFetcher::FetchCallback& callback) {
2443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  Metadata::const_iterator metadata = metadata_.find(policy);
2453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (metadata == metadata_.end()) {
2463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If |policy| does not reference any external data, indicate permanent
2473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // failure.
2483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RunCallback(callback, scoped_ptr<std::string>());
2493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (pending_downloads_.find(policy) != pending_downloads_.end()) {
2533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If a download of the external data referenced by |policy| has already
2543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // been requested, add |callback| to the list of callbacks for |policy| and
2553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // return.
2563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pending_downloads_[policy].push_back(callback);
2573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<std::string> data(new std::string);
2613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (external_data_store_ && external_data_store_->Load(
2623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          policy, metadata->second.hash, GetMaxExternalDataSize(policy),
2633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          data.get())) {
2643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the external data referenced by |policy| exists in the cache and
2653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // matches the expected hash, pass it to the callback.
2663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    RunCallback(callback, data.Pass());
2673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Request a download of the the external data referenced by |policy| and
2713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // initialize the list of callbacks by adding |callback|.
2723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  pending_downloads_[policy].push_back(callback);
2733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  StartDownload(policy);
2743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::FetchAll() {
2773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Loop through all external data references.
2783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (Metadata::const_iterator it = metadata_.begin(); it != metadata_.end();
2793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       ++it) {
2803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy = it->first;
2813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<std::string> data(new std::string);
2823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (pending_downloads_.find(policy) != pending_downloads_.end() ||
2833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        (external_data_store_ && external_data_store_->Load(
2843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch             policy, it->second.hash, GetMaxExternalDataSize(policy),
2853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch             data.get()))) {
2863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // If a download of the external data referenced by |policy| has already
2873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // been requested or the data exists in the cache and matches the expected
2883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // hash, there is nothing to be done.
2893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
2903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
2913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Request a download of the the external data referenced by |policy| and
2923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // initialize the list of callbacks to an empty list.
2933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    pending_downloads_[policy];
2943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    StartDownload(policy);
2953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochsize_t CloudExternalDataManagerBase::Backend::GetMaxExternalDataSize(
2993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy) const {
300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (max_external_data_size_for_testing)
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return max_external_data_size_for_testing;
302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Look up the maximum size that the data referenced by |policy| can have in
3043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // policy_definitions_, which is constructed from the information in
3053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // policy_templates.json, allowing the maximum data size to be specified as
3063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // part of the policy definition.
3073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (const PolicyDefinitionList::Entry* entry = policy_definitions_->begin;
3083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       entry != policy_definitions_->end; ++entry) {
3093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (entry->name == policy)
3103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return entry->max_external_data_size;
3113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
3123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NOTREACHED();
3133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return 0;
3143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::RunCallback(
3173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ExternalDataFetcher::FetchCallback& callback,
3183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<std::string> data) const {
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  callback_task_runner_->PostTask(FROM_HERE,
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  base::Bind(callback, base::Passed(&data)));
3213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Backend::StartDownload(
3243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy) {
3253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(pending_downloads_.find(policy) != pending_downloads_.end());
3263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (!updater_)
3273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
3283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const MetadataEntry& metadata = metadata_[policy];
3303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  updater_->FetchExternalData(
3313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      policy,
3323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      ExternalPolicyDataUpdater::Request(metadata.url,
3333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                         metadata.hash,
3343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                         GetMaxExternalDataSize(policy)),
3353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      base::Bind(&CloudExternalDataManagerBase::Backend::OnDownloadSuccess,
3363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 base::Unretained(this),
3373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 policy,
3383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                 metadata.hash));
3393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochCloudExternalDataManagerBase::CloudExternalDataManagerBase(
3423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const PolicyDefinitionList* policy_definitions,
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
3453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    : backend_task_runner_(backend_task_runner),
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      io_task_runner_(io_task_runner),
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      backend_(new Backend(policy_definitions,
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           backend_task_runner_,
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           base::MessageLoopProxy::current())) {
3503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochCloudExternalDataManagerBase::~CloudExternalDataManagerBase() {
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  io_task_runner_->DeleteSoon(FROM_HERE,
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              external_policy_data_fetcher_backend_.release());
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
3573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::SetExternalDataStore(
3603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<CloudExternalDataStore> external_data_store) {
36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
3633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      &Backend::SetExternalDataStore,
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Unretained(backend_.get()),
3653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      base::Passed(&external_data_store)));
3663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::SetPolicyStore(
3693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    CloudPolicyStore* policy_store) {
37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  CloudExternalDataManager::SetPolicyStore(policy_store);
3723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (policy_store_ && policy_store_->is_initialized())
3733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    OnPolicyStoreLoaded();
3743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
3763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::OnPolicyStoreLoaded() {
3773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Collect all external data references made by policies in |policy_store_|
3783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // and pass them to the |backend_|.
37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_ptr<Metadata> metadata(new Metadata);
3813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  const PolicyMap& policy_map = policy_store_->policy_map();
3823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (PolicyMap::const_iterator it = policy_map.begin();
3833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       it != policy_map.end(); ++it) {
3843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!it->second.external_data_fetcher) {
3853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // Skip policies that do not reference external data.
3863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
3873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
3883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const base::DictionaryValue* dict = NULL;
3893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string url;
3903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string hex_hash;
3913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::vector<uint8> hash;
3923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (it->second.value && it->second.value->GetAsDictionary(&dict) &&
3933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        dict->GetStringWithoutPathExpansion("url", &url) &&
3943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        dict->GetStringWithoutPathExpansion("hash", &hex_hash) &&
3953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        !url.empty() && !hex_hash.empty() &&
3963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        base::HexStringToBytes(hex_hash, &hash)) {
3973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // Add the external data reference to |metadata| if it is valid (URL and
3983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      // hash are not empty, hash can be decoded as a hex string).
3993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      (*metadata)[it->first] =
4003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          MetadataEntry(url, std::string(hash.begin(), hash.end()));
4013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
4023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
4033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
4053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      &Backend::OnMetadataUpdated,
40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Unretained(backend_.get()),
4073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      base::Passed(&metadata)));
4083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Connect(
4113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_refptr<net::URLRequestContextGetter> request_context) {
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(!external_policy_data_fetcher_backend_);
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  external_policy_data_fetcher_backend_.reset(
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new ExternalPolicyDataFetcherBackend(io_task_runner_,
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                           request_context));
4173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::Connect,
41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Unretained(backend_.get()),
42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Passed(external_policy_data_fetcher_backend_->CreateFrontend(
42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          backend_task_runner_))));
4223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Disconnect() {
42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  io_task_runner_->DeleteSoon(FROM_HERE,
42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              external_policy_data_fetcher_backend_.release());
4283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::Disconnect, base::Unretained(backend_.get())));
4303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::Fetch(
4333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const std::string& policy,
4343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ExternalDataFetcher::FetchCallback& callback) {
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::Fetch, base::Unretained(backend_.get()), policy, callback));
4383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// static
441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CloudExternalDataManagerBase::SetMaxExternalDataSizeForTesting(
442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int max_size) {
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  max_external_data_size_for_testing = max_size;
444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid CloudExternalDataManagerBase::FetchAll() {
44758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  backend_task_runner_->PostTask(FROM_HERE, base::Bind(
44958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &Backend::FetchAll, base::Unretained(backend_.get())));
4503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
4523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}  // namespace policy
453