cloud_policy_manager.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright (c) 2012 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/cloud_policy_manager.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/command_line.h"
10#include "base/files/file_path.h"
11#include "base/logging.h"
12#include "base/prefs/pref_service.h"
13#include "components/policy/core/common/cloud/cloud_policy_service.h"
14#include "components/policy/core/common/policy_bundle.h"
15#include "components/policy/core/common/policy_map.h"
16#include "components/policy/core/common/policy_switches.h"
17#include "net/url_request/url_request_context_getter.h"
18
19#if !defined(OS_ANDROID) && !defined(OS_IOS)
20#include "components/policy/core/common/cloud/resource_cache.h"
21#endif
22
23namespace policy {
24
25CloudPolicyManager::CloudPolicyManager(
26    const PolicyNamespaceKey& policy_ns_key,
27    CloudPolicyStore* cloud_policy_store,
28    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
29    const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
30    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
31    : core_(policy_ns_key, cloud_policy_store, task_runner),
32      waiting_for_policy_refresh_(false),
33      file_task_runner_(file_task_runner),
34      io_task_runner_(io_task_runner) {
35  store()->AddObserver(this);
36
37  // If the underlying store is already initialized, publish the loaded
38  // policy. Otherwise, request a load now.
39  if (store()->is_initialized())
40    CheckAndPublishPolicy();
41  else
42    store()->Load();
43}
44
45CloudPolicyManager::~CloudPolicyManager() {}
46
47void CloudPolicyManager::Shutdown() {
48  component_policy_service_.reset();
49  core_.Disconnect();
50  store()->RemoveObserver(this);
51  ConfigurationPolicyProvider::Shutdown();
52}
53
54bool CloudPolicyManager::IsInitializationComplete(PolicyDomain domain) const {
55  if (domain == POLICY_DOMAIN_CHROME)
56    return store()->is_initialized();
57  if (ComponentCloudPolicyService::SupportsDomain(domain) &&
58      component_policy_service_) {
59    return component_policy_service_->is_initialized();
60  }
61  return true;
62}
63
64void CloudPolicyManager::RefreshPolicies() {
65  if (service()) {
66    waiting_for_policy_refresh_ = true;
67    service()->RefreshPolicy(
68        base::Bind(&CloudPolicyManager::OnRefreshComplete,
69                   base::Unretained(this)));
70  } else {
71    OnRefreshComplete(false);
72  }
73}
74
75void CloudPolicyManager::OnStoreLoaded(CloudPolicyStore* cloud_policy_store) {
76  DCHECK_EQ(store(), cloud_policy_store);
77  CheckAndPublishPolicy();
78}
79
80void CloudPolicyManager::OnStoreError(CloudPolicyStore* cloud_policy_store) {
81  DCHECK_EQ(store(), cloud_policy_store);
82  // Publish policy (even though it hasn't changed) in order to signal load
83  // complete on the ConfigurationPolicyProvider interface. Technically, this
84  // is only required on the first load, but doesn't hurt in any case.
85  CheckAndPublishPolicy();
86}
87
88void CloudPolicyManager::OnComponentCloudPolicyUpdated() {
89  CheckAndPublishPolicy();
90}
91
92void CloudPolicyManager::CheckAndPublishPolicy() {
93  if (IsInitializationComplete(POLICY_DOMAIN_CHROME) &&
94      !waiting_for_policy_refresh_) {
95    scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
96    bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
97        .CopyFrom(store()->policy_map());
98    if (component_policy_service_)
99      bundle->MergeFrom(component_policy_service_->policy());
100    UpdatePolicy(bundle.Pass());
101  }
102}
103
104void CloudPolicyManager::CreateComponentCloudPolicyService(
105    const base::FilePath& policy_cache_path,
106    const scoped_refptr<net::URLRequestContextGetter>& request_context) {
107#if !defined(OS_ANDROID) && !defined(OS_IOS)
108  // Init() must have been called.
109  DCHECK(schema_registry());
110  // Called at most once.
111  DCHECK(!component_policy_service_);
112
113  if (!CommandLine::ForCurrentProcess()->HasSwitch(
114           switches::kEnableComponentCloudPolicy) ||
115      policy_cache_path.empty()) {
116    return;
117  }
118
119  // TODO(joaodasilva): Move the |file_task_runner_| to the blocking pool.
120  // Currently it's not possible because the ComponentCloudPolicyStore is
121  // NonThreadSafe and doesn't support getting calls from different threads.
122  scoped_ptr<ResourceCache> resource_cache(
123      new ResourceCache(policy_cache_path, file_task_runner_));
124  component_policy_service_.reset(new ComponentCloudPolicyService(
125      this,
126      schema_registry(),
127      core(),
128      resource_cache.Pass(),
129      request_context,
130      file_task_runner_,
131      io_task_runner_));
132#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
133}
134
135void CloudPolicyManager::ClearAndDestroyComponentCloudPolicyService() {
136#if !defined(OS_ANDROID) && !defined(OS_IOS)
137  if (component_policy_service_) {
138    component_policy_service_->ClearCache();
139    component_policy_service_.reset();
140  }
141#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
142}
143
144void CloudPolicyManager::OnRefreshComplete(bool success) {
145  waiting_for_policy_refresh_ = false;
146  CheckAndPublishPolicy();
147}
148
149}  // namespace policy
150