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