• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MockSchemaRegistryObserver()65   MockSchemaRegistryObserver() {}
~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:
SetUpInProcessBrowserTestFixture()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 
ReplyWhenSatisfied(Namespace settings_namespace,const std::string & normal_action,const std::string & incognito_action)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 
LoadAndReplyWhenSatisfied(Namespace settings_namespace,const std::string & normal_action,const std::string & incognito_action,const std::string & extension_dir)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 
FinalReplyWhenSatisfied(Namespace settings_namespace,const std::string & normal_action,const std::string & incognito_action)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 
GetSyncableService()117   syncer::SyncableService* GetSyncableService() {
118     return settings_sync_util::GetSyncableService(browser()->profile(),
119                                                   kModelType);
120   }
121 
InitSync(syncer::SyncChangeProcessor * sync_processor)122   void InitSync(syncer::SyncChangeProcessor* sync_processor) {
123     base::MessageLoop::current()->RunUntilIdle();
124     InitSyncWithSyncableService(sync_processor, GetSyncableService());
125   }
126 
SendChanges(const syncer::SyncChangeList & change_list)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)
SetPolicies(const base::DictionaryValue & policies)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:
MaybeLoadAndReplyWhenSatisfied(Namespace settings_namespace,const std::string & normal_action,const std::string & incognito_action,const std::string * extension_dir,bool is_final_action)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 
CreateMessage(Namespace settings_namespace,const std::string & action,bool is_final_action)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 
InitSyncWithSyncableService(syncer::SyncChangeProcessor * sync_processor,syncer::SyncableService * settings_service)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 
SendChangesToSyncableService(const syncer::SyncChangeList & change_list,syncer::SyncableService * settings_service)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,SimpleTest)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.
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,SplitModeIncognito)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,OnChangedNotificationsBetweenBackgroundPages)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,SyncAndLocalAreasAreSeparate)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
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,DISABLED_OnChangedNotificationsFromSync)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.
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,DISABLED_OnChangedNotificationsFromSyncNotSentToLocal)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,IsStorageEnabled)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,ExtensionsSchemas)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,ManagedStorage)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,DISABLED_PRE_ManagedStorageEvents)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,DISABLED_ManagedStorageEvents)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 
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,ManagedStorageDisabled)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