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.
5 #include "chrome/browser/policy/cloud/user_cloud_policy_store.h"
7 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/policy/cloud/mock_cloud_external_data_manager.h"
14 #include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
15 #include "chrome/browser/policy/cloud/policy_builder.h"
16 #include "chrome/browser/signin/fake_signin_manager.h"
17 #include "chrome/browser/signin/signin_manager.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "net/url_request/url_request_context_getter.h"
22 #include "policy/policy_constants.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
29 using testing::Property;
30 using testing::Sequence;
37 base::RunLoop run_loop;
38 run_loop.RunUntilIdle();
41 class UserCloudPolicyStoreTest : public testing::Test {
43 UserCloudPolicyStoreTest()
44 : loop_(base::MessageLoop::TYPE_UI),
45 profile_(new TestingProfile()) {}
47 virtual void SetUp() OVERRIDE {
48 ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
49 SigninManager* signin = static_cast<SigninManager*>(
50 SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
51 profile_.get(), FakeSigninManager::Build));
52 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
53 PolicyBuilder::kFakeUsername);
54 signin->Initialize(profile_.get(), NULL);
55 store_.reset(new UserCloudPolicyStore(
56 profile_.get(), policy_file(), loop_.message_loop_proxy()));
57 external_data_manager_.reset(new MockCloudExternalDataManager);
58 external_data_manager_->SetPolicyStore(store_.get());
59 store_->AddObserver(&observer_);
61 policy_.payload().mutable_passwordmanagerenabled()->set_value(true);
62 policy_.payload().mutable_urlblacklist()->mutable_value()->add_entries(
68 virtual void TearDown() OVERRIDE {
69 store_->RemoveObserver(&observer_);
70 external_data_manager_.reset();
75 base::FilePath policy_file() {
76 return tmp_dir_.path().AppendASCII("policy");
79 // Verifies that store_->policy_map() has the appropriate entries.
80 void VerifyPolicyMap(CloudPolicyStore* store) {
81 EXPECT_EQ(2U, store->policy_map().size());
82 const PolicyMap::Entry* entry =
83 store->policy_map().Get(key::kPasswordManagerEnabled);
85 EXPECT_TRUE(base::FundamentalValue(true).Equals(entry->value));
86 ASSERT_TRUE(store->policy_map().Get(key::kURLBlacklist));
89 // Install an expectation on |observer_| for an error code.
90 void ExpectError(CloudPolicyStore* store, CloudPolicyStore::Status error) {
91 EXPECT_CALL(observer_,
92 OnStoreError(AllOf(Eq(store),
93 Property(&CloudPolicyStore::status,
97 UserPolicyBuilder policy_;
98 MockCloudPolicyStoreObserver observer_;
99 scoped_ptr<UserCloudPolicyStore> store_;
100 scoped_ptr<MockCloudExternalDataManager> external_data_manager_;
102 // CloudPolicyValidator() requires a FILE thread so declare one here. Both
103 // |ui_thread_| and |file_thread_| share the same MessageLoop |loop_| so
104 // callers can use RunLoop to manage both virtual threads.
105 base::MessageLoop loop_;
107 scoped_ptr<TestingProfile> profile_;
108 base::ScopedTempDir tmp_dir_;
110 DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreTest);
113 TEST_F(UserCloudPolicyStoreTest, LoadWithNoFile) {
114 EXPECT_FALSE(store_->policy());
115 EXPECT_TRUE(store_->policy_map().empty());
118 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
119 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
123 EXPECT_FALSE(store_->policy());
124 EXPECT_TRUE(store_->policy_map().empty());
127 TEST_F(UserCloudPolicyStoreTest, LoadWithInvalidFile) {
128 EXPECT_FALSE(store_->policy());
129 EXPECT_TRUE(store_->policy_map().empty());
131 // Create a bogus file.
132 ASSERT_TRUE(file_util::CreateDirectory(policy_file().DirName()));
133 std::string bogus_data = "bogus_data";
134 int size = bogus_data.size();
135 ASSERT_EQ(size, file_util::WriteFile(policy_file(),
139 ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
143 EXPECT_FALSE(store_->policy());
144 EXPECT_TRUE(store_->policy_map().empty());
147 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithNoFile) {
148 EXPECT_FALSE(store_->policy());
149 EXPECT_TRUE(store_->policy_map().empty());
152 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
153 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
154 store_->LoadImmediately(); // Should load without running the message loop.
156 EXPECT_FALSE(store_->policy());
157 EXPECT_TRUE(store_->policy_map().empty());
160 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithInvalidFile) {
161 EXPECT_FALSE(store_->policy());
162 EXPECT_TRUE(store_->policy_map().empty());
164 // Create a bogus file.
165 ASSERT_TRUE(file_util::CreateDirectory(policy_file().DirName()));
166 std::string bogus_data = "bogus_data";
167 int size = bogus_data.size();
168 ASSERT_EQ(size, file_util::WriteFile(policy_file(),
172 ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
173 store_->LoadImmediately(); // Should load without running the message loop.
175 EXPECT_FALSE(store_->policy());
176 EXPECT_TRUE(store_->policy_map().empty());
179 TEST_F(UserCloudPolicyStoreTest, Store) {
180 EXPECT_FALSE(store_->policy());
181 EXPECT_TRUE(store_->policy_map().empty());
183 // Store a simple policy and make sure it ends up as the currently active
186 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
187 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
188 store_->Store(policy_.policy());
191 // Policy should be decoded and stored.
192 ASSERT_TRUE(store_->policy());
193 EXPECT_EQ(policy_.policy_data().SerializeAsString(),
194 store_->policy()->SerializeAsString());
195 VerifyPolicyMap(store_.get());
196 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
199 TEST_F(UserCloudPolicyStoreTest, StoreThenClear) {
200 EXPECT_FALSE(store_->policy());
201 EXPECT_TRUE(store_->policy_map().empty());
203 // Store a simple policy and make sure the file exists.
206 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s1);
207 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s1);
208 store_->Store(policy_.policy());
211 EXPECT_TRUE(store_->policy());
212 EXPECT_FALSE(store_->policy_map().empty());
214 Mock::VerifyAndClearExpectations(external_data_manager_.get());
215 Mock::VerifyAndClearExpectations(&observer_);
217 // Policy file should exist.
218 ASSERT_TRUE(base::PathExists(policy_file()));
221 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s2);
222 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s2);
226 // Policy file should not exist.
227 ASSERT_TRUE(!base::PathExists(policy_file()));
229 // Policy should be gone.
230 EXPECT_FALSE(store_->policy());
231 EXPECT_TRUE(store_->policy_map().empty());
232 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
235 TEST_F(UserCloudPolicyStoreTest, StoreTwoTimes) {
236 EXPECT_FALSE(store_->policy());
237 EXPECT_TRUE(store_->policy_map().empty());
239 // Store a simple policy then store a second policy before the first one
240 // finishes validating, and make sure the second policy ends up as the active
243 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s1);
244 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s1);
246 UserPolicyBuilder first_policy;
247 first_policy.payload().mutable_passwordmanagerenabled()->set_value(false);
248 first_policy.Build();
249 store_->Store(first_policy.policy());
252 Mock::VerifyAndClearExpectations(external_data_manager_.get());
253 Mock::VerifyAndClearExpectations(&observer_);
256 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s2);
257 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s2);
259 store_->Store(policy_.policy());
262 // Policy should be decoded and stored.
263 ASSERT_TRUE(store_->policy());
264 EXPECT_EQ(policy_.policy_data().SerializeAsString(),
265 store_->policy()->SerializeAsString());
266 VerifyPolicyMap(store_.get());
267 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
270 TEST_F(UserCloudPolicyStoreTest, StoreThenLoad) {
271 // Store a simple policy and make sure it can be read back in.
274 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
275 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
276 store_->Store(policy_.policy());
279 // Now, make sure the policy can be read back in from a second store.
280 scoped_ptr<UserCloudPolicyStore> store2(new UserCloudPolicyStore(
281 profile_.get(), policy_file(), loop_.message_loop_proxy()));
282 store2->AddObserver(&observer_);
283 EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
287 ASSERT_TRUE(store2->policy());
288 EXPECT_EQ(policy_.policy_data().SerializeAsString(),
289 store2->policy()->SerializeAsString());
290 VerifyPolicyMap(store2.get());
291 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
292 store2->RemoveObserver(&observer_);
295 TEST_F(UserCloudPolicyStoreTest, StoreThenLoadImmediately) {
296 // Store a simple policy and make sure it can be read back in.
299 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
300 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
301 store_->Store(policy_.policy());
304 // Now, make sure the policy can be read back in from a second store.
305 scoped_ptr<UserCloudPolicyStore> store2(new UserCloudPolicyStore(
306 profile_.get(), policy_file(), loop_.message_loop_proxy()));
307 store2->AddObserver(&observer_);
308 EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
309 store2->LoadImmediately(); // Should load without running the message loop.
311 ASSERT_TRUE(store2->policy());
312 EXPECT_EQ(policy_.policy_data().SerializeAsString(),
313 store2->policy()->SerializeAsString());
314 VerifyPolicyMap(store2.get());
315 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
316 store2->RemoveObserver(&observer_);
319 TEST_F(UserCloudPolicyStoreTest, StoreValidationError) {
320 // Create an invalid policy (no policy type).
321 policy_.policy_data().clear_policy_type();
325 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
326 store_->Store(policy_.policy());
328 ASSERT_FALSE(store_->policy());
331 TEST_F(UserCloudPolicyStoreTest, LoadValidationError) {
332 // Force a validation error by changing the username after policy is stored.
334 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s);
335 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s);
336 store_->Store(policy_.policy());
339 // Sign out, and sign back in as a different user, and try to load the profile
340 // data (should fail due to mismatched username).
341 SigninManagerFactory::GetForProfile(profile_.get())->SignOut();
342 SigninManagerFactory::GetForProfile(profile_.get())->SetAuthenticatedUsername(
343 "foobar@foobar.com");
345 scoped_ptr<UserCloudPolicyStore> store2(new UserCloudPolicyStore(
346 profile_.get(), policy_file(), loop_.message_loop_proxy()));
347 store2->AddObserver(&observer_);
348 ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
352 ASSERT_FALSE(store2->policy());
353 store2->RemoveObserver(&observer_);
355 // Sign out - we should be able to load the policy (don't check usernames
357 SigninManagerFactory::GetForProfile(profile_.get())->SignOut();
358 scoped_ptr<UserCloudPolicyStore> store3(new UserCloudPolicyStore(
359 profile_.get(), policy_file(), loop_.message_loop_proxy()));
360 store3->AddObserver(&observer_);
361 EXPECT_CALL(observer_, OnStoreLoaded(store3.get()));
365 ASSERT_TRUE(store3->policy());
366 store3->RemoveObserver(&observer_);
368 // Now start a signin as a different user - this should fail validation.
369 FakeSigninManager* signin = static_cast<FakeSigninManager*>(
370 SigninManagerFactory::GetForProfile(profile_.get()));
371 signin->set_auth_in_progress("foobar@foobar.com");
373 scoped_ptr<UserCloudPolicyStore> store4(new UserCloudPolicyStore(
374 profile_.get(), policy_file(), loop_.message_loop_proxy()));
375 store4->AddObserver(&observer_);
376 ExpectError(store4.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
380 ASSERT_FALSE(store4->policy());
381 store4->RemoveObserver(&observer_);
386 } // namespace policy