• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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/component_cloud_policy_updater.h"
6 
7 #include "base/callback.h"
8 #include "base/compiler_specific.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/sha1.h"
12 #include "base/test/test_simple_task_runner.h"
13 #include "base/values.h"
14 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
15 #include "components/policy/core/common/cloud/component_cloud_policy_store.h"
16 #include "components/policy/core/common/cloud/external_policy_data_fetcher.h"
17 #include "components/policy/core/common/cloud/policy_builder.h"
18 #include "components/policy/core/common/cloud/resource_cache.h"
19 #include "components/policy/core/common/external_data_fetcher.h"
20 #include "components/policy/core/common/policy_bundle.h"
21 #include "components/policy/core/common/policy_map.h"
22 #include "components/policy/core/common/policy_types.h"
23 #include "net/url_request/test_url_fetcher_factory.h"
24 #include "net/url_request/url_fetcher_delegate.h"
25 #include "net/url_request/url_request_context_getter.h"
26 #include "policy/proto/chrome_extension_policy.pb.h"
27 #include "policy/proto/device_management_backend.pb.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
31 
32 namespace em = enterprise_management;
33 
34 using testing::Mock;
35 
36 namespace policy {
37 
38 namespace {
39 
40 const char kTestExtension[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
41 const char kTestExtension2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
42 const char kTestExtension3[] = "cccccccccccccccccccccccccccccccc";
43 const char kTestDownload[] = "http://example.com/getpolicy?id=123";
44 const char kTestDownload2[] = "http://example.com/getpolicy?id=456";
45 const char kTestDownload3[] = "http://example.com/getpolicy?id=789";
46 const char kTestPolicy[] =
47     "{"
48     "  \"Name\": {"
49     "    \"Value\": \"disabled\""
50     "  },"
51     "  \"Second\": {"
52     "    \"Value\": \"maybe\","
53     "    \"Level\": \"Recommended\""
54     "  }"
55     "}";
56 
57 class MockComponentCloudPolicyStoreDelegate
58     : public ComponentCloudPolicyStore::Delegate {
59  public:
~MockComponentCloudPolicyStoreDelegate()60   virtual ~MockComponentCloudPolicyStoreDelegate() {}
61 
62   MOCK_METHOD0(OnComponentCloudPolicyStoreUpdated, void());
63 };
64 
65 }  // namespace
66 
67 class ComponentCloudPolicyUpdaterTest : public testing::Test {
68  protected:
69   virtual void SetUp() OVERRIDE;
70   virtual void TearDown() OVERRIDE;
71 
72   scoped_ptr<em::PolicyFetchResponse> CreateResponse();
73 
74   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
75   base::ScopedTempDir temp_dir_;
76   scoped_ptr<ResourceCache> cache_;
77   scoped_ptr<ComponentCloudPolicyStore> store_;
78   MockComponentCloudPolicyStoreDelegate store_delegate_;
79   net::TestURLFetcherFactory fetcher_factory_;
80   scoped_ptr<ExternalPolicyDataFetcherBackend> fetcher_backend_;
81   scoped_ptr<ComponentCloudPolicyUpdater> updater_;
82   ComponentPolicyBuilder builder_;
83   PolicyBundle expected_bundle_;
84 };
85 
SetUp()86 void ComponentCloudPolicyUpdaterTest::SetUp() {
87   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
88   task_runner_ = new base::TestSimpleTaskRunner();
89   cache_.reset(new ResourceCache(temp_dir_.path(), task_runner_));
90   store_.reset(new ComponentCloudPolicyStore(&store_delegate_, cache_.get()));
91   store_->SetCredentials(ComponentPolicyBuilder::kFakeUsername,
92                          ComponentPolicyBuilder::kFakeToken);
93   fetcher_factory_.set_remove_fetcher_on_delete(true);
94   fetcher_backend_.reset(new ExternalPolicyDataFetcherBackend(
95       task_runner_,
96       scoped_refptr<net::URLRequestContextGetter>()));
97   updater_.reset(new ComponentCloudPolicyUpdater(
98       task_runner_,
99       fetcher_backend_->CreateFrontend(task_runner_),
100       store_.get()));
101   ASSERT_EQ(store_->policy().end(), store_->policy().begin());
102 
103   builder_.policy_data().set_policy_type(
104       dm_protocol::kChromeExtensionPolicyType);
105   builder_.policy_data().set_settings_entity_id(kTestExtension);
106   builder_.payload().set_download_url(kTestDownload);
107   builder_.payload().set_secure_hash(base::SHA1HashString(kTestPolicy));
108 
109   PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
110   PolicyMap& policy = expected_bundle_.Get(ns);
111   policy.Set("Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
112              base::Value::CreateStringValue("disabled"), NULL);
113   policy.Set("Second", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
114              base::Value::CreateStringValue("maybe"), NULL);
115 }
116 
TearDown()117 void ComponentCloudPolicyUpdaterTest::TearDown() {
118   updater_.reset();
119   task_runner_->RunUntilIdle();
120 }
121 
122 scoped_ptr<em::PolicyFetchResponse>
CreateResponse()123     ComponentCloudPolicyUpdaterTest::CreateResponse() {
124   builder_.Build();
125   return make_scoped_ptr(new em::PolicyFetchResponse(builder_.policy()));
126 }
127 
TEST_F(ComponentCloudPolicyUpdaterTest,FetchAndCache)128 TEST_F(ComponentCloudPolicyUpdaterTest, FetchAndCache) {
129   // Submit a policy fetch response.
130   updater_->UpdateExternalPolicy(CreateResponse());
131   task_runner_->RunUntilIdle();
132 
133   // Verify that a download has been started.
134   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
135   ASSERT_TRUE(fetcher);
136   EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
137 
138   // Complete the download.
139   fetcher->set_response_code(200);
140   fetcher->SetResponseString(kTestPolicy);
141   fetcher->delegate()->OnURLFetchComplete(fetcher);
142   EXPECT_CALL(store_delegate_, OnComponentCloudPolicyStoreUpdated());
143   task_runner_->RunUntilIdle();
144   Mock::VerifyAndClearExpectations(&store_delegate_);
145 
146   // Verify that the downloaded policy is being served.
147   EXPECT_TRUE(store_->policy().Equals(expected_bundle_));
148 }
149 
TEST_F(ComponentCloudPolicyUpdaterTest,PolicyFetchResponseTooLarge)150 TEST_F(ComponentCloudPolicyUpdaterTest, PolicyFetchResponseTooLarge) {
151   // Submit a policy fetch response that exceeds the allowed maximum size.
152   std::string long_download("http://example.com/get?id=");
153   long_download.append(20 * 1024, '1');
154   builder_.payload().set_download_url(long_download);
155   updater_->UpdateExternalPolicy(CreateResponse());
156 
157   // Submit two valid policy fetch responses.
158   builder_.policy_data().set_settings_entity_id(kTestExtension2);
159   builder_.payload().set_download_url(kTestDownload2);
160   updater_->UpdateExternalPolicy(CreateResponse());
161   builder_.policy_data().set_settings_entity_id(kTestExtension3);
162   builder_.payload().set_download_url(kTestDownload3);
163   updater_->UpdateExternalPolicy(CreateResponse());
164   task_runner_->RunUntilIdle();
165 
166   // Verify that the first policy fetch response has been ignored and downloads
167   // have been started for the next two fetch responses instead.
168   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
169   ASSERT_TRUE(fetcher);
170   EXPECT_EQ(GURL(kTestDownload2), fetcher->GetOriginalURL());
171   fetcher = fetcher_factory_.GetFetcherByID(1);
172   ASSERT_TRUE(fetcher);
173   EXPECT_EQ(GURL(kTestDownload3), fetcher->GetOriginalURL());
174 }
175 
TEST_F(ComponentCloudPolicyUpdaterTest,PolicyFetchResponseInvalid)176 TEST_F(ComponentCloudPolicyUpdaterTest, PolicyFetchResponseInvalid) {
177   // Submit an invalid policy fetch response.
178   builder_.policy_data().set_username("wronguser@example.com");
179   updater_->UpdateExternalPolicy(CreateResponse());
180 
181   // Submit two valid policy fetch responses.
182   builder_.policy_data().set_username(ComponentPolicyBuilder::kFakeUsername);
183   builder_.policy_data().set_settings_entity_id(kTestExtension2);
184   builder_.payload().set_download_url(kTestDownload2);
185   updater_->UpdateExternalPolicy(CreateResponse());
186   builder_.policy_data().set_settings_entity_id(kTestExtension3);
187   builder_.payload().set_download_url(kTestDownload3);
188   updater_->UpdateExternalPolicy(CreateResponse());
189   task_runner_->RunUntilIdle();
190 
191   // Verify that the first policy fetch response has been ignored and downloads
192   // have been started for the next two fetch responses instead.
193   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
194   ASSERT_TRUE(fetcher);
195   EXPECT_EQ(GURL(kTestDownload2), fetcher->GetOriginalURL());
196   fetcher = fetcher_factory_.GetFetcherByID(1);
197   ASSERT_TRUE(fetcher);
198   EXPECT_EQ(GURL(kTestDownload3), fetcher->GetOriginalURL());
199 }
200 
TEST_F(ComponentCloudPolicyUpdaterTest,AlreadyCached)201 TEST_F(ComponentCloudPolicyUpdaterTest, AlreadyCached) {
202   // Cache policy for an extension.
203   builder_.Build();
204   PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
205   EXPECT_CALL(store_delegate_, OnComponentCloudPolicyStoreUpdated());
206   EXPECT_TRUE(store_->Store(ns,
207                             builder_.GetBlob(),
208                             base::SHA1HashString(kTestPolicy),
209                             kTestPolicy));
210   Mock::VerifyAndClearExpectations(&store_delegate_);
211 
212   // Submit a policy fetch response whose extension ID and hash match the
213   // already cached policy.
214   updater_->UpdateExternalPolicy(CreateResponse());
215   task_runner_->RunUntilIdle();
216 
217   // Verify that no download has been started.
218   EXPECT_FALSE(fetcher_factory_.GetFetcherByID(0));
219 }
220 
TEST_F(ComponentCloudPolicyUpdaterTest,PolicyDataInvalid)221 TEST_F(ComponentCloudPolicyUpdaterTest, PolicyDataInvalid) {
222   // Submit three policy fetch responses.
223   updater_->UpdateExternalPolicy(CreateResponse());
224   builder_.payload().set_download_url(kTestDownload2);
225   builder_.policy_data().set_settings_entity_id(kTestExtension2);
226   updater_->UpdateExternalPolicy(CreateResponse());
227   builder_.policy_data().set_settings_entity_id(kTestExtension3);
228   builder_.payload().set_download_url(kTestDownload3);
229   updater_->UpdateExternalPolicy(CreateResponse());
230   task_runner_->RunUntilIdle();
231 
232   // Verify that the first download has been started.
233   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
234   ASSERT_TRUE(fetcher);
235   EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
236 
237   // Verify that the second download has been started.
238   fetcher = fetcher_factory_.GetFetcherByID(1);
239   ASSERT_TRUE(fetcher);
240   EXPECT_EQ(GURL(kTestDownload2), fetcher->GetOriginalURL());
241 
242   // Indicate that the policy data size will exceed allowed maximum.
243   fetcher->delegate()->OnURLFetchDownloadProgress(fetcher, 6 * 1024 * 1024, -1);
244   task_runner_->RunUntilIdle();
245 
246   // Verify that the third download has been started.
247   fetcher = fetcher_factory_.GetFetcherByID(2);
248   ASSERT_TRUE(fetcher);
249   EXPECT_EQ(GURL(kTestDownload3), fetcher->GetOriginalURL());
250 }
251 
TEST_F(ComponentCloudPolicyUpdaterTest,FetchUpdatedData)252 TEST_F(ComponentCloudPolicyUpdaterTest, FetchUpdatedData) {
253   // Submit a policy fetch response.
254   updater_->UpdateExternalPolicy(CreateResponse());
255   task_runner_->RunUntilIdle();
256 
257   // Verify that the first download has been started.
258   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
259   ASSERT_TRUE(fetcher);
260   EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
261 
262   // Submit a second policy fetch response for the same extension with an
263   // updated download URL.
264   builder_.payload().set_download_url(kTestDownload2);
265   updater_->UpdateExternalPolicy(CreateResponse());
266   task_runner_->RunUntilIdle();
267 
268   // Verify that the first download is no longer running.
269   EXPECT_FALSE(fetcher_factory_.GetFetcherByID(0));
270 
271   // Verify that the second download has been started.
272   fetcher = fetcher_factory_.GetFetcherByID(1);
273   ASSERT_TRUE(fetcher);
274   EXPECT_EQ(GURL(kTestDownload2), fetcher->GetOriginalURL());
275 }
276 
TEST_F(ComponentCloudPolicyUpdaterTest,FetchUpdatedDataWithoutPolicy)277 TEST_F(ComponentCloudPolicyUpdaterTest, FetchUpdatedDataWithoutPolicy) {
278   // Submit a policy fetch response.
279   updater_->UpdateExternalPolicy(CreateResponse());
280   task_runner_->RunUntilIdle();
281 
282   // Verify that the download has been started.
283   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
284   ASSERT_TRUE(fetcher);
285   EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
286 
287   // Complete the download.
288   fetcher->set_response_code(200);
289   fetcher->SetResponseString(kTestPolicy);
290   fetcher->delegate()->OnURLFetchComplete(fetcher);
291   EXPECT_CALL(store_delegate_, OnComponentCloudPolicyStoreUpdated());
292   task_runner_->RunUntilIdle();
293   Mock::VerifyAndClearExpectations(&store_delegate_);
294 
295   // Verify that the downloaded policy is being served.
296   EXPECT_TRUE(store_->policy().Equals(expected_bundle_));
297 
298   // Submit a second policy fetch response for the same extension with no
299   // download URL, meaning that no policy should be provided for this extension.
300   builder_.payload().clear_download_url();
301   builder_.payload().clear_secure_hash();
302   EXPECT_CALL(store_delegate_, OnComponentCloudPolicyStoreUpdated());
303   updater_->UpdateExternalPolicy(CreateResponse());
304   Mock::VerifyAndClearExpectations(&store_delegate_);
305   task_runner_->RunUntilIdle();
306 
307   // Verify that no download has been started.
308   EXPECT_FALSE(fetcher_factory_.GetFetcherByID(1));
309 
310   // Verify that the policy is no longer being served.
311   const PolicyBundle empty_bundle;
312   EXPECT_TRUE(store_->policy().Equals(empty_bundle));
313 }
314 
TEST_F(ComponentCloudPolicyUpdaterTest,NoPolicy)315 TEST_F(ComponentCloudPolicyUpdaterTest, NoPolicy) {
316   // Submit a policy fetch response with a valid download URL.
317   updater_->UpdateExternalPolicy(CreateResponse());
318   task_runner_->RunUntilIdle();
319 
320   // Verify that the download has been started.
321   EXPECT_TRUE(fetcher_factory_.GetFetcherByID(0));
322 
323   // Update the policy fetch response before the download has finished. The new
324   // policy fetch response has no download URL.
325   builder_.payload().Clear();
326   updater_->UpdateExternalPolicy(CreateResponse());
327   task_runner_->RunUntilIdle();
328 
329   // Verify that the download is no longer running.
330   EXPECT_FALSE(fetcher_factory_.GetFetcherByID(0));
331 }
332 
TEST_F(ComponentCloudPolicyUpdaterTest,CancelUpdate)333 TEST_F(ComponentCloudPolicyUpdaterTest, CancelUpdate) {
334   // Submit a policy fetch response with a valid download URL.
335   updater_->UpdateExternalPolicy(CreateResponse());
336   task_runner_->RunUntilIdle();
337 
338   // Verify that the download has been started.
339   EXPECT_TRUE(fetcher_factory_.GetFetcherByID(0));
340 
341   // Now cancel that update before the download completes.
342   EXPECT_CALL(store_delegate_, OnComponentCloudPolicyStoreUpdated()).Times(0);
343   updater_->CancelUpdate(
344       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kTestExtension));
345   task_runner_->RunUntilIdle();
346   Mock::VerifyAndClearExpectations(&store_delegate_);
347   EXPECT_FALSE(fetcher_factory_.GetFetcherByID(0));
348 }
349 
350 }  // namespace policy
351