Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Unified Diff: extensions/browser/process_manager_unittest.cc

Issue 381283002: Refactor code that defers extension background page loading (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: larger DeferLoadingBackgroundHosts Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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) {

Powered by Google App Engine
This is Rietveld 408576698