summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/policy/device_local_account_extension_tracker.cc
blob: 7b4e02161db09a409751684a99e03ff0142aaf7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/policy/device_local_account_extension_tracker.h"

#include "base/logging.h"
#include "base/values.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/extensions/policy_handlers.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/schema.h"
#include "components/policy/core/common/schema_map.h"
#include "components/policy/core/common/schema_registry.h"
#include "components/prefs/pref_value_map.h"
#include "extensions/browser/pref_names.h"

namespace policy {

DeviceLocalAccountExtensionTracker::DeviceLocalAccountExtensionTracker(
    const DeviceLocalAccount& account,
    CloudPolicyStore* store,
    SchemaRegistry* schema_registry)
    : store_(store),
      schema_registry_(schema_registry) {
  if (account.type == DeviceLocalAccount::TYPE_KIOSK_APP) {
    // This is easy: Just add a component for the app id.
    PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, account.kiosk_app_id);
    schema_registry_->RegisterComponent(ns, Schema());
  } else if (account.type == DeviceLocalAccount::TYPE_PUBLIC_SESSION) {
    // For public sessions, track the value of the ExtensionInstallForcelist
    // policy.
    store_->AddObserver(this);
    UpdateFromStore();
  } else {
    NOTREACHED();
  }

  schema_registry_->SetReady(POLICY_DOMAIN_EXTENSIONS);
}

DeviceLocalAccountExtensionTracker::~DeviceLocalAccountExtensionTracker() {
  store_->RemoveObserver(this);
}

void DeviceLocalAccountExtensionTracker::OnStoreLoaded(
    CloudPolicyStore* store) {
  UpdateFromStore();
}

void DeviceLocalAccountExtensionTracker::OnStoreError(CloudPolicyStore* store) {
  UpdateFromStore();
}

void DeviceLocalAccountExtensionTracker::UpdateFromStore() {
  const policy::PolicyMap& policy_map = store_->policy_map();

  // TODO(binjin): Use two policy handlers here after
  // ExtensionManagementPolicyHandler is introduced.
  extensions::ExtensionInstallForcelistPolicyHandler policy_handler;
  if (!policy_handler.CheckPolicySettings(policy_map, NULL))
    return;

  PrefValueMap pref_value_map;
  policy_handler.ApplyPolicySettings(policy_map, &pref_value_map);

  const base::Value* value = NULL;
  const base::DictionaryValue* dict = NULL;
  if (!pref_value_map.GetValue(extensions::pref_names::kInstallForceList,
                               &value) ||
      !value->GetAsDictionary(&dict)) {
    return;
  }

  for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
    PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, it.key());
    if (schema_registry_->schema_map()->GetSchema(ns)) {
      // Important detail: Don't register the component again if it already
      // has a schema! If the session already started for this public session
      // then the real Schema for the extension has already been set by the
      // ManagedValueStoreCache::ExtensionTracker. Do not override that schema
      // with an invalid one now, or the policy for the extension will be
      // dropped.
      // However, if the forcelist is updated then we need to register the new
      // component ID so that its remote policy data can be fetched.
      continue;
    }
    schema_registry_->RegisterComponent(ns, Schema());
  }

  // Removing an extension from a public session at runtime can happen but is
  // a rare event. In that case we leave the extension ID in the SchemaRegistry,
  // and it will be purged on the next restart.
}

}  // namespace policy