1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/policy/core/common/cloud/component_cloud_policy_updater.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/logging.h" 10#include "base/sequenced_task_runner.h" 11#include "base/strings/string_number_conversions.h" 12#include "components/policy/core/common/cloud/component_cloud_policy_store.h" 13#include "components/policy/core/common/cloud/external_policy_data_fetcher.h" 14#include "policy/proto/chrome_extension_policy.pb.h" 15#include "policy/proto/device_management_backend.pb.h" 16 17namespace em = enterprise_management; 18 19namespace policy { 20 21namespace { 22 23// The maximum size of the serialized policy protobuf. 24const size_t kPolicyProtoMaxSize = 16 * 1024; 25 26// The maximum size of the downloaded policy data. 27const int64 kPolicyDataMaxSize = 5 * 1024 * 1024; 28 29// Tha maximum number of policy data fetches to run in parallel. 30const int64 kMaxParallelPolicyDataFetches = 2; 31 32} // namespace 33 34ComponentCloudPolicyUpdater::ComponentCloudPolicyUpdater( 35 scoped_refptr<base::SequencedTaskRunner> task_runner, 36 scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher, 37 ComponentCloudPolicyStore* store) 38 : store_(store), 39 external_policy_data_updater_(task_runner, 40 external_policy_data_fetcher.Pass(), 41 kMaxParallelPolicyDataFetches) { 42} 43 44ComponentCloudPolicyUpdater::~ComponentCloudPolicyUpdater() { 45} 46 47void ComponentCloudPolicyUpdater::UpdateExternalPolicy( 48 scoped_ptr<em::PolicyFetchResponse> response) { 49 // Keep a serialized copy of |response|, to cache it later. 50 // The policy is also rejected if it exceeds the maximum size. 51 std::string serialized_response; 52 if (!response->SerializeToString(&serialized_response) || 53 serialized_response.size() > kPolicyProtoMaxSize) { 54 return; 55 } 56 57 // Validate the policy before doing anything else. 58 PolicyNamespace ns; 59 em::ExternalPolicyData data; 60 if (!store_->ValidatePolicy(response.Pass(), &ns, &data)) { 61 LOG(ERROR) << "Failed to validate component policy fetched from DMServer"; 62 return; 63 } 64 65 // Maybe the data for this hash has already been downloaded and cached. 66 const std::string& cached_hash = store_->GetCachedHash(ns); 67 if (!cached_hash.empty() && data.secure_hash() == cached_hash) 68 return; 69 70 // TODO(joaodasilva): implement the other two auth methods. 71 if (data.download_auth_method() != em::ExternalPolicyData::NONE) 72 return; 73 74 const std::string key = NamespaceToKey(ns); 75 76 if (data.download_url().empty() || !data.has_secure_hash()) { 77 // If there is no policy for this component or the policy has been removed, 78 // cancel any existing request to fetch policy for this component. 79 external_policy_data_updater_.CancelExternalDataFetch(key); 80 81 // Delete any existing policy for this component. 82 store_->Delete(ns); 83 } else { 84 // Make a request to fetch policy for this component. If another fetch 85 // request is already pending for the component, it will be canceled. 86 external_policy_data_updater_.FetchExternalData( 87 key, 88 ExternalPolicyDataUpdater::Request(data.download_url(), 89 data.secure_hash(), 90 kPolicyDataMaxSize), 91 base::Bind(&ComponentCloudPolicyStore::Store, base::Unretained(store_), 92 ns, 93 serialized_response, 94 data.secure_hash())); 95 } 96} 97 98void ComponentCloudPolicyUpdater::CancelUpdate(const PolicyNamespace& ns) { 99 external_policy_data_updater_.CancelExternalDataFetch(NamespaceToKey(ns)); 100} 101 102std::string ComponentCloudPolicyUpdater::NamespaceToKey( 103 const PolicyNamespace& ns) { 104 const std::string domain = base::IntToString(ns.domain); 105 const std::string size = base::IntToString(domain.size()); 106 return size + ":" + domain + ":" + ns.component_id; 107} 108 109} // namespace policy 110