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