Home | History | Annotate | Download | only in policy
      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/async_policy_provider.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/values.h"
     10 #include "chrome/browser/policy/async_policy_loader.h"
     11 #include "chrome/browser/policy/external_data_fetcher.h"
     12 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
     13 #include "content/public/browser/browser_thread.h"
     14 #include "content/public/test/test_browser_thread.h"
     15 #include "policy/policy_constants.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 using testing::Mock;
     20 using testing::Return;
     21 using testing::Sequence;
     22 
     23 namespace policy {
     24 
     25 namespace {
     26 
     27 // Helper to write a policy in |bundle| with less code.
     28 void SetPolicy(PolicyBundle* bundle,
     29                const std::string& name,
     30                const std::string& value) {
     31   bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
     32       .Set(name,
     33            POLICY_LEVEL_MANDATORY,
     34            POLICY_SCOPE_USER,
     35            base::Value::CreateStringValue(value),
     36            NULL);
     37 }
     38 
     39 class MockPolicyLoader : public AsyncPolicyLoader {
     40  public:
     41   MockPolicyLoader();
     42   virtual ~MockPolicyLoader();
     43 
     44   // Load() returns a scoped_ptr<PolicyBundle> but it can't be mocked because
     45   // scoped_ptr is moveable but not copyable. This override forwards the
     46   // call to MockLoad() which returns a PolicyBundle*, and returns a copy
     47   // wrapped in a passed scoped_ptr.
     48   virtual scoped_ptr<PolicyBundle> Load() OVERRIDE;
     49 
     50   MOCK_METHOD0(MockLoad, const PolicyBundle*());
     51   MOCK_METHOD0(InitOnFile, void());
     52   MOCK_METHOD0(LastModificationTime, base::Time());
     53 
     54  private:
     55   DISALLOW_COPY_AND_ASSIGN(MockPolicyLoader);
     56 };
     57 
     58 MockPolicyLoader::MockPolicyLoader() {}
     59 
     60 MockPolicyLoader::~MockPolicyLoader() {}
     61 
     62 scoped_ptr<PolicyBundle> MockPolicyLoader::Load() {
     63   scoped_ptr<PolicyBundle> bundle;
     64   const PolicyBundle* loaded = MockLoad();
     65   if (loaded) {
     66     bundle.reset(new PolicyBundle());
     67     bundle->CopyFrom(*loaded);
     68   }
     69   return bundle.Pass();
     70 }
     71 
     72 }  // namespace
     73 
     74 class AsyncPolicyProviderTest : public testing::Test {
     75  protected:
     76   AsyncPolicyProviderTest();
     77   virtual ~AsyncPolicyProviderTest();
     78 
     79   virtual void SetUp() OVERRIDE;
     80   virtual void TearDown() OVERRIDE;
     81 
     82   PolicyBundle initial_bundle_;
     83   MockPolicyLoader* loader_;
     84   scoped_ptr<AsyncPolicyProvider> provider_;
     85 
     86   base::MessageLoop loop_;
     87 
     88  private:
     89   content::TestBrowserThread ui_thread_;
     90   content::TestBrowserThread file_thread_;
     91 
     92   DISALLOW_COPY_AND_ASSIGN(AsyncPolicyProviderTest);
     93 };
     94 
     95 AsyncPolicyProviderTest::AsyncPolicyProviderTest()
     96     : ui_thread_(content::BrowserThread::UI, &loop_),
     97       file_thread_(content::BrowserThread::FILE, &loop_) {}
     98 
     99 AsyncPolicyProviderTest::~AsyncPolicyProviderTest() {}
    100 
    101 void AsyncPolicyProviderTest::SetUp() {
    102   SetPolicy(&initial_bundle_, "policy", "initial");
    103   loader_ = new MockPolicyLoader();
    104   EXPECT_CALL(*loader_, LastModificationTime())
    105       .WillRepeatedly(Return(base::Time()));
    106   EXPECT_CALL(*loader_, InitOnFile()).Times(1);
    107   EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&initial_bundle_));
    108 
    109   provider_.reset(
    110       new AsyncPolicyProvider(scoped_ptr<AsyncPolicyLoader>(loader_)));
    111   provider_->Init();
    112   // Verify that the initial load is done synchronously:
    113   EXPECT_TRUE(provider_->policies().Equals(initial_bundle_));
    114 
    115   loop_.RunUntilIdle();
    116   Mock::VerifyAndClearExpectations(loader_);
    117 
    118   EXPECT_CALL(*loader_, LastModificationTime())
    119       .WillRepeatedly(Return(base::Time()));
    120 }
    121 
    122 void AsyncPolicyProviderTest::TearDown() {
    123   if (provider_) {
    124     provider_->Shutdown();
    125     provider_.reset();
    126   }
    127   loop_.RunUntilIdle();
    128 }
    129 
    130 TEST_F(AsyncPolicyProviderTest, RefreshPolicies) {
    131   PolicyBundle refreshed_bundle;
    132   SetPolicy(&refreshed_bundle, "policy", "refreshed");
    133   EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&refreshed_bundle));
    134 
    135   MockConfigurationPolicyObserver observer;
    136   provider_->AddObserver(&observer);
    137   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
    138   provider_->RefreshPolicies();
    139   loop_.RunUntilIdle();
    140   // The refreshed policies are now provided.
    141   EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
    142   provider_->RemoveObserver(&observer);
    143 }
    144 
    145 TEST_F(AsyncPolicyProviderTest, RefreshPoliciesTwice) {
    146   PolicyBundle refreshed_bundle;
    147   SetPolicy(&refreshed_bundle, "policy", "refreshed");
    148   EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&refreshed_bundle));
    149 
    150   MockConfigurationPolicyObserver observer;
    151   provider_->AddObserver(&observer);
    152   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
    153   provider_->RefreshPolicies();
    154   // Doesn't refresh before going through the FILE thread.
    155   Mock::VerifyAndClearExpectations(&observer);
    156 
    157   // Doesn't refresh if another RefreshPolicies request is made.
    158   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
    159   provider_->RefreshPolicies();
    160   Mock::VerifyAndClearExpectations(&observer);
    161 
    162   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
    163   loop_.RunUntilIdle();
    164   // The refreshed policies are now provided.
    165   EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
    166   Mock::VerifyAndClearExpectations(&observer);
    167   provider_->RemoveObserver(&observer);
    168 }
    169 
    170 TEST_F(AsyncPolicyProviderTest, RefreshPoliciesDuringReload) {
    171   PolicyBundle reloaded_bundle;
    172   SetPolicy(&reloaded_bundle, "policy", "reloaded");
    173   PolicyBundle refreshed_bundle;
    174   SetPolicy(&refreshed_bundle, "policy", "refreshed");
    175 
    176   Sequence load_sequence;
    177   // Reload.
    178   EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence)
    179                                    .WillOnce(Return(&reloaded_bundle));
    180   // RefreshPolicies.
    181   EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence)
    182                                    .WillOnce(Return(&refreshed_bundle));
    183 
    184   MockConfigurationPolicyObserver observer;
    185   provider_->AddObserver(&observer);
    186   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
    187 
    188   // A Reload is triggered before RefreshPolicies, and it shouldn't trigger
    189   // notifications.
    190   loader_->Reload(true);
    191   Mock::VerifyAndClearExpectations(&observer);
    192 
    193   // Doesn't refresh before going through the FILE thread.
    194   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
    195   provider_->RefreshPolicies();
    196   Mock::VerifyAndClearExpectations(&observer);
    197 
    198   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
    199   loop_.RunUntilIdle();
    200   // The refreshed policies are now provided, and the |reloaded_bundle| was
    201   // dropped.
    202   EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
    203   Mock::VerifyAndClearExpectations(&observer);
    204   provider_->RemoveObserver(&observer);
    205 }
    206 
    207 TEST_F(AsyncPolicyProviderTest, Shutdown) {
    208   EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&initial_bundle_));
    209 
    210   MockConfigurationPolicyObserver observer;
    211   provider_->AddObserver(&observer);
    212 
    213   // Though there is a pending Reload, the provider and the loader can be
    214   // deleted at any time.
    215   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
    216   loader_->Reload(true);
    217   Mock::VerifyAndClearExpectations(&observer);
    218 
    219   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
    220   provider_->Shutdown();
    221   loop_.RunUntilIdle();
    222   Mock::VerifyAndClearExpectations(&observer);
    223 
    224   provider_->RemoveObserver(&observer);
    225   provider_.reset();
    226 }
    227 
    228 }  // namespace policy
    229