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/basictypes.h"
8#include "base/callback.h"
9#include "base/compiler_specific.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/message_loop/message_loop.h"
12#include "components/policy/core/common/cloud/cloud_policy_constants.h"
13#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
14#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
15#include "components/policy/core/common/cloud/policy_builder.h"
16#include "components/policy/core/common/configuration_policy_provider_test.h"
17#include "components/policy/core/common/external_data_fetcher.h"
18#include "components/policy/core/common/mock_configuration_policy_provider.h"
19#include "components/policy/core/common/schema_registry.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23using testing::Mock;
24using testing::_;
25
26namespace em = enterprise_management;
27
28namespace policy {
29namespace {
30
31class TestHarness : public PolicyProviderTestHarness {
32 public:
33  explicit TestHarness(PolicyLevel level);
34  virtual ~TestHarness();
35
36  virtual void SetUp() OVERRIDE;
37
38  virtual ConfigurationPolicyProvider* CreateProvider(
39      SchemaRegistry* registry,
40      scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
41
42  virtual void InstallEmptyPolicy() OVERRIDE;
43  virtual void InstallStringPolicy(const std::string& policy_name,
44                                   const std::string& policy_value) OVERRIDE;
45  virtual void InstallIntegerPolicy(const std::string& policy_name,
46                                    int policy_value) OVERRIDE;
47  virtual void InstallBooleanPolicy(const std::string& policy_name,
48                                    bool policy_value) OVERRIDE;
49  virtual void InstallStringListPolicy(
50      const std::string& policy_name,
51      const base::ListValue* policy_value) OVERRIDE;
52  virtual void InstallDictionaryPolicy(
53      const std::string& policy_name,
54      const base::DictionaryValue* policy_value) OVERRIDE;
55
56  // Creates harnesses for mandatory and recommended levels, respectively.
57  static PolicyProviderTestHarness* CreateMandatory();
58  static PolicyProviderTestHarness* CreateRecommended();
59
60 private:
61  MockCloudPolicyStore store_;
62
63  DISALLOW_COPY_AND_ASSIGN(TestHarness);
64};
65
66TestHarness::TestHarness(PolicyLevel level)
67    : PolicyProviderTestHarness(level, POLICY_SCOPE_USER) {}
68
69TestHarness::~TestHarness() {}
70
71void TestHarness::SetUp() {}
72
73ConfigurationPolicyProvider* TestHarness::CreateProvider(
74    SchemaRegistry* registry,
75    scoped_refptr<base::SequencedTaskRunner> task_runner) {
76  // Create and initialize the store.
77  store_.NotifyStoreLoaded();
78  ConfigurationPolicyProvider* provider = new CloudPolicyManager(
79      PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, std::string()),
80      &store_,
81      task_runner,
82      task_runner,
83      task_runner);
84  Mock::VerifyAndClearExpectations(&store_);
85  return provider;
86}
87
88void TestHarness::InstallEmptyPolicy() {}
89
90void TestHarness::InstallStringPolicy(const std::string& policy_name,
91                                      const std::string& policy_value) {
92  store_.policy_map_.Set(policy_name,
93                         policy_level(),
94                         policy_scope(),
95                         new base::StringValue(policy_value),
96                         NULL);
97}
98
99void TestHarness::InstallIntegerPolicy(const std::string& policy_name,
100                                       int policy_value) {
101  store_.policy_map_.Set(policy_name,
102                         policy_level(),
103                         policy_scope(),
104                         new base::FundamentalValue(policy_value),
105                         NULL);
106}
107
108void TestHarness::InstallBooleanPolicy(const std::string& policy_name,
109                                       bool policy_value) {
110  store_.policy_map_.Set(policy_name,
111                         policy_level(),
112                         policy_scope(),
113                         new base::FundamentalValue(policy_value),
114                         NULL);
115}
116
117void TestHarness::InstallStringListPolicy(const std::string& policy_name,
118                                          const base::ListValue* policy_value) {
119  store_.policy_map_.Set(policy_name, policy_level(), policy_scope(),
120                         policy_value->DeepCopy(), NULL);
121}
122
123void TestHarness::InstallDictionaryPolicy(
124    const std::string& policy_name,
125    const base::DictionaryValue* policy_value) {
126  store_.policy_map_.Set(policy_name, policy_level(), policy_scope(),
127                         policy_value->DeepCopy(), NULL);
128}
129
130// static
131PolicyProviderTestHarness* TestHarness::CreateMandatory() {
132  return new TestHarness(POLICY_LEVEL_MANDATORY);
133}
134
135// static
136PolicyProviderTestHarness* TestHarness::CreateRecommended() {
137  return new TestHarness(POLICY_LEVEL_RECOMMENDED);
138}
139
140// Instantiate abstract test case for basic policy reading tests.
141INSTANTIATE_TEST_CASE_P(
142    UserCloudPolicyManagerProviderTest,
143    ConfigurationPolicyProviderTest,
144    testing::Values(TestHarness::CreateMandatory,
145                    TestHarness::CreateRecommended));
146
147class TestCloudPolicyManager : public CloudPolicyManager {
148 public:
149  TestCloudPolicyManager(
150      CloudPolicyStore* store,
151      const scoped_refptr<base::SequencedTaskRunner>& task_runner)
152      : CloudPolicyManager(PolicyNamespaceKey(
153                               dm_protocol::kChromeUserPolicyType,
154                               std::string()),
155                           store,
156                           task_runner,
157                           task_runner,
158                           task_runner) {}
159  virtual ~TestCloudPolicyManager() {}
160
161  // Publish the protected members for testing.
162  using CloudPolicyManager::client;
163  using CloudPolicyManager::store;
164  using CloudPolicyManager::service;
165  using CloudPolicyManager::CheckAndPublishPolicy;
166
167 private:
168  DISALLOW_COPY_AND_ASSIGN(TestCloudPolicyManager);
169};
170
171MATCHER_P(ProtoMatches, proto, "") {
172  return arg.SerializePartialAsString() == proto.SerializePartialAsString();
173}
174
175class CloudPolicyManagerTest : public testing::Test {
176 protected:
177  CloudPolicyManagerTest()
178      : policy_ns_key_(dm_protocol::kChromeUserPolicyType, std::string()) {}
179
180  virtual void SetUp() OVERRIDE {
181    // Set up a policy map for testing.
182    policy_map_.Set("key",
183                    POLICY_LEVEL_MANDATORY,
184                    POLICY_SCOPE_USER,
185                    new base::StringValue("value"),
186                    NULL);
187    expected_bundle_.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
188        .CopyFrom(policy_map_);
189
190    policy_.payload().mutable_passwordmanagerenabled()->set_value(false);
191    policy_.Build();
192
193    EXPECT_CALL(store_, Load());
194    manager_.reset(new TestCloudPolicyManager(&store_,
195                                              loop_.message_loop_proxy()));
196    manager_->Init(&schema_registry_);
197    Mock::VerifyAndClearExpectations(&store_);
198    manager_->AddObserver(&observer_);
199  }
200
201  virtual void TearDown() OVERRIDE {
202    manager_->RemoveObserver(&observer_);
203    manager_->Shutdown();
204  }
205
206  // Required by the refresh scheduler that's created by the manager.
207  base::MessageLoop loop_;
208
209  // Testing policy.
210  const PolicyNamespaceKey policy_ns_key_;
211  UserPolicyBuilder policy_;
212  PolicyMap policy_map_;
213  PolicyBundle expected_bundle_;
214
215  // Policy infrastructure.
216  SchemaRegistry schema_registry_;
217  MockConfigurationPolicyObserver observer_;
218  MockCloudPolicyStore store_;
219  scoped_ptr<TestCloudPolicyManager> manager_;
220
221 private:
222  DISALLOW_COPY_AND_ASSIGN(CloudPolicyManagerTest);
223};
224
225TEST_F(CloudPolicyManagerTest, InitAndShutdown) {
226  PolicyBundle empty_bundle;
227  EXPECT_TRUE(empty_bundle.Equals(manager_->policies()));
228  EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
229
230  EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
231  manager_->CheckAndPublishPolicy();
232  Mock::VerifyAndClearExpectations(&observer_);
233
234  store_.policy_map_.CopyFrom(policy_map_);
235  store_.policy_.reset(new em::PolicyData(policy_.policy_data()));
236  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
237  store_.NotifyStoreLoaded();
238  Mock::VerifyAndClearExpectations(&observer_);
239  EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
240  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
241
242  MockCloudPolicyClient* client = new MockCloudPolicyClient();
243  EXPECT_CALL(*client, SetupRegistration(_, _));
244  manager_->core()->Connect(scoped_ptr<CloudPolicyClient>(client));
245  Mock::VerifyAndClearExpectations(client);
246  EXPECT_TRUE(manager_->client());
247  EXPECT_TRUE(manager_->service());
248
249  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
250  manager_->CheckAndPublishPolicy();
251  Mock::VerifyAndClearExpectations(&observer_);
252
253  manager_->core()->Disconnect();
254  EXPECT_FALSE(manager_->client());
255  EXPECT_FALSE(manager_->service());
256}
257
258TEST_F(CloudPolicyManagerTest, RegistrationAndFetch) {
259  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
260  store_.NotifyStoreLoaded();
261  Mock::VerifyAndClearExpectations(&observer_);
262  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
263
264  MockCloudPolicyClient* client = new MockCloudPolicyClient();
265  manager_->core()->Connect(scoped_ptr<CloudPolicyClient>(client));
266
267  client->SetDMToken(policy_.policy_data().request_token());
268  client->NotifyRegistrationStateChanged();
269
270  client->SetPolicy(policy_ns_key_, policy_.policy());
271  EXPECT_CALL(store_, Store(ProtoMatches(policy_.policy())));
272  client->NotifyPolicyFetched();
273  Mock::VerifyAndClearExpectations(&store_);
274
275  store_.policy_map_.CopyFrom(policy_map_);
276  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
277  store_.NotifyStoreLoaded();
278  Mock::VerifyAndClearExpectations(&observer_);
279  EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
280}
281
282TEST_F(CloudPolicyManagerTest, Update) {
283  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
284  store_.NotifyStoreLoaded();
285  Mock::VerifyAndClearExpectations(&observer_);
286  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
287  PolicyBundle empty_bundle;
288  EXPECT_TRUE(empty_bundle.Equals(manager_->policies()));
289
290  store_.policy_map_.CopyFrom(policy_map_);
291  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
292  store_.NotifyStoreLoaded();
293  Mock::VerifyAndClearExpectations(&observer_);
294  EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
295  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
296}
297
298TEST_F(CloudPolicyManagerTest, RefreshNotRegistered) {
299  MockCloudPolicyClient* client = new MockCloudPolicyClient();
300  manager_->core()->Connect(scoped_ptr<CloudPolicyClient>(client));
301
302  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
303  store_.NotifyStoreLoaded();
304  Mock::VerifyAndClearExpectations(&observer_);
305
306  // A refresh on a non-registered store should not block.
307  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
308  manager_->RefreshPolicies();
309  Mock::VerifyAndClearExpectations(&observer_);
310}
311
312TEST_F(CloudPolicyManagerTest, RefreshSuccessful) {
313  MockCloudPolicyClient* client = new MockCloudPolicyClient();
314  manager_->core()->Connect(scoped_ptr<CloudPolicyClient>(client));
315
316  // Simulate a store load.
317  store_.policy_.reset(new em::PolicyData(policy_.policy_data()));
318  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
319  EXPECT_CALL(*client, SetupRegistration(_, _));
320  store_.NotifyStoreLoaded();
321  Mock::VerifyAndClearExpectations(client);
322  Mock::VerifyAndClearExpectations(&observer_);
323
324  // Acknowledge registration.
325  client->SetDMToken(policy_.policy_data().request_token());
326
327  // Start a refresh.
328  EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
329  EXPECT_CALL(*client, FetchPolicy());
330  manager_->RefreshPolicies();
331  Mock::VerifyAndClearExpectations(client);
332  Mock::VerifyAndClearExpectations(&observer_);
333  store_.policy_map_.CopyFrom(policy_map_);
334
335  // A stray reload should be suppressed until the refresh completes.
336  EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
337  store_.NotifyStoreLoaded();
338  Mock::VerifyAndClearExpectations(&observer_);
339
340  // Respond to the policy fetch, which should trigger a write to |store_|.
341  EXPECT_CALL(observer_, OnUpdatePolicy(_)).Times(0);
342  EXPECT_CALL(store_, Store(_));
343  client->SetPolicy(policy_ns_key_, policy_.policy());
344  client->NotifyPolicyFetched();
345  Mock::VerifyAndClearExpectations(&observer_);
346  Mock::VerifyAndClearExpectations(&store_);
347
348  // The load notification from |store_| should trigger the policy update.
349  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
350  store_.NotifyStoreLoaded();
351  EXPECT_TRUE(expected_bundle_.Equals(manager_->policies()));
352  Mock::VerifyAndClearExpectations(&observer_);
353}
354
355TEST_F(CloudPolicyManagerTest, SignalOnError) {
356  // Simulate a failed load and verify that it triggers OnUpdatePolicy().
357  store_.policy_.reset(new em::PolicyData(policy_.policy_data()));
358  EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
359  store_.NotifyStoreError();
360  Mock::VerifyAndClearExpectations(&observer_);
361
362  EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
363}
364
365}  // namespace
366}  // namespace policy
367