1// Copyright 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 "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
6
7#include "base/callback.h"
8#include "base/logging.h"
9#include "base/prefs/pref_value_map.h"
10#include "base/values.h"
11#include "chrome/browser/browser_process.h"
12#include "chrome/browser/extensions/policy_handlers.h"
13#include "chrome/common/pref_names.h"
14#include "components/policy/core/common/policy_map.h"
15#include "extensions/browser/pref_names.h"
16#include "net/url_request/url_request_context_getter.h"
17
18namespace chromeos {
19
20DeviceLocalAccountExternalPolicyLoader::
21    DeviceLocalAccountExternalPolicyLoader(policy::CloudPolicyStore* store,
22                                           const base::FilePath& cache_dir)
23    : store_(store),
24      cache_dir_(cache_dir) {
25}
26
27bool DeviceLocalAccountExternalPolicyLoader::IsCacheRunning() const {
28  return external_cache_;
29}
30
31void DeviceLocalAccountExternalPolicyLoader::StartCache(
32    const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner) {
33  DCHECK(!external_cache_);
34  store_->AddObserver(this);
35  external_cache_.reset(new ExternalCache(
36      cache_dir_,
37      g_browser_process->system_request_context(),
38      cache_task_runner,
39      this,
40      true  /* always_check_updates */,
41      false  /* wait_for_cache_initialization */));
42
43  if (store_->is_initialized())
44    UpdateExtensionListFromStore();
45}
46
47void DeviceLocalAccountExternalPolicyLoader::StopCache(
48    const base::Closure& callback) {
49  if (external_cache_) {
50    external_cache_->Shutdown(callback);
51    external_cache_.reset();
52    store_->RemoveObserver(this);
53  }
54
55  base::DictionaryValue empty_prefs;
56  OnExtensionListsUpdated(&empty_prefs);
57}
58
59void DeviceLocalAccountExternalPolicyLoader::StartLoading() {
60  if (prefs_)
61    LoadFinished();
62}
63
64void DeviceLocalAccountExternalPolicyLoader::OnStoreLoaded(
65    policy::CloudPolicyStore* store) {
66  DCHECK(external_cache_);
67  DCHECK_EQ(store_, store);
68  UpdateExtensionListFromStore();
69}
70
71void DeviceLocalAccountExternalPolicyLoader::OnStoreError(
72    policy::CloudPolicyStore* store) {
73  DCHECK(external_cache_);
74  DCHECK_EQ(store_, store);
75}
76
77void DeviceLocalAccountExternalPolicyLoader::OnExtensionListsUpdated(
78    const base::DictionaryValue* prefs) {
79  DCHECK(external_cache_ || prefs->empty());
80  prefs_.reset(prefs->DeepCopy());
81  LoadFinished();
82}
83
84ExternalCache*
85DeviceLocalAccountExternalPolicyLoader::GetExternalCacheForTesting() {
86  return external_cache_.get();
87}
88
89DeviceLocalAccountExternalPolicyLoader::
90    ~DeviceLocalAccountExternalPolicyLoader() {
91  DCHECK(!external_cache_);
92}
93
94void DeviceLocalAccountExternalPolicyLoader::UpdateExtensionListFromStore() {
95  scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
96  const policy::PolicyMap& policy_map = store_->policy_map();
97  // TODO(binjin): Use two policy handlers here after
98  // ExtensionManagementPolicyHandler is introduced.
99  extensions::ExtensionInstallForcelistPolicyHandler policy_handler;
100  if (policy_handler.CheckPolicySettings(policy_map, NULL)) {
101    PrefValueMap pref_value_map;
102    policy_handler.ApplyPolicySettings(policy_map, &pref_value_map);
103    const base::Value* value = NULL;
104    const base::DictionaryValue* dict = NULL;
105    if (pref_value_map.GetValue(extensions::pref_names::kInstallForceList,
106                                &value) &&
107        value->GetAsDictionary(&dict)) {
108      prefs.reset(dict->DeepCopy());
109    }
110  }
111
112  external_cache_->UpdateExtensionsList(prefs.Pass());
113}
114
115}  // namespace chromeos
116