Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(315)

Side by Side Diff: chrome/browser/policy/component_cloud_policy_service_unittest.cc

Issue 12189011: Split up chrome/browser/policy subdirectory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, add chrome/browser/chromeos/policy/OWNERS Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "chrome/browser/policy/component_cloud_policy_service.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop.h"
9 #include "base/pickle.h"
10 #include "base/run_loop.h"
11 #include "base/sha1.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/stl_util.h"
14 #include "base/values.h"
15 #include "chrome/browser/policy/cloud_policy_constants.h"
16 #include "chrome/browser/policy/mock_cloud_policy_client.h"
17 #include "chrome/browser/policy/mock_cloud_policy_store.h"
18 #include "chrome/browser/policy/policy_builder.h"
19 #include "chrome/browser/policy/policy_map.h"
20 #include "chrome/browser/policy/policy_types.h"
21 #include "chrome/browser/policy/proto/chrome_extension_policy.pb.h"
22 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
23 #include "chrome/browser/policy/resource_cache.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "net/url_request/test_url_fetcher_factory.h"
27 #include "net/url_request/url_fetcher_delegate.h"
28 #include "net/url_request/url_request_context.h"
29 #include "net/url_request/url_request_context_getter.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace em = enterprise_management;
34
35 using testing::Mock;
36
37 namespace policy {
38
39 namespace {
40
41 const char kTestExtension[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
42 const char kTestExtension2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
43 const char kTestExtension3[] = "cccccccccccccccccccccccccccccccc";
44 const char kTestDownload[] = "http://example.com/getpolicy?id=123";
45 const char kTestDownload2[] = "http://example.com/getpolicy?id=456";
46 const char kTestPolicy[] =
47 "{"
48 " \"Name\": {"
49 " \"Value\": \"disabled\""
50 " },"
51 " \"Second\": {"
52 " \"Value\": \"maybe\","
53 " \"Level\": \"Recommended\""
54 " }"
55 "}";
56
57 class MockComponentCloudPolicyDelegate
58 : public ComponentCloudPolicyService::Delegate {
59 public:
60 virtual ~MockComponentCloudPolicyDelegate() {}
61
62 MOCK_METHOD0(OnComponentCloudPolicyRefreshNeeded, void());
63 MOCK_METHOD0(OnComponentCloudPolicyUpdated, void());
64 };
65
66 class TestURLRequestContextGetter : public net::URLRequestContextGetter {
67 public:
68 explicit TestURLRequestContextGetter(
69 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
70 : task_runner_(task_runner) {}
71 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
72 return NULL;
73 }
74 virtual scoped_refptr<base::SingleThreadTaskRunner>
75 GetNetworkTaskRunner() const OVERRIDE {
76 return task_runner_;
77 }
78
79 private:
80 virtual ~TestURLRequestContextGetter() {}
81
82 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
83 };
84
85 } // namespace
86
87 class ComponentCloudPolicyServiceTest : public testing::Test {
88 protected:
89 ComponentCloudPolicyServiceTest()
90 : ui_thread_(content::BrowserThread::UI, &loop_),
91 file_thread_(content::BrowserThread::FILE, &loop_) {}
92
93 virtual void SetUp() OVERRIDE {
94 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
95 cache_ = new ResourceCache(temp_dir_.path());
96 ASSERT_TRUE(cache_->IsOpen());
97 service_.reset(new ComponentCloudPolicyService(
98 &delegate_, &store_, make_scoped_ptr(cache_)));
99
100 builder_.policy_data().set_policy_type(
101 dm_protocol::kChromeExtensionPolicyType);
102 builder_.policy_data().set_settings_entity_id(kTestExtension);
103 builder_.payload().set_download_url(kTestDownload);
104 builder_.payload().set_secure_hash(base::SHA1HashString(kTestPolicy));
105
106 expected_policy_.Set("Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
107 base::Value::CreateStringValue("disabled"));
108 expected_policy_.Set("Second", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
109 base::Value::CreateStringValue("maybe"));
110
111 // A NULL |request_context_| is enough to construct the updater, but
112 // ComponentCloudPolicyService::Backend::LoadStore() tests the pointer when
113 // Connect() is called before the store was loaded.
114 request_context_ =
115 new TestURLRequestContextGetter(loop_.message_loop_proxy());
116 }
117
118 virtual void TearDown() OVERRIDE {
119 // The service cleans up its backend on the FILE thread.
120 service_.reset();
121 RunUntilIdle();
122 }
123
124 void RunUntilIdle() {
125 base::RunLoop().RunUntilIdle();
126 }
127
128 void LoadStore() {
129 EXPECT_FALSE(store_.is_initialized());
130 EXPECT_FALSE(service_->is_initialized());
131
132 em::PolicyData* data = new em::PolicyData();
133 data->set_username(ComponentPolicyBuilder::kFakeUsername);
134 data->set_request_token(ComponentPolicyBuilder::kFakeToken);
135 store_.policy_.reset(data);
136
137 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
138 store_.NotifyStoreLoaded();
139 RunUntilIdle();
140 Mock::VerifyAndClearExpectations(&delegate_);
141 EXPECT_TRUE(service_->is_initialized());
142 }
143
144 void PopulateCache() {
145 Pickle pickle;
146 pickle.WriteString(kTestExtension);
147 pickle.WriteString(kTestExtension2);
148 std::string data(reinterpret_cast<const char*>(pickle.data()),
149 pickle.size());
150 EXPECT_TRUE(
151 cache_->Store(ComponentCloudPolicyService::kComponentNamespaceCache,
152 dm_protocol::kChromeExtensionPolicyType,
153 data));
154
155 EXPECT_TRUE(cache_->Store(
156 "extension-policy", kTestExtension, CreateSerializedResponse()));
157 EXPECT_TRUE(
158 cache_->Store("extension-policy-data", kTestExtension, kTestPolicy));
159
160 builder_.policy_data().set_settings_entity_id(kTestExtension2);
161 EXPECT_TRUE(cache_->Store(
162 "extension-policy", kTestExtension2, CreateSerializedResponse()));
163 EXPECT_TRUE(
164 cache_->Store("extension-policy-data", kTestExtension2, kTestPolicy));
165
166 EXPECT_TRUE(cache_->Store("unrelated", "stuff", "here"));
167 }
168
169 scoped_ptr<em::PolicyFetchResponse> CreateResponse() {
170 builder_.Build();
171 return make_scoped_ptr(new em::PolicyFetchResponse(builder_.policy()));
172 }
173
174 std::string CreateSerializedResponse() {
175 builder_.Build();
176 return builder_.GetBlob();
177 }
178
179 MessageLoop loop_;
180 content::TestBrowserThread ui_thread_;
181 content::TestBrowserThread file_thread_;
182 base::ScopedTempDir temp_dir_;
183 scoped_refptr<TestURLRequestContextGetter> request_context_;
184 net::TestURLFetcherFactory fetcher_factory_;
185 MockComponentCloudPolicyDelegate delegate_;
186 // |cache_| is owned by the |service_| and is invalid once the |service_|
187 // is destroyed.
188 ResourceCache* cache_;
189 MockCloudPolicyClient client_;
190 MockCloudPolicyStore store_;
191 scoped_ptr<ComponentCloudPolicyService> service_;
192 ComponentPolicyBuilder builder_;
193 PolicyMap expected_policy_;
194 };
195
196 TEST_F(ComponentCloudPolicyServiceTest, InitializeWithoutCredentials) {
197 EXPECT_FALSE(service_->is_initialized());
198 // Run the background task to initialize the backend.
199 RunUntilIdle();
200 // Still waiting for the |store_|.
201 EXPECT_FALSE(service_->is_initialized());
202
203 // Initialize with a store without credentials.
204 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
205 store_.NotifyStoreLoaded();
206 RunUntilIdle();
207 EXPECT_TRUE(service_->is_initialized());
208 Mock::VerifyAndClearExpectations(&delegate_);
209 const PolicyBundle empty_bundle;
210 EXPECT_TRUE(service_->policy().Equals(empty_bundle));
211 }
212
213 TEST_F(ComponentCloudPolicyServiceTest, InitializationWithCachedComponents) {
214 // Store a previous list of components.
215 Pickle pickle;
216 pickle.WriteString("aa");
217 pickle.WriteString("bb");
218 pickle.WriteString("cc");
219 std::string data(reinterpret_cast<const char*>(pickle.data()), pickle.size());
220 EXPECT_TRUE(
221 cache_->Store(ComponentCloudPolicyService::kComponentNamespaceCache,
222 dm_protocol::kChromeExtensionPolicyType,
223 data));
224 // Store some garbage in another domain; it won't be fetched.
225 EXPECT_TRUE(cache_->Store(
226 ComponentCloudPolicyService::kComponentNamespaceCache, "garbage", data));
227
228 // Connect a client before initialization is complete.
229 service_->Connect(&client_, request_context_);
230 EXPECT_TRUE(client_.namespaces_to_fetch_.empty());
231
232 // Now load the backend.
233 LoadStore();
234
235 // The cached namespaces were added to the client.
236 std::set<PolicyNamespaceKey> set;
237 set.insert(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType, "aa"));
238 set.insert(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType, "bb"));
239 set.insert(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType, "cc"));
240 EXPECT_EQ(set, client_.namespaces_to_fetch_);
241
242 // And the bad components were wiped from the cache.
243 std::map<std::string, std::string> contents;
244 cache_->LoadAllSubkeys(ComponentCloudPolicyService::kComponentNamespaceCache,
245 &contents);
246 ASSERT_EQ(1u, contents.size());
247 EXPECT_EQ(std::string(dm_protocol::kChromeExtensionPolicyType),
248 contents.begin()->first);
249 }
250
251 TEST_F(ComponentCloudPolicyServiceTest, ConnectAfterRegister) {
252 // Add some components.
253 std::set<std::string> components;
254 components.insert(kTestExtension);
255 components.insert(kTestExtension2);
256 service_->RegisterPolicyDomain(POLICY_DOMAIN_EXTENSIONS, components);
257
258 // Now connect the client.
259 EXPECT_TRUE(client_.namespaces_to_fetch_.empty());
260 service_->Connect(&client_, request_context_);
261 EXPECT_TRUE(client_.namespaces_to_fetch_.empty());
262
263 // It receives the namespaces once the backend is initialized.
264 LoadStore();
265 std::set<PolicyNamespaceKey> set;
266 set.insert(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
267 kTestExtension));
268 set.insert(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
269 kTestExtension2));
270 EXPECT_EQ(set, client_.namespaces_to_fetch_);
271
272 // The current components were also persisted to the cache.
273 std::map<std::string, std::string> contents;
274 cache_->LoadAllSubkeys(ComponentCloudPolicyService::kComponentNamespaceCache,
275 &contents);
276 ASSERT_EQ(1u, contents.size());
277 EXPECT_EQ(std::string(dm_protocol::kChromeExtensionPolicyType),
278 contents.begin()->first);
279 const std::string data(contents.begin()->second);
280 Pickle pickle(data.data(), data.size());
281 PickleIterator pickit(pickle);
282 std::string value0;
283 std::string value1;
284 std::string tmp;
285 ASSERT_TRUE(pickit.ReadString(&value0));
286 ASSERT_TRUE(pickit.ReadString(&value1));
287 EXPECT_FALSE(pickit.ReadString(&tmp));
288 std::set<std::string> unpickled;
289 unpickled.insert(value0);
290 unpickled.insert(value1);
291 EXPECT_EQ(components, unpickled);
292 }
293
294 TEST_F(ComponentCloudPolicyServiceTest, StoreReadyAfterConnectAndRegister) {
295 // Add some previous data to the cache.
296 PopulateCache();
297
298 // Add some components.
299 std::set<std::string> components;
300 components.insert(kTestExtension);
301 service_->RegisterPolicyDomain(POLICY_DOMAIN_EXTENSIONS, components);
302
303 // And connect the client. Make the client have some policies, with a new
304 // download_url.
305 builder_.payload().set_download_url(kTestDownload2);
306 client_.SetPolicy(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
307 kTestExtension),
308 *CreateResponse());
309 service_->Connect(&client_, request_context_);
310
311 // Now make the store ready.
312 LoadStore();
313
314 // The components that were registed before have their caches purged.
315 std::map<std::string, std::string> contents;
316 cache_->LoadAllSubkeys("extension-policy", &contents);
317 EXPECT_EQ(1u, contents.size()); // kTestExtension2 was purged.
318 EXPECT_TRUE(ContainsKey(contents, kTestExtension));
319 cache_->LoadAllSubkeys("unrelated", &contents);
320 EXPECT_EQ(1u, contents.size()); // unrelated keys are not purged.
321 EXPECT_TRUE(ContainsKey(contents, "stuff"));
322
323 // The policy responses that the client already had start updating.
324 net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
325 ASSERT_TRUE(fetcher);
326 // Expect the URL of the client's PolicyFetchResponse, not the cached URL.
327 EXPECT_EQ(GURL(kTestDownload2), fetcher->GetOriginalURL());
328 }
329
330 TEST_F(ComponentCloudPolicyServiceTest, ConnectThenRegisterThenStoreReady) {
331 // Connect right after creating the service.
332 service_->Connect(&client_, request_context_);
333
334 // Now register the current components, before the backend has been
335 // initialized.
336 EXPECT_TRUE(client_.namespaces_to_fetch_.empty());
337 std::set<std::string> components;
338 components.insert(kTestExtension);
339 service_->RegisterPolicyDomain(POLICY_DOMAIN_EXTENSIONS, components);
340 EXPECT_TRUE(client_.namespaces_to_fetch_.empty());
341
342 // Now load the store. The client gets the namespaces.
343 LoadStore();
344 std::set<PolicyNamespaceKey> set;
345 set.insert(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
346 kTestExtension));
347 EXPECT_EQ(set, client_.namespaces_to_fetch_);
348 }
349
350 TEST_F(ComponentCloudPolicyServiceTest, FetchPolicy) {
351 // Initialize the store and create the backend, and connect the client.
352 LoadStore();
353 // A refresh is not needed, because no components were found.
354 EXPECT_CALL(delegate_, OnComponentCloudPolicyRefreshNeeded()).Times(0);
355 service_->Connect(&client_, request_context_);
356 Mock::VerifyAndClearExpectations(&delegate_);
357
358 // Register the components to fetch.
359 std::set<std::string> components;
360 components.insert(kTestExtension);
361 EXPECT_CALL(delegate_, OnComponentCloudPolicyRefreshNeeded());
362 service_->RegisterPolicyDomain(POLICY_DOMAIN_EXTENSIONS, components);
363 Mock::VerifyAndClearExpectations(&delegate_);
364
365 // Send back a fake policy fetch response.
366 client_.SetPolicy(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
367 kTestExtension),
368 *CreateResponse());
369 service_->OnPolicyFetched(&client_);
370 RunUntilIdle();
371
372 // That should have triggered the download fetch.
373 net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
374 ASSERT_TRUE(fetcher);
375 EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
376 fetcher->set_response_code(200);
377 fetcher->SetResponseString(kTestPolicy);
378 fetcher->delegate()->OnURLFetchComplete(fetcher);
379
380 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
381 RunUntilIdle();
382 Mock::VerifyAndClearExpectations(&delegate_);
383
384 // The policy is now being served.
385 PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
386 PolicyBundle expected_bundle;
387 expected_bundle.Get(ns).CopyFrom(expected_policy_);
388 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
389 }
390
391 TEST_F(ComponentCloudPolicyServiceTest, LoadAndPurgeCache) {
392 // Insert data in the cache.
393 PopulateCache();
394
395 // Load the initial cache.
396 LoadStore();
397
398 EXPECT_CALL(delegate_, OnComponentCloudPolicyRefreshNeeded());
399 service_->Connect(&client_, request_context_);
400 Mock::VerifyAndClearExpectations(&delegate_);
401
402 PolicyBundle expected_bundle;
403 PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
404 expected_bundle.Get(ns).CopyFrom(expected_policy_);
405 ns.component_id = kTestExtension2;
406 expected_bundle.Get(ns).CopyFrom(expected_policy_);
407 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
408
409 // Now purge one of the extensions.
410 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
411 // The service will start updating the components that are registered, which
412 // starts by fetching policy for them.
413 std::set<std::string> keep;
414 keep.insert(kTestExtension2);
415 service_->RegisterPolicyDomain(POLICY_DOMAIN_EXTENSIONS, keep);
416 RunUntilIdle();
417 Mock::VerifyAndClearExpectations(&delegate_);
418
419 ns.component_id = kTestExtension;
420 expected_bundle.Get(ns).Clear();
421 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
422
423 std::map<std::string, std::string> contents;
424 cache_->LoadAllSubkeys("extension-policy", &contents);
425 EXPECT_EQ(1u, contents.size());
426 EXPECT_TRUE(ContainsKey(contents, kTestExtension2));
427 cache_->LoadAllSubkeys("unrelated", &contents);
428 EXPECT_EQ(1u, contents.size());
429 EXPECT_TRUE(ContainsKey(contents, "stuff"));
430 }
431
432 TEST_F(ComponentCloudPolicyServiceTest, UpdateCredentials) {
433 // Do the same as LoadStore() but without the initial credentials.
434 EXPECT_FALSE(store_.is_initialized());
435 EXPECT_FALSE(service_->is_initialized());
436 store_.policy_.reset(new em::PolicyData()); // No credentials.
437 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
438 store_.NotifyStoreLoaded();
439 RunUntilIdle();
440 Mock::VerifyAndClearExpectations(&delegate_);
441 EXPECT_TRUE(service_->is_initialized());
442
443 // Connect the client and register an extension.
444 service_->Connect(&client_, request_context_);
445 EXPECT_CALL(delegate_, OnComponentCloudPolicyRefreshNeeded());
446 std::set<std::string> components;
447 components.insert(kTestExtension);
448 service_->RegisterPolicyDomain(POLICY_DOMAIN_EXTENSIONS, components);
449 Mock::VerifyAndClearExpectations(&delegate_);
450
451 // Send the response to the service. The response data will be rejected,
452 // because the store doesn't have the updated credentials yet.
453 client_.SetPolicy(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
454 kTestExtension),
455 *CreateResponse());
456 service_->OnPolicyFetched(&client_);
457 RunUntilIdle();
458
459 // The policy was not verified, and no download is started.
460 net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
461 EXPECT_FALSE(fetcher);
462
463 // Now update the |store_| with the updated policy, which includes
464 // credentials. The responses in the |client_| will be reloaded.
465 em::PolicyData* data = new em::PolicyData();
466 data->set_username(ComponentPolicyBuilder::kFakeUsername);
467 data->set_request_token(ComponentPolicyBuilder::kFakeToken);
468 store_.policy_.reset(data);
469 store_.NotifyStoreLoaded();
470 RunUntilIdle();
471
472 // The extension policy was validated this time, and the download is started.
473 fetcher = fetcher_factory_.GetFetcherByID(0);
474 ASSERT_TRUE(fetcher);
475 EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
476 fetcher->set_response_code(200);
477 fetcher->SetResponseString(kTestPolicy);
478 fetcher->delegate()->OnURLFetchComplete(fetcher);
479
480 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
481 RunUntilIdle();
482 Mock::VerifyAndClearExpectations(&delegate_);
483
484 // The policy is now being served.
485 PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
486 PolicyBundle expected_bundle;
487 expected_bundle.Get(ns).CopyFrom(expected_policy_);
488 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
489 }
490
491 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/component_cloud_policy_service.cc ('k') | chrome/browser/policy/component_cloud_policy_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698