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