Home | History | Annotate | Download | only in storage
      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 "base/bind.h"
      6 #include "base/json/json_writer.h"
      7 #include "base/memory/ref_counted.h"
      8 #include "base/run_loop.h"
      9 #include "chrome/browser/extensions/api/storage/settings_frontend.h"
     10 #include "chrome/browser/extensions/api/storage/settings_namespace.h"
     11 #include "chrome/browser/extensions/api/storage/settings_sync_util.h"
     12 #include "chrome/browser/extensions/extension_apitest.h"
     13 #include "chrome/browser/extensions/extension_service.h"
     14 #include "chrome/browser/extensions/extension_system.h"
     15 #include "chrome/browser/extensions/extension_system_factory.h"
     16 #include "chrome/browser/extensions/extension_test_message_listener.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/ui/browser.h"
     19 #include "chrome/common/extensions/value_builder.h"
     20 #include "chrome/test/base/ui_test_utils.h"
     21 #include "sync/api/sync_change.h"
     22 #include "sync/api/sync_change_processor.h"
     23 #include "sync/api/sync_error_factory.h"
     24 #include "sync/api/sync_error_factory_mock.h"
     25 #include "testing/gmock/include/gmock/gmock.h"
     26 
     27 #if defined(ENABLE_CONFIGURATION_POLICY)
     28 #include "chrome/browser/policy/browser_policy_connector.h"
     29 #include "chrome/browser/policy/mock_configuration_policy_provider.h"
     30 #include "chrome/browser/policy/policy_bundle.h"
     31 #include "chrome/browser/policy/policy_domain_descriptor.h"
     32 #include "chrome/browser/policy/policy_map.h"
     33 #include "chrome/browser/policy/policy_service.h"
     34 #include "chrome/browser/policy/profile_policy_connector.h"
     35 #include "chrome/browser/policy/profile_policy_connector_factory.h"
     36 #endif
     37 
     38 namespace extensions {
     39 
     40 using settings_namespace::FromString;
     41 using settings_namespace::LOCAL;
     42 using settings_namespace::MANAGED;
     43 using settings_namespace::Namespace;
     44 using settings_namespace::SYNC;
     45 using settings_namespace::ToString;
     46 using testing::AnyNumber;
     47 using testing::Return;
     48 using testing::_;
     49 
     50 namespace {
     51 
     52 // TODO(kalman): test both EXTENSION_SETTINGS and APP_SETTINGS.
     53 const syncer::ModelType kModelType = syncer::EXTENSION_SETTINGS;
     54 
     55 // The managed_storage extension has a key defined in its manifest, so that
     56 // its extension ID is well-known and the policy system can push policies for
     57 // the extension.
     58 const char kManagedStorageExtensionId[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo";
     59 
     60 class NoopSyncChangeProcessor : public syncer::SyncChangeProcessor {
     61  public:
     62   virtual syncer::SyncError ProcessSyncChanges(
     63       const tracked_objects::Location& from_here,
     64       const syncer::SyncChangeList& change_list) OVERRIDE {
     65     return syncer::SyncError();
     66   }
     67 
     68   virtual ~NoopSyncChangeProcessor() {};
     69 };
     70 
     71 class SyncChangeProcessorDelegate : public syncer::SyncChangeProcessor {
     72  public:
     73   explicit SyncChangeProcessorDelegate(syncer::SyncChangeProcessor* recipient)
     74       : recipient_(recipient) {
     75     DCHECK(recipient_);
     76   }
     77   virtual ~SyncChangeProcessorDelegate() {}
     78 
     79   // syncer::SyncChangeProcessor implementation.
     80   virtual syncer::SyncError ProcessSyncChanges(
     81       const tracked_objects::Location& from_here,
     82       const syncer::SyncChangeList& change_list) OVERRIDE {
     83     return recipient_->ProcessSyncChanges(from_here, change_list);
     84   }
     85 
     86  private:
     87   // The recipient of all sync changes.
     88   syncer::SyncChangeProcessor* recipient_;
     89 
     90   DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
     91 };
     92 
     93 }  // namespace
     94 
     95 class ExtensionSettingsApiTest : public ExtensionApiTest {
     96  protected:
     97   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
     98     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
     99 
    100 #if defined(ENABLE_CONFIGURATION_POLICY)
    101     EXPECT_CALL(policy_provider_, IsInitializationComplete(_))
    102         .WillRepeatedly(Return(true));
    103     EXPECT_CALL(policy_provider_, RegisterPolicyDomain(_)).Times(AnyNumber());
    104     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
    105         &policy_provider_);
    106 #endif
    107   }
    108 
    109   void ReplyWhenSatisfied(
    110       Namespace settings_namespace,
    111       const std::string& normal_action,
    112       const std::string& incognito_action) {
    113     MaybeLoadAndReplyWhenSatisfied(
    114         settings_namespace, normal_action, incognito_action, NULL, false);
    115   }
    116 
    117   const Extension* LoadAndReplyWhenSatisfied(
    118       Namespace settings_namespace,
    119       const std::string& normal_action,
    120       const std::string& incognito_action,
    121       const std::string& extension_dir) {
    122     return MaybeLoadAndReplyWhenSatisfied(
    123         settings_namespace,
    124         normal_action,
    125         incognito_action,
    126         &extension_dir,
    127         false);
    128   }
    129 
    130   void FinalReplyWhenSatisfied(
    131       Namespace settings_namespace,
    132       const std::string& normal_action,
    133       const std::string& incognito_action) {
    134     MaybeLoadAndReplyWhenSatisfied(
    135         settings_namespace, normal_action, incognito_action, NULL, true);
    136   }
    137 
    138   void InitSync(syncer::SyncChangeProcessor* sync_processor) {
    139     base::MessageLoop::current()->RunUntilIdle();
    140     InitSyncWithSyncableService(
    141         sync_processor,
    142         browser()->profile()->GetExtensionService()->settings_frontend()->
    143               GetBackendForSync(kModelType));
    144   }
    145 
    146   void SendChanges(const syncer::SyncChangeList& change_list) {
    147     base::MessageLoop::current()->RunUntilIdle();
    148     SendChangesToSyncableService(
    149         change_list,
    150         browser()->profile()->GetExtensionService()->settings_frontend()->
    151               GetBackendForSync(kModelType));
    152   }
    153 
    154 #if defined(ENABLE_CONFIGURATION_POLICY)
    155   void SetPolicies(const base::DictionaryValue& policies) {
    156     scoped_ptr<policy::PolicyBundle> bundle(new policy::PolicyBundle());
    157     policy::PolicyMap& policy_map = bundle->Get(policy::PolicyNamespace(
    158         policy::POLICY_DOMAIN_EXTENSIONS, kManagedStorageExtensionId));
    159     policy_map.LoadFrom(
    160         &policies, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER);
    161     policy_provider_.UpdatePolicy(bundle.Pass());
    162   }
    163 #endif
    164 
    165  private:
    166   const Extension* MaybeLoadAndReplyWhenSatisfied(
    167       Namespace settings_namespace,
    168       const std::string& normal_action,
    169       const std::string& incognito_action,
    170       // May be NULL to imply not loading the extension.
    171       const std::string* extension_dir,
    172       bool is_final_action) {
    173     ExtensionTestMessageListener listener("waiting", true);
    174     ExtensionTestMessageListener listener_incognito("waiting_incognito", true);
    175 
    176     // Only load the extension after the listeners have been set up, to avoid
    177     // initialisation race conditions.
    178     const Extension* extension = NULL;
    179     if (extension_dir) {
    180       extension = LoadExtensionIncognito(
    181           test_data_dir_.AppendASCII("settings").AppendASCII(*extension_dir));
    182       EXPECT_TRUE(extension);
    183     }
    184 
    185     EXPECT_TRUE(listener.WaitUntilSatisfied());
    186     EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
    187 
    188     listener.Reply(
    189         CreateMessage(settings_namespace, normal_action, is_final_action));
    190     listener_incognito.Reply(
    191         CreateMessage(settings_namespace, incognito_action, is_final_action));
    192     return extension;
    193   }
    194 
    195   std::string CreateMessage(
    196       Namespace settings_namespace,
    197       const std::string& action,
    198       bool is_final_action) {
    199     scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue());
    200     message->SetString("namespace", ToString(settings_namespace));
    201     message->SetString("action", action);
    202     message->SetBoolean("isFinalAction", is_final_action);
    203     std::string message_json;
    204     base::JSONWriter::Write(message.get(), &message_json);
    205     return message_json;
    206   }
    207 
    208   void InitSyncWithSyncableService(
    209       syncer::SyncChangeProcessor* sync_processor,
    210       syncer::SyncableService* settings_service) {
    211     EXPECT_FALSE(settings_service->MergeDataAndStartSyncing(
    212         kModelType,
    213         syncer::SyncDataList(),
    214         scoped_ptr<syncer::SyncChangeProcessor>(
    215             new SyncChangeProcessorDelegate(sync_processor)),
    216         scoped_ptr<syncer::SyncErrorFactory>(
    217             new syncer::SyncErrorFactoryMock())).error().IsSet());
    218   }
    219 
    220   void SendChangesToSyncableService(
    221       const syncer::SyncChangeList& change_list,
    222       syncer::SyncableService* settings_service) {
    223     EXPECT_FALSE(
    224         settings_service->ProcessSyncChanges(FROM_HERE, change_list).IsSet());
    225   }
    226 
    227  protected:
    228 #if defined(ENABLE_CONFIGURATION_POLICY)
    229   policy::MockConfigurationPolicyProvider policy_provider_;
    230 #endif
    231 };
    232 
    233 // Flaky. http://crbug.com/248032
    234 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, DISABLED_SimpleTest) {
    235   ASSERT_TRUE(RunExtensionTest("settings/simple_test")) << message_;
    236 }
    237 
    238 // Structure of this test taken from IncognitoSplitMode.
    239 // Note that only split-mode incognito is tested, because spanning mode
    240 // incognito looks the same as normal mode when the only API activity comes
    241 // from background pages.
    242 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, SplitModeIncognito) {
    243   // We need 2 ResultCatchers because we'll be running the same test in both
    244   // regular and incognito mode.
    245   ResultCatcher catcher, catcher_incognito;
    246   catcher.RestrictToProfile(browser()->profile());
    247   catcher_incognito.RestrictToProfile(
    248       browser()->profile()->GetOffTheRecordProfile());
    249 
    250   LoadAndReplyWhenSatisfied(SYNC,
    251       "assertEmpty", "assertEmpty", "split_incognito");
    252   ReplyWhenSatisfied(SYNC, "noop", "setFoo");
    253   ReplyWhenSatisfied(SYNC, "assertFoo", "assertFoo");
    254   ReplyWhenSatisfied(SYNC, "clear", "noop");
    255   ReplyWhenSatisfied(SYNC, "assertEmpty", "assertEmpty");
    256   ReplyWhenSatisfied(SYNC, "setFoo", "noop");
    257   ReplyWhenSatisfied(SYNC, "assertFoo", "assertFoo");
    258   ReplyWhenSatisfied(SYNC, "noop", "removeFoo");
    259   FinalReplyWhenSatisfied(SYNC, "assertEmpty", "assertEmpty");
    260 
    261   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    262   EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
    263 }
    264 
    265 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
    266     OnChangedNotificationsBetweenBackgroundPages) {
    267   // We need 2 ResultCatchers because we'll be running the same test in both
    268   // regular and incognito mode.
    269   ResultCatcher catcher, catcher_incognito;
    270   catcher.RestrictToProfile(browser()->profile());
    271   catcher_incognito.RestrictToProfile(
    272       browser()->profile()->GetOffTheRecordProfile());
    273 
    274   LoadAndReplyWhenSatisfied(SYNC,
    275       "assertNoNotifications", "assertNoNotifications", "split_incognito");
    276   ReplyWhenSatisfied(SYNC, "noop", "setFoo");
    277   ReplyWhenSatisfied(SYNC,
    278       "assertAddFooNotification", "assertAddFooNotification");
    279   ReplyWhenSatisfied(SYNC, "clearNotifications", "clearNotifications");
    280   ReplyWhenSatisfied(SYNC, "removeFoo", "noop");
    281   FinalReplyWhenSatisfied(SYNC,
    282       "assertDeleteFooNotification", "assertDeleteFooNotification");
    283 
    284   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    285   EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
    286 }
    287 
    288 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
    289     SyncAndLocalAreasAreSeparate) {
    290   // We need 2 ResultCatchers because we'll be running the same test in both
    291   // regular and incognito mode.
    292   ResultCatcher catcher, catcher_incognito;
    293   catcher.RestrictToProfile(browser()->profile());
    294   catcher_incognito.RestrictToProfile(
    295       browser()->profile()->GetOffTheRecordProfile());
    296 
    297   LoadAndReplyWhenSatisfied(SYNC,
    298       "assertNoNotifications", "assertNoNotifications", "split_incognito");
    299 
    300   ReplyWhenSatisfied(SYNC, "noop", "setFoo");
    301   ReplyWhenSatisfied(SYNC, "assertFoo", "assertFoo");
    302   ReplyWhenSatisfied(SYNC,
    303       "assertAddFooNotification", "assertAddFooNotification");
    304   ReplyWhenSatisfied(LOCAL, "assertEmpty", "assertEmpty");
    305   ReplyWhenSatisfied(LOCAL, "assertNoNotifications", "assertNoNotifications");
    306 
    307   ReplyWhenSatisfied(SYNC, "clearNotifications", "clearNotifications");
    308 
    309   ReplyWhenSatisfied(LOCAL, "setFoo", "noop");
    310   ReplyWhenSatisfied(LOCAL, "assertFoo", "assertFoo");
    311   ReplyWhenSatisfied(LOCAL,
    312       "assertAddFooNotification", "assertAddFooNotification");
    313   ReplyWhenSatisfied(SYNC, "assertFoo", "assertFoo");
    314   ReplyWhenSatisfied(SYNC, "assertNoNotifications", "assertNoNotifications");
    315 
    316   ReplyWhenSatisfied(LOCAL, "clearNotifications", "clearNotifications");
    317 
    318   ReplyWhenSatisfied(LOCAL, "noop", "removeFoo");
    319   ReplyWhenSatisfied(LOCAL, "assertEmpty", "assertEmpty");
    320   ReplyWhenSatisfied(LOCAL,
    321       "assertDeleteFooNotification", "assertDeleteFooNotification");
    322   ReplyWhenSatisfied(SYNC, "assertFoo", "assertFoo");
    323   ReplyWhenSatisfied(SYNC, "assertNoNotifications", "assertNoNotifications");
    324 
    325   ReplyWhenSatisfied(LOCAL, "clearNotifications", "clearNotifications");
    326 
    327   ReplyWhenSatisfied(SYNC, "removeFoo", "noop");
    328   ReplyWhenSatisfied(SYNC, "assertEmpty", "assertEmpty");
    329   ReplyWhenSatisfied(SYNC,
    330       "assertDeleteFooNotification", "assertDeleteFooNotification");
    331   ReplyWhenSatisfied(LOCAL, "assertNoNotifications", "assertNoNotifications");
    332   FinalReplyWhenSatisfied(LOCAL, "assertEmpty", "assertEmpty");
    333 
    334   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    335   EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
    336 }
    337 
    338 // Disabled, see crbug.com/101110
    339 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
    340     DISABLED_OnChangedNotificationsFromSync) {
    341   // We need 2 ResultCatchers because we'll be running the same test in both
    342   // regular and incognito mode.
    343   ResultCatcher catcher, catcher_incognito;
    344   catcher.RestrictToProfile(browser()->profile());
    345   catcher_incognito.RestrictToProfile(
    346       browser()->profile()->GetOffTheRecordProfile());
    347 
    348   const Extension* extension =
    349       LoadAndReplyWhenSatisfied(SYNC,
    350           "assertNoNotifications", "assertNoNotifications", "split_incognito");
    351   const std::string& extension_id = extension->id();
    352 
    353   NoopSyncChangeProcessor sync_processor;
    354   InitSync(&sync_processor);
    355 
    356   // Set "foo" to "bar" via sync.
    357   syncer::SyncChangeList sync_changes;
    358   StringValue bar("bar");
    359   sync_changes.push_back(settings_sync_util::CreateAdd(
    360       extension_id, "foo", bar, kModelType));
    361   SendChanges(sync_changes);
    362 
    363   ReplyWhenSatisfied(SYNC,
    364       "assertAddFooNotification", "assertAddFooNotification");
    365   ReplyWhenSatisfied(SYNC, "clearNotifications", "clearNotifications");
    366 
    367   // Remove "foo" via sync.
    368   sync_changes.clear();
    369   sync_changes.push_back(settings_sync_util::CreateDelete(
    370       extension_id, "foo", kModelType));
    371   SendChanges(sync_changes);
    372 
    373   FinalReplyWhenSatisfied(SYNC,
    374       "assertDeleteFooNotification", "assertDeleteFooNotification");
    375 
    376   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    377   EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
    378 }
    379 
    380 // Disabled, see crbug.com/101110
    381 //
    382 // TODO: boring test, already done in the unit tests.  What we really should be
    383 // be testing is that the areas don't overlap.
    384 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
    385     DISABLED_OnChangedNotificationsFromSyncNotSentToLocal) {
    386   // We need 2 ResultCatchers because we'll be running the same test in both
    387   // regular and incognito mode.
    388   ResultCatcher catcher, catcher_incognito;
    389   catcher.RestrictToProfile(browser()->profile());
    390   catcher_incognito.RestrictToProfile(
    391       browser()->profile()->GetOffTheRecordProfile());
    392 
    393   const Extension* extension =
    394       LoadAndReplyWhenSatisfied(LOCAL,
    395           "assertNoNotifications", "assertNoNotifications", "split_incognito");
    396   const std::string& extension_id = extension->id();
    397 
    398   NoopSyncChangeProcessor sync_processor;
    399   InitSync(&sync_processor);
    400 
    401   // Set "foo" to "bar" via sync.
    402   syncer::SyncChangeList sync_changes;
    403   StringValue bar("bar");
    404   sync_changes.push_back(settings_sync_util::CreateAdd(
    405       extension_id, "foo", bar, kModelType));
    406   SendChanges(sync_changes);
    407 
    408   ReplyWhenSatisfied(LOCAL, "assertNoNotifications", "assertNoNotifications");
    409 
    410   // Remove "foo" via sync.
    411   sync_changes.clear();
    412   sync_changes.push_back(settings_sync_util::CreateDelete(
    413       extension_id, "foo", kModelType));
    414   SendChanges(sync_changes);
    415 
    416   FinalReplyWhenSatisfied(LOCAL,
    417       "assertNoNotifications", "assertNoNotifications");
    418 
    419   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    420   EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
    421 }
    422 
    423 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, IsStorageEnabled) {
    424   SettingsFrontend* frontend =
    425       browser()->profile()->GetExtensionService()->settings_frontend();
    426   EXPECT_TRUE(frontend->IsStorageEnabled(LOCAL));
    427   EXPECT_TRUE(frontend->IsStorageEnabled(SYNC));
    428 
    429 #if defined(ENABLE_CONFIGURATION_POLICY)
    430   EXPECT_TRUE(frontend->IsStorageEnabled(MANAGED));
    431 #else
    432   EXPECT_FALSE(frontend->IsStorageEnabled(MANAGED));
    433 #endif
    434 }
    435 
    436 #if defined(ENABLE_CONFIGURATION_POLICY)
    437 
    438 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, PolicyDomainDescriptor) {
    439   // Verifies that the PolicyDomainDescriptor for the extensions domain is
    440   // created on startup.
    441   Profile* profile = browser()->profile();
    442   ExtensionSystem* extension_system =
    443       ExtensionSystemFactory::GetForProfile(profile);
    444   if (!extension_system->ready().is_signaled()) {
    445     // Wait until the extension system is ready.
    446     base::RunLoop run_loop;
    447     extension_system->ready().Post(FROM_HERE, run_loop.QuitClosure());
    448     run_loop.Run();
    449     ASSERT_TRUE(extension_system->ready().is_signaled());
    450   }
    451 
    452   policy::ProfilePolicyConnector* connector =
    453       policy::ProfilePolicyConnectorFactory::GetForProfile(profile);
    454   policy::PolicyService* service = connector->policy_service();
    455   scoped_refptr<const policy::PolicyDomainDescriptor> descriptor =
    456       service->GetPolicyDomainDescriptor(policy::POLICY_DOMAIN_EXTENSIONS);
    457   EXPECT_TRUE(descriptor.get());
    458 }
    459 
    460 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorage) {
    461   // Set policies for the test extension.
    462   scoped_ptr<base::DictionaryValue> policy = extensions::DictionaryBuilder()
    463       .Set("string-policy", "value")
    464       .Set("int-policy", -123)
    465       .Set("double-policy", 456e7)
    466       .SetBoolean("boolean-policy", true)
    467       .Set("list-policy", extensions::ListBuilder()
    468           .Append("one")
    469           .Append("two")
    470           .Append("three"))
    471       .Set("dict-policy", extensions::DictionaryBuilder()
    472           .Set("list", extensions::ListBuilder()
    473               .Append(extensions::DictionaryBuilder()
    474                   .Set("one", 1)
    475                   .Set("two", 2))
    476               .Append(extensions::DictionaryBuilder()
    477                   .Set("three", 3))))
    478       .Build();
    479   SetPolicies(*policy);
    480   // Now run the extension.
    481   ASSERT_TRUE(RunExtensionTest("settings/managed_storage")) << message_;
    482 }
    483 
    484 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, PRE_ManagedStorageEvents) {
    485   ResultCatcher catcher;
    486 
    487   // This test starts without any test extensions installed.
    488   EXPECT_FALSE(GetSingleLoadedExtension());
    489   message_.clear();
    490 
    491   // Set policies for the test extension.
    492   scoped_ptr<base::DictionaryValue> policy = extensions::DictionaryBuilder()
    493       .Set("constant-policy", "aaa")
    494       .Set("changes-policy", "bbb")
    495       .Set("deleted-policy", "ccc")
    496       .Build();
    497   SetPolicies(*policy);
    498 
    499   ExtensionTestMessageListener ready_listener("ready", false);
    500   // Load the extension to install the event listener.
    501   const Extension* extension = LoadExtension(
    502       test_data_dir_.AppendASCII("settings/managed_storage_events"));
    503   ASSERT_TRUE(extension);
    504   // Wait until the extension sends the "ready" message.
    505   ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
    506 
    507   // Now change the policies and wait until the extension is done.
    508   policy = extensions::DictionaryBuilder()
    509       .Set("constant-policy", "aaa")
    510       .Set("changes-policy", "ddd")
    511       .Set("new-policy", "eee")
    512       .Build();
    513   SetPolicies(*policy);
    514   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    515 }
    516 
    517 #if defined(OS_CHROMEOS) || defined(OS_WIN)
    518 // Flakily times out. http://crbug.com/171477
    519 #define MAYBE_ManagedStorageEvents DISABLED_ManagedStorageEvents
    520 #else
    521 #define MAYBE_ManagedStorageEvents ManagedStorageEvents
    522 #endif
    523 
    524 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, MAYBE_ManagedStorageEvents) {
    525   // This test runs after PRE_ManagedStorageEvents without having deleted the
    526   // profile, so the extension is still around. While the browser restarted the
    527   // policy went back to the empty default, and so the extension should receive
    528   // the corresponding change events.
    529 
    530   ResultCatcher catcher;
    531 
    532   // Verify that the test extension is still installed.
    533   const Extension* extension = GetSingleLoadedExtension();
    534   ASSERT_TRUE(extension);
    535   EXPECT_EQ(kManagedStorageExtensionId, extension->id());
    536 
    537   // Running the test again skips the onInstalled callback, and just triggers
    538   // the onChanged notification.
    539   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    540 }
    541 
    542 #endif  // defined(ENABLE_CONFIGURATION_POLICY)
    543 
    544 IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorageDisabled) {
    545   // Disable the 'managed' namespace. This is redundant when
    546   // ENABLE_CONFIGURATION_POLICY is not defined.
    547   SettingsFrontend* frontend =
    548       browser()->profile()->GetExtensionService()->settings_frontend();
    549   frontend->DisableStorageForTesting(MANAGED);
    550   EXPECT_FALSE(frontend->IsStorageEnabled(MANAGED));
    551   // Now run the extension.
    552   ASSERT_TRUE(RunExtensionTest("settings/managed_storage_disabled"))
    553       << message_;
    554 }
    555 
    556 }  // namespace extensions
    557