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