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 "components/policy/core/common/forwarding_policy_provider.h"
6
7#include "components/policy/core/common/schema_map.h"
8#include "components/policy/core/common/schema_registry.h"
9
10namespace policy {
11
12ForwardingPolicyProvider::ForwardingPolicyProvider(
13    ConfigurationPolicyProvider* delegate)
14    : delegate_(delegate), state_(WAITING_FOR_REGISTRY_READY) {
15  delegate_->AddObserver(this);
16  // Serve the initial |delegate_| policies.
17  OnUpdatePolicy(delegate_);
18}
19
20ForwardingPolicyProvider::~ForwardingPolicyProvider() {
21  delegate_->RemoveObserver(this);
22}
23
24void ForwardingPolicyProvider::Init(SchemaRegistry* registry) {
25  ConfigurationPolicyProvider::Init(registry);
26  if (registry->IsReady())
27    OnSchemaRegistryReady();
28}
29
30bool ForwardingPolicyProvider::IsInitializationComplete(PolicyDomain domain)
31    const {
32  if (domain == POLICY_DOMAIN_CHROME)
33    return delegate_->IsInitializationComplete(domain);
34  // This provider keeps its own state for all the other domains.
35  return state_ == READY;
36}
37
38void ForwardingPolicyProvider::RefreshPolicies() {
39  delegate_->RefreshPolicies();
40}
41
42void ForwardingPolicyProvider::OnSchemaRegistryReady() {
43  DCHECK_EQ(WAITING_FOR_REGISTRY_READY, state_);
44  // This provider's registry is ready, meaning that it has all the initial
45  // components schemas; the delegate's registry should also see them now,
46  // since it's tracking the former.
47  // Asking the delegate to RefreshPolicies now means that the next
48  // OnUpdatePolicy from the delegate will have the initial policy for
49  // components.
50  if (!schema_map()->HasComponents()) {
51    // If there are no component registered for this provider then there's no
52    // need to reload.
53    state_ = READY;
54    OnUpdatePolicy(delegate_);
55    return;
56  }
57
58  state_ = WAITING_FOR_REFRESH;
59  RefreshPolicies();
60}
61
62void ForwardingPolicyProvider::OnSchemaRegistryUpdated(bool has_new_schemas) {
63  if (state_ != READY)
64    return;
65  if (has_new_schemas) {
66    RefreshPolicies();
67  } else {
68    // Remove the policies that were being served for the component that have
69    // been removed. This is important so that update notifications are also
70    // sent in case those component are reinstalled during the current session.
71    OnUpdatePolicy(delegate_);
72  }
73}
74
75void ForwardingPolicyProvider::OnUpdatePolicy(
76    ConfigurationPolicyProvider* provider) {
77  DCHECK_EQ(delegate_, provider);
78
79  if (state_ == WAITING_FOR_REFRESH)
80    state_ = READY;
81
82  scoped_ptr<PolicyBundle> bundle(new PolicyBundle());
83  if (state_ == READY) {
84    bundle->CopyFrom(delegate_->policies());
85    schema_map()->FilterBundle(bundle.get());
86  } else {
87    // Always forward the Chrome policy, even if the components are not ready
88    // yet.
89    const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
90    bundle->Get(chrome_ns).CopyFrom(delegate_->policies().Get(chrome_ns));
91  }
92
93  UpdatePolicy(bundle.Pass());
94}
95
96}  // namespace policy
97