Home | History | Annotate | Download | only in cloud
      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 "chrome/browser/policy/cloud/user_cloud_policy_store.h"
      6 
      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/prefs/pref_service.h"
     11 #include "base/run_loop.h"
     12 #include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
     13 #include "chrome/browser/policy/cloud/policy_builder.h"
     14 #include "chrome/browser/signin/fake_signin_manager.h"
     15 #include "chrome/browser/signin/signin_manager.h"
     16 #include "chrome/browser/signin/signin_manager_factory.h"
     17 #include "chrome/common/pref_names.h"
     18 #include "chrome/test/base/testing_profile.h"
     19 #include "content/public/test/test_browser_thread.h"
     20 #include "policy/policy_constants.h"
     21 #include "testing/gmock/include/gmock/gmock.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 using testing::AllOf;
     25 using testing::Eq;
     26 using testing::Property;
     27 
     28 namespace policy {
     29 
     30 namespace {
     31 
     32 void RunUntilIdle() {
     33   base::RunLoop run_loop;
     34   run_loop.RunUntilIdle();
     35 }
     36 
     37 class UserCloudPolicyStoreTest : public testing::Test {
     38  public:
     39   UserCloudPolicyStoreTest()
     40       : loop_(base::MessageLoop::TYPE_UI),
     41         ui_thread_(content::BrowserThread::UI, &loop_),
     42         file_thread_(content::BrowserThread::FILE, &loop_),
     43         profile_(new TestingProfile()) {}
     44 
     45   virtual void SetUp() OVERRIDE {
     46     ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
     47     SigninManager* signin = static_cast<SigninManager*>(
     48       SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
     49           profile_.get(), FakeSigninManager::Build));
     50     profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
     51                                     PolicyBuilder::kFakeUsername);
     52     signin->Initialize(profile_.get(), NULL);
     53     store_.reset(new UserCloudPolicyStore(profile_.get(), policy_file()));
     54     store_->AddObserver(&observer_);
     55 
     56     policy_.payload().mutable_passwordmanagerenabled()->set_value(true);
     57     policy_.payload().mutable_urlblacklist()->mutable_value()->add_entries(
     58         "chromium.org");
     59 
     60     policy_.Build();
     61   }
     62 
     63   virtual void TearDown() OVERRIDE {
     64     store_->RemoveObserver(&observer_);
     65     store_.reset();
     66     RunUntilIdle();
     67   }
     68 
     69   base::FilePath policy_file() {
     70     return tmp_dir_.path().AppendASCII("policy");
     71   }
     72 
     73   // Verifies that store_->policy_map() has the appropriate entries.
     74   void VerifyPolicyMap(CloudPolicyStore* store) {
     75     EXPECT_EQ(2U, store->policy_map().size());
     76     const PolicyMap::Entry* entry =
     77         store->policy_map().Get(key::kPasswordManagerEnabled);
     78     ASSERT_TRUE(entry);
     79     EXPECT_TRUE(base::FundamentalValue(true).Equals(entry->value));
     80     ASSERT_TRUE(store->policy_map().Get(key::kURLBlacklist));
     81   }
     82 
     83   // Install an expectation on |observer_| for an error code.
     84   void ExpectError(CloudPolicyStore* store, CloudPolicyStore::Status error) {
     85     EXPECT_CALL(observer_,
     86                 OnStoreError(AllOf(Eq(store),
     87                                    Property(&CloudPolicyStore::status,
     88                                             Eq(error)))));
     89   }
     90 
     91   UserPolicyBuilder policy_;
     92   MockCloudPolicyStoreObserver observer_;
     93   scoped_ptr<UserCloudPolicyStore> store_;
     94 
     95   // CloudPolicyValidator() requires a FILE thread so declare one here. Both
     96   // |ui_thread_| and |file_thread_| share the same MessageLoop |loop_| so
     97   // callers can use RunLoop to manage both virtual threads.
     98   base::MessageLoop loop_;
     99   content::TestBrowserThread ui_thread_;
    100   content::TestBrowserThread file_thread_;
    101 
    102   scoped_ptr<TestingProfile> profile_;
    103   base::ScopedTempDir tmp_dir_;
    104 
    105   DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreTest);
    106 };
    107 
    108 TEST_F(UserCloudPolicyStoreTest, LoadWithNoFile) {
    109   EXPECT_FALSE(store_->policy());
    110   EXPECT_TRUE(store_->policy_map().empty());
    111 
    112   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    113   store_->Load();
    114   RunUntilIdle();
    115 
    116   EXPECT_FALSE(store_->policy());
    117   EXPECT_TRUE(store_->policy_map().empty());
    118   EXPECT_FALSE(store_->policy_changed());
    119 }
    120 
    121 TEST_F(UserCloudPolicyStoreTest, LoadWithInvalidFile) {
    122   EXPECT_FALSE(store_->policy());
    123   EXPECT_TRUE(store_->policy_map().empty());
    124 
    125   // Create a bogus file.
    126   ASSERT_TRUE(file_util::CreateDirectory(policy_file().DirName()));
    127   std::string bogus_data = "bogus_data";
    128   int size = bogus_data.size();
    129   ASSERT_EQ(size, file_util::WriteFile(policy_file(),
    130                                        bogus_data.c_str(),
    131                                        bogus_data.size()));
    132 
    133   ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
    134   store_->Load();
    135   RunUntilIdle();
    136 
    137   EXPECT_FALSE(store_->policy());
    138   EXPECT_TRUE(store_->policy_map().empty());
    139   EXPECT_FALSE(store_->policy_changed());
    140 }
    141 
    142 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithNoFile) {
    143   EXPECT_FALSE(store_->policy());
    144   EXPECT_TRUE(store_->policy_map().empty());
    145 
    146   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    147   store_->LoadImmediately();  // Should load without running the message loop.
    148 
    149   EXPECT_FALSE(store_->policy());
    150   EXPECT_TRUE(store_->policy_map().empty());
    151   EXPECT_FALSE(store_->policy_changed());
    152 }
    153 
    154 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithInvalidFile) {
    155   EXPECT_FALSE(store_->policy());
    156   EXPECT_TRUE(store_->policy_map().empty());
    157 
    158   // Create a bogus file.
    159   ASSERT_TRUE(file_util::CreateDirectory(policy_file().DirName()));
    160   std::string bogus_data = "bogus_data";
    161   int size = bogus_data.size();
    162   ASSERT_EQ(size, file_util::WriteFile(policy_file(),
    163                                        bogus_data.c_str(),
    164                                        bogus_data.size()));
    165 
    166   ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR);
    167   store_->LoadImmediately();  // Should load without running the message loop.
    168 
    169   EXPECT_FALSE(store_->policy());
    170   EXPECT_TRUE(store_->policy_map().empty());
    171   EXPECT_FALSE(store_->policy_changed());
    172 }
    173 
    174 TEST_F(UserCloudPolicyStoreTest, Store) {
    175   EXPECT_FALSE(store_->policy());
    176   EXPECT_TRUE(store_->policy_map().empty());
    177 
    178   // Store a simple policy and make sure it ends up as the currently active
    179   // policy.
    180   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    181   store_->Store(policy_.policy());
    182   RunUntilIdle();
    183 
    184   // Policy should be decoded and stored.
    185   ASSERT_TRUE(store_->policy());
    186   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
    187             store_->policy()->SerializeAsString());
    188   VerifyPolicyMap(store_.get());
    189   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
    190 }
    191 
    192 TEST_F(UserCloudPolicyStoreTest, StoreThenClear) {
    193   EXPECT_FALSE(store_->policy());
    194   EXPECT_TRUE(store_->policy_map().empty());
    195 
    196   // Store a simple policy and make sure the file exists.
    197   // policy.
    198   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    199   store_->Store(policy_.policy());
    200   RunUntilIdle();
    201 
    202   EXPECT_TRUE(store_->policy());
    203   EXPECT_FALSE(store_->policy_map().empty());
    204 
    205   // Policy file should exist.
    206   ASSERT_TRUE(base::PathExists(policy_file()));
    207 
    208   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    209   store_->Clear();
    210   RunUntilIdle();
    211 
    212   // Policy file should not exist.
    213   ASSERT_TRUE(!base::PathExists(policy_file()));
    214 
    215   // Policy should be gone.
    216   EXPECT_FALSE(store_->policy());
    217   EXPECT_TRUE(store_->policy_map().empty());
    218   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
    219 }
    220 
    221 TEST_F(UserCloudPolicyStoreTest, StoreTwoTimes) {
    222   EXPECT_FALSE(store_->policy());
    223   EXPECT_TRUE(store_->policy_map().empty());
    224 
    225   // Store a simple policy then store a second policy before the first one
    226   // finishes validating, and make sure the second policy ends up as the active
    227   // policy.
    228   EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).Times(2);
    229 
    230   UserPolicyBuilder first_policy;
    231   first_policy.payload().mutable_passwordmanagerenabled()->set_value(false);
    232   first_policy.Build();
    233   store_->Store(first_policy.policy());
    234   RunUntilIdle();
    235 
    236   store_->Store(policy_.policy());
    237   RunUntilIdle();
    238 
    239   // Policy should be decoded and stored.
    240   ASSERT_TRUE(store_->policy());
    241   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
    242             store_->policy()->SerializeAsString());
    243   VerifyPolicyMap(store_.get());
    244   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
    245 }
    246 
    247 TEST_F(UserCloudPolicyStoreTest, StoreThenLoad) {
    248   // Store a simple policy and make sure it can be read back in.
    249   // policy.
    250   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    251   store_->Store(policy_.policy());
    252   RunUntilIdle();
    253 
    254   // Now, make sure the policy can be read back in from a second store.
    255   scoped_ptr<UserCloudPolicyStore> store2(
    256       new UserCloudPolicyStore(profile_.get(), policy_file()));
    257   store2->AddObserver(&observer_);
    258   EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
    259   store2->Load();
    260   RunUntilIdle();
    261 
    262   ASSERT_TRUE(store2->policy());
    263   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
    264             store2->policy()->SerializeAsString());
    265   VerifyPolicyMap(store2.get());
    266   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
    267   store2->RemoveObserver(&observer_);
    268 }
    269 
    270 TEST_F(UserCloudPolicyStoreTest, StoreThenLoadImmediately) {
    271   // Store a simple policy and make sure it can be read back in.
    272   // policy.
    273   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    274   store_->Store(policy_.policy());
    275   RunUntilIdle();
    276 
    277   // Now, make sure the policy can be read back in from a second store.
    278   scoped_ptr<UserCloudPolicyStore> store2(
    279       new UserCloudPolicyStore(profile_.get(), policy_file()));
    280   store2->AddObserver(&observer_);
    281   EXPECT_CALL(observer_, OnStoreLoaded(store2.get()));
    282   store2->LoadImmediately();  // Should load without running the message loop.
    283 
    284   ASSERT_TRUE(store2->policy());
    285   EXPECT_EQ(policy_.policy_data().SerializeAsString(),
    286             store2->policy()->SerializeAsString());
    287   VerifyPolicyMap(store2.get());
    288   EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status());
    289   store2->RemoveObserver(&observer_);
    290   EXPECT_TRUE(store2->policy_changed());
    291 }
    292 
    293 TEST_F(UserCloudPolicyStoreTest, StoreValidationError) {
    294   // Create an invalid policy (no policy type).
    295   policy_.policy_data().clear_policy_type();
    296   policy_.Build();
    297 
    298   // Store policy.
    299   ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
    300   store_->Store(policy_.policy());
    301   RunUntilIdle();
    302   ASSERT_FALSE(store_->policy());
    303   EXPECT_FALSE(store_->policy_changed());
    304 }
    305 
    306 TEST_F(UserCloudPolicyStoreTest, LoadValidationError) {
    307   // Force a validation error by changing the username after policy is stored.
    308   EXPECT_CALL(observer_, OnStoreLoaded(store_.get()));
    309   store_->Store(policy_.policy());
    310   RunUntilIdle();
    311 
    312   // Sign out, and sign back in as a different user, and try to load the profile
    313   // data (should fail due to mismatched username).
    314   SigninManagerFactory::GetForProfile(profile_.get())->SignOut();
    315   SigninManagerFactory::GetForProfile(profile_.get())->SetAuthenticatedUsername(
    316       "foobar (at) foobar.com");
    317 
    318   scoped_ptr<UserCloudPolicyStore> store2(
    319       new UserCloudPolicyStore(profile_.get(), policy_file()));
    320   store2->AddObserver(&observer_);
    321   ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
    322   store2->Load();
    323   RunUntilIdle();
    324 
    325   ASSERT_FALSE(store2->policy());
    326   store2->RemoveObserver(&observer_);
    327 
    328   // Sign out - we should be able to load the policy (don't check usernames
    329   // when signed out).
    330   SigninManagerFactory::GetForProfile(profile_.get())->SignOut();
    331   scoped_ptr<UserCloudPolicyStore> store3(
    332       new UserCloudPolicyStore(profile_.get(), policy_file()));
    333   store3->AddObserver(&observer_);
    334   EXPECT_CALL(observer_, OnStoreLoaded(store3.get()));
    335   store3->Load();
    336   RunUntilIdle();
    337 
    338   ASSERT_TRUE(store3->policy());
    339   store3->RemoveObserver(&observer_);
    340 
    341   // Now start a signin as a different user - this should fail validation.
    342   FakeSigninManager* signin = static_cast<FakeSigninManager*>(
    343       SigninManagerFactory::GetForProfile(profile_.get()));
    344   signin->set_auth_in_progress("foobar (at) foobar.com");
    345 
    346   scoped_ptr<UserCloudPolicyStore> store4(
    347       new UserCloudPolicyStore(profile_.get(), policy_file()));
    348   store4->AddObserver(&observer_);
    349   ExpectError(store4.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR);
    350   store4->Load();
    351   RunUntilIdle();
    352 
    353   ASSERT_FALSE(store4->policy());
    354   store4->RemoveObserver(&observer_);
    355 }
    356 
    357 TEST_F(UserCloudPolicyStoreTest, PolicyChanged) {
    358   EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).Times(7);
    359   EXPECT_FALSE(store_->policy_changed());
    360 
    361   // Clearing before storing should not result in a change.
    362   store_->Clear();
    363   EXPECT_FALSE(store_->policy_changed());
    364 
    365   // Storing an initial policy should result in a change.
    366   store_->Store(policy_.policy());
    367   RunUntilIdle();
    368   EXPECT_TRUE(store_->policy_changed());
    369 
    370   // Storing the same policy should not result in a change.
    371   store_->Store(policy_.policy());
    372   RunUntilIdle();
    373   EXPECT_FALSE(store_->policy_changed());
    374 
    375   // Storing a modified policy should result in a change.
    376   policy_.payload().mutable_urlblacklist()->mutable_value()->add_entries(
    377       "build.chromium.org");
    378   policy_.Build();
    379   store_->Store(policy_.policy());
    380   RunUntilIdle();
    381   EXPECT_TRUE(store_->policy_changed());
    382 
    383   // Storing the same policy should not result in a change.
    384   store_->Store(policy_.policy());
    385   RunUntilIdle();
    386   EXPECT_FALSE(store_->policy_changed());
    387 
    388   // Clearing the policy should result in a change.
    389   store_->Clear();
    390   EXPECT_TRUE(store_->policy_changed());
    391 
    392   // Clearing the policy again shouldn't result in a change.
    393   store_->Clear();
    394   EXPECT_FALSE(store_->policy_changed());
    395 }
    396 
    397 }  // namespace
    398 
    399 }  // namespace policy
    400