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