Chromium Code Reviews| Index: extensions/browser/process_manager_unittest.cc |
| diff --git a/extensions/browser/process_manager_unittest.cc b/extensions/browser/process_manager_unittest.cc |
| index b72b1125a7f733302595108efb37833c8e9d3e64..a0a8a7aa716eb3bfa87a49e77bbc6409d135e73a 100644 |
| --- a/extensions/browser/process_manager_unittest.cc |
| +++ b/extensions/browser/process_manager_unittest.cc |
| @@ -5,11 +5,16 @@ |
| #include "extensions/browser/process_manager.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| +#include "components/keyed_service/content/browser_context_dependency_manager.h" |
| #include "content/public/browser/content_browser_client.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/site_instance.h" |
| #include "content/public/test/test_browser_context.h" |
| +#include "extensions/browser/extension_system.h" |
| +#include "extensions/browser/extension_system_provider.h" |
| #include "extensions/browser/test_extensions_browser_client.h" |
| +#include "extensions/common/extension_set.h" |
| +#include "extensions/common/one_shot_event.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| using content::BrowserContext; |
| @@ -33,12 +38,99 @@ class TestBrowserContextIncognito : public TestBrowserContext { |
| DISALLOW_COPY_AND_ASSIGN(TestBrowserContextIncognito); |
| }; |
| +// An ExtensionSystem that only provides a ready signal. |
| +class MockExtensionSystem : public ExtensionSystem { |
| + public: |
| + MockExtensionSystem() {} |
| + virtual ~MockExtensionSystem() {} |
| + |
| + // ExtensionSystem overrides: |
| + virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE {} |
| + virtual ExtensionService* extension_service() OVERRIDE { return NULL; } |
| + virtual RuntimeData* runtime_data() OVERRIDE { return NULL; } |
| + virtual ManagementPolicy* management_policy() OVERRIDE { return NULL; } |
| + virtual UserScriptMaster* user_script_master() OVERRIDE { return NULL; } |
| + virtual ProcessManager* process_manager() OVERRIDE { return NULL; } |
| + virtual StateStore* state_store() OVERRIDE { return NULL; } |
| + virtual StateStore* rules_store() OVERRIDE { return NULL; } |
| + virtual InfoMap* info_map() OVERRIDE { return NULL; } |
| + virtual LazyBackgroundTaskQueue* lazy_background_task_queue() OVERRIDE { |
| + return NULL; |
| + } |
| + virtual EventRouter* event_router() OVERRIDE { return NULL; } |
| + virtual ExtensionWarningService* warning_service() OVERRIDE { return NULL; } |
| + virtual Blacklist* blacklist() OVERRIDE { return NULL; } |
| + virtual ErrorConsole* error_console() OVERRIDE { return NULL; } |
| + virtual InstallVerifier* install_verifier() OVERRIDE { return NULL; } |
| + virtual QuotaService* quota_service() OVERRIDE { return NULL; } |
| + virtual const OneShotEvent& ready() const OVERRIDE { return ready_; } |
| + virtual ContentVerifier* content_verifier() OVERRIDE { return NULL; } |
| + virtual scoped_ptr<ExtensionSet> GetDependentExtensions( |
| + const Extension* extension) OVERRIDE { |
| + return scoped_ptr<ExtensionSet>(); |
| + } |
| + |
| + void SetReady() { |
| + ready_.Signal(); |
| + } |
| + |
| + private: |
| + OneShotEvent ready_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockExtensionSystem); |
| +}; |
| + |
| +// An ExtensionSystemProvider for the MockExtensionSystem. |
| +class MockExtensionSystemFactory : public ExtensionSystemProvider { |
|
Yoyo Zhou
2014/07/11 01:51:53
Is it possible to use SetTestingFactoryAndUse? You
James Cook
2014/07/11 21:19:29
It turns out I don't need any of this.
|
| + public: |
| + // ExtensionSystemProvider implementation: |
| + virtual ExtensionSystem* GetForBrowserContext( |
| + content::BrowserContext* context) OVERRIDE { |
| + return static_cast<ExtensionSystem*>( |
| + GetInstance()->GetServiceForBrowserContext(context, true)); |
| + } |
| + |
| + static MockExtensionSystemFactory* GetInstance() { |
| + return Singleton<MockExtensionSystemFactory>::get(); |
| + } |
| + |
| + private: |
| + friend struct DefaultSingletonTraits<MockExtensionSystemFactory>; |
| + |
| + MockExtensionSystemFactory() |
| + : ExtensionSystemProvider( |
| + "MockExtensionSystem", |
| + BrowserContextDependencyManager::GetInstance()) {} |
| + |
| + virtual ~MockExtensionSystemFactory() {} |
| + |
| + // BrowserContextKeyedServiceFactory implementation: |
| + virtual KeyedService* BuildServiceInstanceFor( |
| + content::BrowserContext* context) const OVERRIDE { |
| + return new MockExtensionSystem; |
| + } |
| + |
| + virtual content::BrowserContext* GetBrowserContextToUse( |
| + content::BrowserContext* context) const OVERRIDE { |
| + // Use a separate instance for incognito. |
| + return context; |
| + } |
| + |
| + virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE { |
| + return true; |
| + } |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockExtensionSystemFactory); |
| +}; |
| + |
| } // namespace |
| class ProcessManagerTest : public testing::Test { |
| public: |
| ProcessManagerTest() : extensions_browser_client_(&original_context_) { |
| extensions_browser_client_.SetIncognitoContext(&incognito_context_); |
| + extensions_browser_client_.set_extension_system_factory( |
| + MockExtensionSystemFactory::GetInstance()); |
| ExtensionsBrowserClient::Set(&extensions_browser_client_); |
| } |
| @@ -48,6 +140,23 @@ class ProcessManagerTest : public testing::Test { |
| BrowserContext* original_context() { return &original_context_; } |
| BrowserContext* incognito_context() { return &incognito_context_; } |
| + TestExtensionsBrowserClient* extensions_browser_client() { |
| + return &extensions_browser_client_; |
| + } |
| + |
| + virtual void SetUp() OVERRIDE { |
| + BrowserContextDependencyManager::GetInstance()-> |
| + CreateBrowserContextServicesForTest(&original_context_); |
| + BrowserContextDependencyManager::GetInstance()-> |
| + CreateBrowserContextServicesForTest(&incognito_context_); |
| + } |
| + |
| + virtual void TearDown() OVERRIDE { |
| + BrowserContextDependencyManager::GetInstance()-> |
| + DestroyBrowserContextServices(&incognito_context_); |
| + BrowserContextDependencyManager::GetInstance()-> |
| + DestroyBrowserContextServices(&original_context_); |
| + } |
| // Returns true if the notification |type| is registered for |manager| with |
| // source |context|. Pass NULL for |context| for all sources. |
| @@ -125,6 +234,84 @@ TEST_F(ProcessManagerTest, ExtensionNotificationRegistration) { |
| incognito_context())); |
| } |
| +// Test that startup background hosts can be created when the browser context is |
| +// created before the extension system is ready (the usual order). |
| +// |
| +// NOTE: This test does not try to create real ExtensionsHosts because |
| +// ExtensionHost is tightly coupled to WebContents and can't be constructed in |
| +// unit tests. |
| +TEST_F(ProcessManagerTest, StartupBrowserContextFirst) { |
| + scoped_ptr<ProcessManager> manager( |
| + ProcessManager::Create(original_context())); |
| + ASSERT_FALSE(manager->startup_background_hosts_created_for_test()); |
| + |
| + // Simulate the BrowserContext load completing. |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_PROFILE_CREATED, |
|
Yoyo Zhou
2014/07/11 01:51:53
We're trying to avoid this in src/extensions, righ
James Cook
2014/07/11 21:19:29
Yes, this was the initial "test driven development
|
| + content::Source<BrowserContext>(original_context()), |
| + content::NotificationService::NoDetails()); |
| + |
| + // Simulate the extension system becoming ready. Background hosts should be |
| + // created. |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_EXTENSIONS_READY, |
| + content::Source<BrowserContext>(original_context()), |
| + content::NotificationService::NoDetails()); |
| + EXPECT_TRUE(manager->startup_background_hosts_created_for_test()); |
| +} |
| + |
| +// Test that startup background hosts can be created if the extension system is |
| +// ready before the browser context (due to an abnormally slow async load). |
| +TEST_F(ProcessManagerTest, StartupExtensionsReadyFirst) { |
| + // Pretend the context is still loading. |
| + extensions_browser_client()->set_defer_loading_background_hosts(true); |
|
Yoyo Zhou
2014/07/11 01:51:53
I think this is an issue. If we set_defer_loading_
James Cook
2014/07/11 21:19:29
This should be clearer now. From the extensions mo
|
| + |
| + scoped_ptr<ProcessManager> manager( |
| + ProcessManager::Create(original_context())); |
| + ASSERT_FALSE(manager->startup_background_hosts_created_for_test()); |
| + |
| + // Simulate the extension system becoming ready. Should not create hosts |
| + // because the BrowserContext isn't valid. |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_EXTENSIONS_READY, |
| + content::Source<BrowserContext>(original_context()), |
| + content::NotificationService::NoDetails()); |
| + EXPECT_FALSE(manager->startup_background_hosts_created_for_test()); |
| + |
| + // Simulate the BrowserContext load completing. Now hosts should be created. |
| + extensions_browser_client()->set_defer_loading_background_hosts(false); |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_PROFILE_CREATED, |
| + content::Source<BrowserContext>(original_context()), |
| + content::NotificationService::NoDetails()); |
| + EXPECT_TRUE(manager->startup_background_hosts_created_for_test()); |
| +} |
| + |
| +// Test that an extension embedder can defer extension host creation initially, |
| +// then have the hosts created when a browser window opens. (Chrome does this |
| +// when it is launched to show the app list) |
| +TEST_F(ProcessManagerTest, DeferUntilBrowserWindowReady) { |
|
Yoyo Zhou
2014/07/11 01:51:53
Do you also want a test in the opposite order (bro
James Cook
2014/07/11 21:19:28
More tests added.
|
| + extensions_browser_client()->set_defer_loading_background_hosts(true); |
| + |
| + scoped_ptr<ProcessManager> manager( |
| + ProcessManager::Create(original_context())); |
| + ASSERT_FALSE(manager->startup_background_hosts_created_for_test()); |
| + |
| + // Extension system ready but not yet browser window. |
| + static_cast<MockExtensionSystem*>(ExtensionSystem::Get(original_context())) |
| + ->SetReady(); |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_EXTENSIONS_READY, |
| + content::Source<BrowserContext>(original_context()), |
| + content::NotificationService::NoDetails()); |
| + EXPECT_FALSE(manager->startup_background_hosts_created_for_test()); |
| + |
| + // Browser window opens. |
| + extensions_browser_client()->set_defer_loading_background_hosts(false); |
| + manager->OnBrowserWindowReady(); |
| + EXPECT_TRUE(manager->startup_background_hosts_created_for_test()); |
| +} |
| + |
| // Test that extensions get grouped in the right SiteInstance (and therefore |
| // process) based on their URLs. |
| TEST_F(ProcessManagerTest, ProcessGrouping) { |