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_service.h"
6
7 #include <map>
8 #include <string>
9
10 #include "base/callback.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/stl_util.h"
16 #include "base/values.h"
17 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
18 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
19 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
20 #include "components/policy/core/common/cloud/policy_builder.h"
21 #include "components/policy/core/common/cloud/resource_cache.h"
22 #include "components/policy/core/common/external_data_fetcher.h"
23 #include "components/policy/core/common/policy_map.h"
24 #include "components/policy/core/common/policy_types.h"
25 #include "components/policy/core/common/schema.h"
26 #include "components/policy/core/common/schema_map.h"
27 #include "crypto/sha2.h"
28 #include "net/url_request/test_url_fetcher_factory.h"
29 #include "net/url_request/url_fetcher_delegate.h"
30 #include "net/url_request/url_request_context.h"
31 #include "net/url_request/url_request_context_getter.h"
32 #include "policy/proto/chrome_extension_policy.pb.h"
33 #include "policy/proto/device_management_backend.pb.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 namespace em = enterprise_management;
38
39 using testing::Mock;
40
41 namespace policy {
42
43 namespace {
44
45 const char kTestExtension[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
46 const char kTestExtension2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
47 const char kTestDownload[] = "http://example.com/getpolicy?id=123";
48
49 const char kTestPolicy[] =
50 "{"
51 " \"Name\": {"
52 " \"Value\": \"disabled\""
53 " },"
54 " \"Second\": {"
55 " \"Value\": \"maybe\","
56 " \"Level\": \"Recommended\""
57 " }"
58 "}";
59
60 const char kInvalidTestPolicy[] =
61 "{"
62 " \"Name\": {"
63 " \"Value\": \"published\""
64 " },"
65 " \"Undeclared Name\": {"
66 " \"Value\": \"not published\""
67 " }"
68 "}";
69
70 const char kTestSchema[] =
71 "{"
72 " \"type\": \"object\","
73 " \"properties\": {"
74 " \"Name\": { \"type\": \"string\" },"
75 " \"Second\": { \"type\": \"string\" }"
76 " }"
77 "}";
78
79 class MockComponentCloudPolicyDelegate
80 : public ComponentCloudPolicyService::Delegate {
81 public:
~MockComponentCloudPolicyDelegate()82 virtual ~MockComponentCloudPolicyDelegate() {}
83
84 MOCK_METHOD0(OnComponentCloudPolicyUpdated, void());
85 };
86
87 class TestURLRequestContextGetter : public net::URLRequestContextGetter {
88 public:
TestURLRequestContextGetter(scoped_refptr<base::SingleThreadTaskRunner> task_runner)89 explicit TestURLRequestContextGetter(
90 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
91 : task_runner_(task_runner) {}
GetURLRequestContext()92 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
93 return NULL;
94 }
95 virtual scoped_refptr<base::SingleThreadTaskRunner>
GetNetworkTaskRunner() const96 GetNetworkTaskRunner() const OVERRIDE {
97 return task_runner_;
98 }
99
100 private:
~TestURLRequestContextGetter()101 virtual ~TestURLRequestContextGetter() {}
102
103 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
104 };
105
106 } // namespace
107
108 class ComponentCloudPolicyServiceTest : public testing::Test {
109 protected:
ComponentCloudPolicyServiceTest()110 ComponentCloudPolicyServiceTest()
111 : client_(NULL),
112 core_(PolicyNamespaceKey(GetChromeUserPolicyType(), ""),
113 &store_,
114 loop_.message_loop_proxy()) {}
115
SetUp()116 virtual void SetUp() OVERRIDE {
117 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
118
119 cache_ = new ResourceCache(temp_dir_.path(), loop_.message_loop_proxy());
120 request_context_ =
121 new TestURLRequestContextGetter(loop_.message_loop_proxy());
122 service_.reset(new ComponentCloudPolicyService(
123 &delegate_,
124 ®istry_,
125 &core_,
126 make_scoped_ptr(cache_),
127 request_context_,
128 loop_.message_loop_proxy(),
129 loop_.message_loop_proxy()));
130
131 builder_.policy_data().set_policy_type(
132 dm_protocol::kChromeExtensionPolicyType);
133 builder_.policy_data().set_settings_entity_id(kTestExtension);
134 builder_.payload().set_download_url(kTestDownload);
135 builder_.payload().set_secure_hash(crypto::SHA256HashString(kTestPolicy));
136
137 expected_policy_.Set("Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
138 base::Value::CreateStringValue("disabled"), NULL);
139 expected_policy_.Set("Second", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
140 base::Value::CreateStringValue("maybe"), NULL);
141 }
142
TearDown()143 virtual void TearDown() OVERRIDE {
144 // The service cleans up its backend on the background thread.
145 service_.reset();
146 RunUntilIdle();
147 }
148
RunUntilIdle()149 void RunUntilIdle() {
150 base::RunLoop().RunUntilIdle();
151 }
152
Connect(size_t expected_namespaces_in_client)153 void Connect(size_t expected_namespaces_in_client) {
154 client_ = new MockCloudPolicyClient();
155 client_->SetDMToken(ComponentPolicyBuilder::kFakeToken);
156 EXPECT_EQ(0u, client_->namespaces_to_fetch_.size());
157
158 core_.Connect(scoped_ptr<CloudPolicyClient>(client_));
159
160 // |expected_namespaces_in_client| is the expected number of components
161 // that the ComponentCloudPolicyService will set at the |client_| at
162 // OnCoreConnected.
163 EXPECT_EQ(expected_namespaces_in_client,
164 client_->namespaces_to_fetch_.size());
165
166 // Also initialize the refresh scheduler, so that calls to
167 // core()->RefreshSoon() trigger a FetchPolicy() call on the mock |client_|.
168 // The |service_| should never trigger new fetches.
169 EXPECT_CALL(*client_, FetchPolicy());
170 core_.StartRefreshScheduler();
171 RunUntilIdle();
172 Mock::VerifyAndClearExpectations(client_);
173 }
174
LoadStore()175 void LoadStore() {
176 EXPECT_FALSE(store_.is_initialized());
177
178 em::PolicyData* data = new em::PolicyData();
179 data->set_username(ComponentPolicyBuilder::kFakeUsername);
180 data->set_request_token(ComponentPolicyBuilder::kFakeToken);
181 store_.policy_.reset(data);
182
183 store_.NotifyStoreLoaded();
184 RunUntilIdle();
185 EXPECT_TRUE(store_.is_initialized());
186 }
187
InitializeRegistry()188 void InitializeRegistry() {
189 registry_.RegisterComponent(
190 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kTestExtension),
191 CreateTestSchema());
192 registry_.SetReady(POLICY_DOMAIN_CHROME);
193 registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
194 }
195
PopulateCache()196 void PopulateCache() {
197 EXPECT_TRUE(cache_->Store(
198 "extension-policy", kTestExtension, CreateSerializedResponse()));
199 EXPECT_TRUE(
200 cache_->Store("extension-policy-data", kTestExtension, kTestPolicy));
201
202 builder_.policy_data().set_settings_entity_id(kTestExtension2);
203 EXPECT_TRUE(cache_->Store(
204 "extension-policy", kTestExtension2, CreateSerializedResponse()));
205 EXPECT_TRUE(
206 cache_->Store("extension-policy-data", kTestExtension2, kTestPolicy));
207 }
208
CreateResponse()209 scoped_ptr<em::PolicyFetchResponse> CreateResponse() {
210 builder_.Build();
211 return make_scoped_ptr(new em::PolicyFetchResponse(builder_.policy()));
212 }
213
CreateSerializedResponse()214 std::string CreateSerializedResponse() {
215 builder_.Build();
216 return builder_.GetBlob();
217 }
218
CreateTestSchema()219 Schema CreateTestSchema() {
220 std::string error;
221 Schema schema = Schema::Parse(kTestSchema, &error);
222 EXPECT_TRUE(schema.valid()) << error;
223 return schema;
224 }
225
226 base::MessageLoop loop_;
227 base::ScopedTempDir temp_dir_;
228 scoped_refptr<TestURLRequestContextGetter> request_context_;
229 net::TestURLFetcherFactory fetcher_factory_;
230 MockComponentCloudPolicyDelegate delegate_;
231 // |cache_| is owned by the |service_| and is invalid once the |service_|
232 // is destroyed.
233 ResourceCache* cache_;
234 MockCloudPolicyClient* client_;
235 MockCloudPolicyStore store_;
236 CloudPolicyCore core_;
237 SchemaRegistry registry_;
238 scoped_ptr<ComponentCloudPolicyService> service_;
239 ComponentPolicyBuilder builder_;
240 PolicyMap expected_policy_;
241 };
242
TEST_F(ComponentCloudPolicyServiceTest,InitializedAtConstructionTime)243 TEST_F(ComponentCloudPolicyServiceTest, InitializedAtConstructionTime) {
244 service_.reset();
245 Connect(1u);
246 LoadStore();
247 InitializeRegistry();
248
249 cache_ = new ResourceCache(temp_dir_.path(), loop_.message_loop_proxy());
250 service_.reset(new ComponentCloudPolicyService(&delegate_,
251 ®istry_,
252 &core_,
253 make_scoped_ptr(cache_),
254 request_context_,
255 loop_.message_loop_proxy(),
256 loop_.message_loop_proxy()));
257 EXPECT_FALSE(service_->is_initialized());
258
259 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
260 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
261 RunUntilIdle();
262 Mock::VerifyAndClearExpectations(&client_);
263 Mock::VerifyAndClearExpectations(&delegate_);
264
265 EXPECT_TRUE(service_->is_initialized());
266 EXPECT_EQ(2u, client_->namespaces_to_fetch_.size());
267 const PolicyBundle empty_bundle;
268 EXPECT_TRUE(service_->policy().Equals(empty_bundle));
269 }
270
TEST_F(ComponentCloudPolicyServiceTest,InitializeStoreThenRegistry)271 TEST_F(ComponentCloudPolicyServiceTest, InitializeStoreThenRegistry) {
272 Connect(2u);
273
274 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated()).Times(0);
275 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
276 LoadStore();
277 Mock::VerifyAndClearExpectations(client_);
278 Mock::VerifyAndClearExpectations(&delegate_);
279 EXPECT_FALSE(service_->is_initialized());
280
281 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
282 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
283 InitializeRegistry();
284 RunUntilIdle();
285 Mock::VerifyAndClearExpectations(client_);
286 Mock::VerifyAndClearExpectations(&delegate_);
287 EXPECT_TRUE(service_->is_initialized());
288
289 const PolicyBundle empty_bundle;
290 EXPECT_TRUE(service_->policy().Equals(empty_bundle));
291 }
292
TEST_F(ComponentCloudPolicyServiceTest,InitializeRegistryThenStore)293 TEST_F(ComponentCloudPolicyServiceTest, InitializeRegistryThenStore) {
294 Connect(2u);
295
296 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated()).Times(0);
297 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
298 InitializeRegistry();
299 RunUntilIdle();
300 Mock::VerifyAndClearExpectations(client_);
301 Mock::VerifyAndClearExpectations(&delegate_);
302 EXPECT_FALSE(service_->is_initialized());
303
304 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
305 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
306 LoadStore();
307 Mock::VerifyAndClearExpectations(client_);
308 Mock::VerifyAndClearExpectations(&delegate_);
309 EXPECT_TRUE(service_->is_initialized());
310 EXPECT_EQ(2u, client_->namespaces_to_fetch_.size());
311 const PolicyBundle empty_bundle;
312 EXPECT_TRUE(service_->policy().Equals(empty_bundle));
313 }
314
TEST_F(ComponentCloudPolicyServiceTest,InitializeWithCachedPolicy)315 TEST_F(ComponentCloudPolicyServiceTest, InitializeWithCachedPolicy) {
316 PopulateCache();
317 Connect(2u);
318
319 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
320 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
321 InitializeRegistry();
322 LoadStore();
323 Mock::VerifyAndClearExpectations(client_);
324 Mock::VerifyAndClearExpectations(&delegate_);
325
326 EXPECT_TRUE(service_->is_initialized());
327 EXPECT_EQ(2u, client_->namespaces_to_fetch_.size());
328
329 // kTestExtension2 is not in the registry so it was dropped.
330 std::map<std::string, std::string> contents;
331 cache_->LoadAllSubkeys("extension-policy", &contents);
332 ASSERT_EQ(1u, contents.size());
333 EXPECT_EQ(kTestExtension, contents.begin()->first);
334
335 PolicyBundle expected_bundle;
336 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
337 expected_bundle.Get(ns).CopyFrom(expected_policy_);
338 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
339 }
340
TEST_F(ComponentCloudPolicyServiceTest,FetchPolicy)341 TEST_F(ComponentCloudPolicyServiceTest, FetchPolicy) {
342 Connect(2u);
343 // Initialize the store and create the backend.
344 // A refresh is not needed, because no components are registered yet.
345 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
346 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
347 registry_.SetReady(POLICY_DOMAIN_CHROME);
348 registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
349 LoadStore();
350 Mock::VerifyAndClearExpectations(client_);
351 Mock::VerifyAndClearExpectations(&delegate_);
352 EXPECT_TRUE(service_->is_initialized());
353
354 // Register the components to fetch. The |service_| issues a new update
355 // because the new schema may filter different policies from the store.
356 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
357 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
358 registry_.RegisterComponent(
359 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kTestExtension),
360 CreateTestSchema());
361 RunUntilIdle();
362 Mock::VerifyAndClearExpectations(client_);
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 const 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
TEST_F(ComponentCloudPolicyServiceTest,LoadAndPurgeCache)391 TEST_F(ComponentCloudPolicyServiceTest, LoadAndPurgeCache) {
392 Connect(2u);
393 // Insert data in the cache.
394 PopulateCache();
395 registry_.RegisterComponent(
396 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kTestExtension2),
397 CreateTestSchema());
398 InitializeRegistry();
399
400 // Load the initial cache.
401 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
402 EXPECT_CALL(*client_, FetchPolicy()).Times(0);
403 LoadStore();
404 Mock::VerifyAndClearExpectations(client_);
405 Mock::VerifyAndClearExpectations(&delegate_);
406
407 PolicyBundle expected_bundle;
408 PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
409 expected_bundle.Get(ns).CopyFrom(expected_policy_);
410 ns.component_id = kTestExtension2;
411 expected_bundle.Get(ns).CopyFrom(expected_policy_);
412 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
413
414 // Now purge one of the extensions. This generates 2 notifications: one for
415 // the new, immediate filtering, and another once the backend comes back
416 // after purging the cache.
417 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated()).Times(2);
418 registry_.UnregisterComponent(
419 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kTestExtension));
420 RunUntilIdle();
421 Mock::VerifyAndClearExpectations(&delegate_);
422
423 ns.component_id = kTestExtension;
424 expected_bundle.Get(ns).Clear();
425 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
426
427 std::map<std::string, std::string> contents;
428 cache_->LoadAllSubkeys("extension-policy", &contents);
429 EXPECT_EQ(1u, contents.size());
430 EXPECT_TRUE(ContainsKey(contents, kTestExtension2));
431 }
432
TEST_F(ComponentCloudPolicyServiceTest,SignInAfterStartup)433 TEST_F(ComponentCloudPolicyServiceTest, SignInAfterStartup) {
434 registry_.SetReady(POLICY_DOMAIN_CHROME);
435 registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
436
437 // Initialize the store without credentials.
438 EXPECT_FALSE(store_.is_initialized());
439 EXPECT_FALSE(service_->is_initialized());
440 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
441 store_.NotifyStoreLoaded();
442 RunUntilIdle();
443 Mock::VerifyAndClearExpectations(&delegate_);
444 EXPECT_TRUE(service_->is_initialized());
445
446 // Register an extension.
447 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
448 registry_.RegisterComponent(
449 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kTestExtension),
450 CreateTestSchema());
451 RunUntilIdle();
452 Mock::VerifyAndClearExpectations(&delegate_);
453
454 // Now signin. A fetch will be requested for the new extension.
455 Connect(2u);
456
457 // Send the response to the service. The response data will be ignored,
458 // because the store doesn't have the updated credentials yet.
459 client_->SetPolicy(PolicyNamespaceKey(dm_protocol::kChromeExtensionPolicyType,
460 kTestExtension),
461 *CreateResponse());
462 service_->OnPolicyFetched(client_);
463 RunUntilIdle();
464
465 // The policy was ignored and no download is started because the store
466 // doesn't have credentials.
467 net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
468 EXPECT_FALSE(fetcher);
469
470 // Now update the |store_| with the updated policy, which includes
471 // credentials. The responses in the |client_| will be reloaded.
472 em::PolicyData* data = new em::PolicyData();
473 data->set_username(ComponentPolicyBuilder::kFakeUsername);
474 data->set_request_token(ComponentPolicyBuilder::kFakeToken);
475 store_.policy_.reset(data);
476 store_.NotifyStoreLoaded();
477 RunUntilIdle();
478
479 // The extension policy was validated this time, and the download is started.
480 fetcher = fetcher_factory_.GetFetcherByID(0);
481 ASSERT_TRUE(fetcher);
482 EXPECT_EQ(GURL(kTestDownload), fetcher->GetOriginalURL());
483 fetcher->set_response_code(200);
484 fetcher->SetResponseString(kTestPolicy);
485 fetcher->delegate()->OnURLFetchComplete(fetcher);
486
487 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
488 RunUntilIdle();
489 Mock::VerifyAndClearExpectations(&delegate_);
490
491 // The policy is now being served.
492 PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
493 PolicyBundle expected_bundle;
494 expected_bundle.Get(ns).CopyFrom(expected_policy_);
495 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
496 }
497
TEST_F(ComponentCloudPolicyServiceTest,SignOut)498 TEST_F(ComponentCloudPolicyServiceTest, SignOut) {
499 // Initialize everything and serve policy for a component.
500 PopulateCache();
501 LoadStore();
502 InitializeRegistry();
503
504 // The initial, cached policy will be served once the backend is initialized.
505 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
506 RunUntilIdle();
507 Mock::VerifyAndClearExpectations(&delegate_);
508 PolicyBundle expected_bundle;
509 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
510 expected_bundle.Get(ns).CopyFrom(expected_policy_);
511 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
512 std::map<std::string, std::string> contents;
513 cache_->LoadAllSubkeys("extension-policy", &contents);
514 ASSERT_EQ(1u, contents.size());
515
516 // Now sign in.
517 Connect(2u);
518
519 // Signing out removes all of the component policies from the service and
520 // from the cache. It does not trigger a refresh.
521 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
522 core_.Disconnect();
523 store_.policy_.reset();
524 store_.NotifyStoreLoaded();
525 RunUntilIdle();
526 Mock::VerifyAndClearExpectations(&delegate_);
527 const PolicyBundle empty_bundle;
528 EXPECT_TRUE(service_->policy().Equals(empty_bundle));
529 cache_->LoadAllSubkeys("extension-policy", &contents);
530 ASSERT_EQ(0u, contents.size());
531 }
532
TEST_F(ComponentCloudPolicyServiceTest,LoadInvalidPolicyFromCache)533 TEST_F(ComponentCloudPolicyServiceTest, LoadInvalidPolicyFromCache) {
534 // Put the invalid test policy in the cache. One of its policies will be
535 // loaded, the other should be filtered out by the schema.
536 builder_.payload().set_secure_hash(
537 crypto::SHA256HashString(kInvalidTestPolicy));
538 EXPECT_TRUE(cache_->Store(
539 "extension-policy", kTestExtension, CreateSerializedResponse()));
540 EXPECT_TRUE(cache_->Store(
541 "extension-policy-data", kTestExtension, kInvalidTestPolicy));
542
543 LoadStore();
544 InitializeRegistry();
545
546 // The initial, cached policy will be served once the backend is initialized.
547 EXPECT_CALL(delegate_, OnComponentCloudPolicyUpdated());
548 RunUntilIdle();
549 Mock::VerifyAndClearExpectations(&delegate_);
550
551 PolicyBundle expected_bundle;
552 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kTestExtension);
553 expected_bundle.Get(ns).Set("Name", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
554 base::Value::CreateStringValue("published"),
555 NULL);
556 EXPECT_TRUE(service_->policy().Equals(expected_bundle));
557 }
558
559 } // namespace policy
560