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 <string>
8
9#include "base/memory/scoped_ptr.h"
10#include "base/values.h"
11#include "components/policy/core/common/mock_configuration_policy_provider.h"
12#include "components/policy/core/common/policy_bundle.h"
13#include "components/policy/core/common/policy_map.h"
14#include "components/policy/core/common/policy_types.h"
15#include "components/policy/core/common/schema.h"
16#include "components/policy/core/common/schema_registry.h"
17#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using testing::_;
21using testing::Mock;
22using testing::Return;
23
24namespace policy {
25
26namespace {
27
28const char kTestSchema[] =
29    "{"
30    "  \"type\": \"object\","
31    "  \"properties\": {"
32    "    \"foo\": { \"type\": \"string\" }"
33    "  }"
34    "}";
35
36}  // namespace
37
38class ForwardingPolicyProviderTest : public testing::Test {
39 protected:
40  ForwardingPolicyProviderTest() : forwarding_provider_(&mock_provider_) {
41    mock_provider_.Init();
42    forwarding_provider_.Init(&schema_registry_);
43    forwarding_provider_.AddObserver(&observer_);
44  }
45
46  virtual ~ForwardingPolicyProviderTest() {
47    forwarding_provider_.RemoveObserver(&observer_);
48    forwarding_provider_.Shutdown();
49    mock_provider_.Shutdown();
50  }
51
52  Schema CreateTestSchema() {
53    std::string error;
54    Schema schema = Schema::Parse(kTestSchema, &error);
55    if (!schema.valid())
56      ADD_FAILURE() << error;
57    return schema;
58  }
59
60  SchemaRegistry schema_registry_;
61  MockConfigurationPolicyObserver observer_;
62  MockConfigurationPolicyProvider mock_provider_;
63  ForwardingPolicyProvider forwarding_provider_;
64};
65
66TEST_F(ForwardingPolicyProviderTest, Empty) {
67  EXPECT_FALSE(schema_registry_.IsReady());
68  EXPECT_FALSE(
69      forwarding_provider_.IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
70
71  EXPECT_CALL(mock_provider_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
72      .WillOnce(Return(false));
73  EXPECT_FALSE(
74      forwarding_provider_.IsInitializationComplete(POLICY_DOMAIN_CHROME));
75  Mock::VerifyAndClearExpectations(&mock_provider_);
76
77  const PolicyBundle empty_bundle;
78  EXPECT_TRUE(forwarding_provider_.policies().Equals(empty_bundle));
79}
80
81TEST_F(ForwardingPolicyProviderTest, ForwardsChromePolicy) {
82  PolicyBundle bundle;
83  const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
84  bundle.Get(chrome_ns).Set("policy",
85                            POLICY_LEVEL_MANDATORY,
86                            POLICY_SCOPE_USER,
87                            new base::StringValue("value"),
88                            NULL);
89
90  EXPECT_CALL(observer_, OnUpdatePolicy(&forwarding_provider_));
91  scoped_ptr<PolicyBundle> delegate_bundle(new PolicyBundle);
92  delegate_bundle->CopyFrom(bundle);
93  delegate_bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
94      .Set("foo",
95           POLICY_LEVEL_MANDATORY,
96           POLICY_SCOPE_USER,
97           new base::StringValue("not forwarded"),
98           NULL);
99  mock_provider_.UpdatePolicy(delegate_bundle.Pass());
100  Mock::VerifyAndClearExpectations(&observer_);
101
102  EXPECT_FALSE(
103      forwarding_provider_.IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
104  EXPECT_TRUE(forwarding_provider_.policies().Equals(bundle));
105}
106
107TEST_F(ForwardingPolicyProviderTest, RefreshPolicies) {
108  EXPECT_CALL(mock_provider_, RefreshPolicies());
109  forwarding_provider_.RefreshPolicies();
110  Mock::VerifyAndClearExpectations(&mock_provider_);
111}
112
113TEST_F(ForwardingPolicyProviderTest, SchemaReady) {
114  EXPECT_CALL(observer_, OnUpdatePolicy(&forwarding_provider_));
115  schema_registry_.SetReady(POLICY_DOMAIN_CHROME);
116  schema_registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
117  Mock::VerifyAndClearExpectations(&observer_);
118
119  EXPECT_TRUE(forwarding_provider_.IsInitializationComplete(
120      policy::POLICY_DOMAIN_EXTENSIONS));
121}
122
123TEST_F(ForwardingPolicyProviderTest, SchemaReadyWithComponents) {
124  PolicyMap policy_map;
125  policy_map.Set("foo",
126                 POLICY_LEVEL_MANDATORY,
127                 POLICY_SCOPE_USER,
128                 new base::StringValue("omg"),
129                 NULL);
130  scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
131  bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")).CopyFrom(policy_map);
132  bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
133      .CopyFrom(policy_map);
134  EXPECT_CALL(observer_, OnUpdatePolicy(&forwarding_provider_));
135  mock_provider_.UpdatePolicy(bundle.Pass());
136  Mock::VerifyAndClearExpectations(&observer_);
137
138  EXPECT_CALL(mock_provider_, RefreshPolicies()).Times(0);
139  schema_registry_.RegisterComponent(
140      PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), CreateTestSchema());
141  schema_registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
142  Mock::VerifyAndClearExpectations(&mock_provider_);
143
144  EXPECT_CALL(mock_provider_, RefreshPolicies());
145  schema_registry_.SetReady(POLICY_DOMAIN_CHROME);
146  Mock::VerifyAndClearExpectations(&mock_provider_);
147
148  EXPECT_FALSE(forwarding_provider_.IsInitializationComplete(
149      policy::POLICY_DOMAIN_EXTENSIONS));
150  PolicyBundle expected_bundle;
151  expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, ""))
152      .CopyFrom(policy_map);
153  EXPECT_TRUE(forwarding_provider_.policies().Equals(expected_bundle));
154
155  EXPECT_CALL(observer_, OnUpdatePolicy(&forwarding_provider_));
156  forwarding_provider_.OnUpdatePolicy(&mock_provider_);
157  Mock::VerifyAndClearExpectations(&observer_);
158
159  EXPECT_TRUE(forwarding_provider_.IsInitializationComplete(
160      policy::POLICY_DOMAIN_EXTENSIONS));
161  expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
162      .CopyFrom(policy_map);
163  EXPECT_TRUE(forwarding_provider_.policies().Equals(expected_bundle));
164}
165
166TEST_F(ForwardingPolicyProviderTest, DelegateUpdates) {
167  schema_registry_.RegisterComponent(
168      PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), CreateTestSchema());
169  EXPECT_FALSE(schema_registry_.IsReady());
170  EXPECT_FALSE(forwarding_provider_.IsInitializationComplete(
171      policy::POLICY_DOMAIN_EXTENSIONS));
172
173  PolicyMap policy_map;
174  policy_map.Set("foo",
175                 POLICY_LEVEL_MANDATORY,
176                 POLICY_SCOPE_USER,
177                 new base::StringValue("omg"),
178                 NULL);
179  // Chrome policy updates are forwarded even if the components aren't ready.
180  EXPECT_CALL(observer_, OnUpdatePolicy(&forwarding_provider_));
181  mock_provider_.UpdateChromePolicy(policy_map);
182  Mock::VerifyAndClearExpectations(&observer_);
183
184  EXPECT_CALL(mock_provider_, RefreshPolicies());
185  schema_registry_.SetReady(POLICY_DOMAIN_CHROME);
186  schema_registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
187  EXPECT_TRUE(schema_registry_.IsReady());
188  Mock::VerifyAndClearExpectations(&mock_provider_);
189  EXPECT_FALSE(forwarding_provider_.IsInitializationComplete(
190      policy::POLICY_DOMAIN_EXTENSIONS));
191
192  // The forwarding provider becomes ready after this refresh completes, and
193  // starts forwarding policy updates after that.
194  EXPECT_CALL(observer_, OnUpdatePolicy(_));
195  mock_provider_.UpdateChromePolicy(policy_map);
196  Mock::VerifyAndClearExpectations(&observer_);
197
198  EXPECT_TRUE(forwarding_provider_.IsInitializationComplete(
199      policy::POLICY_DOMAIN_EXTENSIONS));
200
201  // Keeps forwarding.
202  EXPECT_CALL(observer_, OnUpdatePolicy(_));
203  mock_provider_.UpdateChromePolicy(policy_map);
204  Mock::VerifyAndClearExpectations(&observer_);
205}
206
207TEST_F(ForwardingPolicyProviderTest, RemoveAndAddComponent) {
208  EXPECT_CALL(mock_provider_, RefreshPolicies());
209  const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "xyz");
210  schema_registry_.SetReady(POLICY_DOMAIN_CHROME);
211  schema_registry_.RegisterComponent(ns, CreateTestSchema());
212  schema_registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
213  Mock::VerifyAndClearExpectations(&mock_provider_);
214
215  // Serve policy for |ns|.
216  PolicyBundle platform_policy;
217  platform_policy.Get(ns).Set("foo",
218                              POLICY_LEVEL_MANDATORY,
219                              POLICY_SCOPE_USER,
220                              new base::StringValue("omg"),
221                              NULL);
222  scoped_ptr<PolicyBundle> copy(new PolicyBundle);
223  copy->CopyFrom(platform_policy);
224  EXPECT_CALL(observer_, OnUpdatePolicy(_));
225  mock_provider_.UpdatePolicy(copy.Pass());
226  Mock::VerifyAndClearExpectations(&observer_);
227  EXPECT_TRUE(forwarding_provider_.policies().Equals(platform_policy));
228
229  // Now remove that component.
230  EXPECT_CALL(observer_, OnUpdatePolicy(_));
231  schema_registry_.UnregisterComponent(ns);
232  Mock::VerifyAndClearExpectations(&observer_);
233  const PolicyBundle empty;
234  EXPECT_TRUE(forwarding_provider_.policies().Equals(empty));
235
236  // Adding it back should serve the current policies again, even though they
237  // haven't changed on the platform provider.
238  EXPECT_CALL(mock_provider_, RefreshPolicies());
239  schema_registry_.RegisterComponent(ns, CreateTestSchema());
240  Mock::VerifyAndClearExpectations(&mock_provider_);
241
242  EXPECT_CALL(observer_, OnUpdatePolicy(_));
243  copy.reset(new PolicyBundle);
244  copy->CopyFrom(platform_policy);
245  mock_provider_.UpdatePolicy(copy.Pass());
246  Mock::VerifyAndClearExpectations(&observer_);
247  EXPECT_TRUE(forwarding_provider_.policies().Equals(platform_policy));
248}
249
250}  // namespace policy
251