Commit 736f4566 authored by gspencer@chromium.org's avatar gspencer@chromium.org

This defers starting background extension page RenderViews

until after session restore has completed.

This is mainly to help login/startup times so that Chrome is useful to
the user earlier.  To make sure that this is actually helping, this CL
includes a Finch experiment that will only enable the deferral on 50%
of the clients.

It is also expected that deferring these will help with some problems
we've seen when extensions attempt to do GAIA authentication.

BUG=279427,259791
TEST=Ran performance tests on ChromeOS and Linux

Review URL: https://chromiumcodereview.appspot.com/23618014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221621 0039d316-1c4b-4281-b951-d872f2087c98
parent 819afb5c
...@@ -137,6 +137,7 @@ ExtensionProcessManager* ExtensionProcessManager::Create(Profile* profile) { ...@@ -137,6 +137,7 @@ ExtensionProcessManager* ExtensionProcessManager::Create(Profile* profile) {
ExtensionProcessManager::ExtensionProcessManager(Profile* profile) ExtensionProcessManager::ExtensionProcessManager(Profile* profile)
: site_instance_(SiteInstance::Create(profile)), : site_instance_(SiteInstance::Create(profile)),
defer_background_host_creation_(false),
weak_ptr_factory_(this), weak_ptr_factory_(this),
devtools_callback_(base::Bind( devtools_callback_(base::Bind(
&ExtensionProcessManager::OnDevToolsStateChanged, &ExtensionProcessManager::OnDevToolsStateChanged,
...@@ -544,6 +545,16 @@ void ExtensionProcessManager::CancelSuspend(const Extension* extension) { ...@@ -544,6 +545,16 @@ void ExtensionProcessManager::CancelSuspend(const Extension* extension) {
} }
} }
void ExtensionProcessManager::DeferBackgroundHostCreation(bool defer) {
bool previous = defer_background_host_creation_;
defer_background_host_creation_ = defer;
// If we were deferred, and we switch to non-deferred, then create the
// background hosts.
if (previous && !defer_background_host_creation_)
CreateBackgroundHostsForProfileStartup();
}
void ExtensionProcessManager::Observe( void ExtensionProcessManager::Observe(
int type, int type,
const content::NotificationSource& source, const content::NotificationSource& source,
...@@ -568,12 +579,6 @@ void ExtensionProcessManager::Observe( ...@@ -568,12 +579,6 @@ void ExtensionProcessManager::Observe(
} }
case chrome::NOTIFICATION_EXTENSIONS_READY: case chrome::NOTIFICATION_EXTENSIONS_READY:
case chrome::NOTIFICATION_PROFILE_CREATED: { case chrome::NOTIFICATION_PROFILE_CREATED: {
// Don't load background hosts now if the loading should be deferred.
// Instead they will be loaded when a browser window for this profile
// (or an incognito profile from this profile) is ready.
if (DeferLoadingBackgroundHosts())
break;
CreateBackgroundHostsForProfileStartup(); CreateBackgroundHostsForProfileStartup();
break; break;
} }
...@@ -699,6 +704,13 @@ void ExtensionProcessManager::OnDevToolsStateChanged( ...@@ -699,6 +704,13 @@ void ExtensionProcessManager::OnDevToolsStateChanged(
} }
void ExtensionProcessManager::CreateBackgroundHostsForProfileStartup() { void ExtensionProcessManager::CreateBackgroundHostsForProfileStartup() {
// Don't load background hosts now if the loading should be deferred.
// Instead they will be loaded when a browser window for this profile
// (or an incognito profile from this profile) is ready, or when
// DeferBackgroundHostCreation is called with false.
if (DeferLoadingBackgroundHosts())
return;
ExtensionService* service = GetProfile()->GetExtensionService(); ExtensionService* service = GetProfile()->GetExtensionService();
for (ExtensionSet::const_iterator extension = service->extensions()->begin(); for (ExtensionSet::const_iterator extension = service->extensions()->begin();
extension != service->extensions()->end(); ++extension) { extension != service->extensions()->end(); ++extension) {
...@@ -776,6 +788,10 @@ void ExtensionProcessManager::ClearBackgroundPageData( ...@@ -776,6 +788,10 @@ void ExtensionProcessManager::ClearBackgroundPageData(
} }
bool ExtensionProcessManager::DeferLoadingBackgroundHosts() const { bool ExtensionProcessManager::DeferLoadingBackgroundHosts() const {
// Don't load background hosts now if the loading should be deferred.
if (defer_background_host_creation_)
return true;
// The profile may not be valid yet if it is still being initialized. // The profile may not be valid yet if it is still being initialized.
// In that case, defer loading, since it depends on an initialized profile. // In that case, defer loading, since it depends on an initialized profile.
// http://crbug.com/222473 // http://crbug.com/222473
......
...@@ -134,6 +134,11 @@ class ExtensionProcessManager : public content::NotificationObserver { ...@@ -134,6 +134,11 @@ class ExtensionProcessManager : public content::NotificationObserver {
// onSuspendCanceled() event to it. // onSuspendCanceled() event to it.
void CancelSuspend(const extensions::Extension* extension); void CancelSuspend(const extensions::Extension* extension);
// If |defer| is true background host creation is to be deferred until this is
// called again with |defer| set to false, at which point all deferred
// background hosts will be created. Defaults to false.
void DeferBackgroundHostCreation(bool defer);
protected: protected:
explicit ExtensionProcessManager(Profile* profile); explicit ExtensionProcessManager(Profile* profile);
...@@ -199,7 +204,8 @@ class ExtensionProcessManager : public content::NotificationObserver { ...@@ -199,7 +204,8 @@ class ExtensionProcessManager : public content::NotificationObserver {
// Returns true if loading background pages should be deferred. This is // Returns true if loading background pages should be deferred. This is
// true if there are no browser windows open and the browser process was // true if there are no browser windows open and the browser process was
// started to show the app launcher. // started to show the app launcher, or if DeferBackgroundHostCreation was
// called with true, or if the profile is not yet valid.
bool DeferLoadingBackgroundHosts() const; bool DeferLoadingBackgroundHosts() const;
void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached); void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached);
...@@ -219,6 +225,9 @@ class ExtensionProcessManager : public content::NotificationObserver { ...@@ -219,6 +225,9 @@ class ExtensionProcessManager : public content::NotificationObserver {
// sending a Suspend message; read from command-line switch. // sending a Suspend message; read from command-line switch.
base::TimeDelta event_page_suspending_time_; base::TimeDelta event_page_suspending_time_;
// If true, then creation of background hosts is suspended.
bool defer_background_host_creation_;
base::WeakPtrFactory<ExtensionProcessManager> weak_ptr_factory_; base::WeakPtrFactory<ExtensionProcessManager> weak_ptr_factory_;
base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_; base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_;
......
...@@ -302,7 +302,9 @@ void ExtensionSystemImpl::Shutdown() { ...@@ -302,7 +302,9 @@ void ExtensionSystemImpl::Shutdown() {
extension_process_manager_.reset(); extension_process_manager_.reset();
} }
void ExtensionSystemImpl::InitForRegularProfile(bool extensions_enabled) { void ExtensionSystemImpl::InitForRegularProfile(
bool extensions_enabled,
bool defer_background_creation) {
DCHECK(!profile_->IsOffTheRecord()); DCHECK(!profile_->IsOffTheRecord());
if (user_script_master() || extension_service()) if (user_script_master() || extension_service())
return; // Already initialized. return; // Already initialized.
...@@ -313,6 +315,9 @@ void ExtensionSystemImpl::InitForRegularProfile(bool extensions_enabled) { ...@@ -313,6 +315,9 @@ void ExtensionSystemImpl::InitForRegularProfile(bool extensions_enabled) {
extension_process_manager_.reset(ExtensionProcessManager::Create(profile_)); extension_process_manager_.reset(ExtensionProcessManager::Create(profile_));
extension_process_manager_->DeferBackgroundHostCreation(
defer_background_creation);
shared_->Init(extensions_enabled); shared_->Init(extensions_enabled);
} }
......
...@@ -52,8 +52,12 @@ class ExtensionSystem : public BrowserContextKeyedService { ...@@ -52,8 +52,12 @@ class ExtensionSystem : public BrowserContextKeyedService {
// Initializes extensions machinery. // Initializes extensions machinery.
// Component extensions are always enabled, external and user extensions // Component extensions are always enabled, external and user extensions
// are controlled by |extensions_enabled|. // are controlled by |extensions_enabled|. If |defer_background_creation| is
virtual void InitForRegularProfile(bool extensions_enabled) = 0; // true, then creation of background extension RenderViews will be deferred
// until ExtensionProcessManager::DeferBackgroundHostCreation is called with
// |defer| set to false.
virtual void InitForRegularProfile(bool extensions_enabled,
bool defer_background_creation) = 0;
// The ExtensionService is created at startup. // The ExtensionService is created at startup.
virtual ExtensionService* extension_service() = 0; virtual ExtensionService* extension_service() = 0;
...@@ -125,7 +129,8 @@ class ExtensionSystemImpl : public ExtensionSystem { ...@@ -125,7 +129,8 @@ class ExtensionSystemImpl : public ExtensionSystem {
// BrowserContextKeyedService implementation. // BrowserContextKeyedService implementation.
virtual void Shutdown() OVERRIDE; virtual void Shutdown() OVERRIDE;
virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE; virtual void InitForRegularProfile(bool extensions_enabled,
bool defer_background_creation) OVERRIDE;
virtual ExtensionService* extension_service() OVERRIDE; // shared virtual ExtensionService* extension_service() OVERRIDE; // shared
virtual ManagementPolicy* management_policy() OVERRIDE; // shared virtual ManagementPolicy* management_policy() OVERRIDE; // shared
......
...@@ -50,7 +50,8 @@ class TestExtensionSystem : public ExtensionSystem { ...@@ -50,7 +50,8 @@ class TestExtensionSystem : public ExtensionSystem {
void CreateSocketManager(); void CreateSocketManager();
virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE {} virtual void InitForRegularProfile(bool extensions_enabled,
bool defer_background_creation) OVERRIDE {}
void SetExtensionService(ExtensionService* service); void SetExtensionService(ExtensionService* service);
virtual ExtensionService* extension_service() OVERRIDE; virtual ExtensionService* extension_service() OVERRIDE;
virtual ManagementPolicy* management_policy() OVERRIDE; virtual ManagementPolicy* management_policy() OVERRIDE;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/file_util.h" #include "base/file_util.h"
#include "base/files/file_enumerator.h" #include "base/files/file_enumerator.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h" #include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h" #include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
...@@ -733,8 +734,37 @@ void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) { ...@@ -733,8 +734,37 @@ void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
void ProfileManager::DoFinalInitForServices(Profile* profile, void ProfileManager::DoFinalInitForServices(Profile* profile,
bool go_off_the_record) { bool go_off_the_record) {
#if defined(ENABLE_EXTENSIONS) #if defined(ENABLE_EXTENSIONS)
// Set up a field trial to determine the effectiveness of deferring
// creation of background extension RenderViews.
CR_DEFINE_STATIC_LOCAL(scoped_refptr<base::FieldTrial>, trial, ());
static bool defer_creation = false;
if (!trial.get()) {
const base::FieldTrial::Probability kDivisor = 100;
// Enable the deferred creation for 50% of the users.
base::FieldTrial::Probability probability_per_group = 50;
// After August 31, 2014 builds, it will always be in default group
// (defer_creation == false).
trial = base::FieldTrialList::FactoryGetFieldTrial(
"DeferBackgroundExtensionCreation",
kDivisor,
"RateLimited",
2014,
8,
31,
base::FieldTrial::ONE_TIME_RANDOMIZED,
NULL);
// Add group for deferred creation of background extension RenderViews.
int defer_creation_group =
trial->AppendGroup("Deferred", probability_per_group);
defer_creation = trial->group() == defer_creation_group;
}
extensions::ExtensionSystem::Get(profile)->InitForRegularProfile( extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
!go_off_the_record); !go_off_the_record, defer_creation);
// During tests, when |profile| is an instance of TestingProfile, // During tests, when |profile| is an instance of TestingProfile,
// ExtensionSystem might not create an ExtensionService. // ExtensionSystem might not create an ExtensionService.
if (extensions::ExtensionSystem::Get(profile)->extension_service()) { if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
......
...@@ -26,7 +26,8 @@ ExtensionDataTypeController::ExtensionDataTypeController( ...@@ -26,7 +26,8 @@ ExtensionDataTypeController::ExtensionDataTypeController(
ExtensionDataTypeController::~ExtensionDataTypeController() {} ExtensionDataTypeController::~ExtensionDataTypeController() {}
bool ExtensionDataTypeController::StartModels() { bool ExtensionDataTypeController::StartModels() {
extensions::ExtensionSystem::Get(profile_)->InitForRegularProfile(true); extensions::ExtensionSystem::Get(profile_)
->InitForRegularProfile(true, false);
return true; return true;
} }
......
...@@ -53,7 +53,8 @@ bool ExtensionSettingDataTypeController::PostTaskOnBackendThread( ...@@ -53,7 +53,8 @@ bool ExtensionSettingDataTypeController::PostTaskOnBackendThread(
bool ExtensionSettingDataTypeController::StartModels() { bool ExtensionSettingDataTypeController::StartModels() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
extensions::ExtensionSystem::Get(profile_)->InitForRegularProfile(true); extensions::ExtensionSystem::Get(profile_)
->InitForRegularProfile(true, false);
return true; return true;
} }
......
...@@ -21,7 +21,8 @@ ThemeDataTypeController::ThemeDataTypeController( ...@@ -21,7 +21,8 @@ ThemeDataTypeController::ThemeDataTypeController(
ThemeDataTypeController::~ThemeDataTypeController() {} ThemeDataTypeController::~ThemeDataTypeController() {}
bool ThemeDataTypeController::StartModels() { bool ThemeDataTypeController::StartModels() {
extensions::ExtensionSystem::Get(profile_)->InitForRegularProfile(true); extensions::ExtensionSystem::Get(profile_)
->InitForRegularProfile(true, false);
return true; return true;
} }
......
...@@ -95,10 +95,10 @@ void SyncAppHelper::SetupIfNecessary(SyncTest* test) { ...@@ -95,10 +95,10 @@ void SyncAppHelper::SetupIfNecessary(SyncTest* test) {
for (int i = 0; i < test->num_clients(); ++i) { for (int i = 0; i < test->num_clients(); ++i) {
extensions::ExtensionSystem::Get( extensions::ExtensionSystem::Get(
test->GetProfile(i))->InitForRegularProfile(true); test->GetProfile(i))->InitForRegularProfile(true, false);
} }
extensions::ExtensionSystem::Get( extensions::ExtensionSystem::Get(
test->verifier())->InitForRegularProfile(true); test->verifier())->InitForRegularProfile(true, false);
setup_completed_ = true; setup_completed_ = true;
} }
......
...@@ -252,7 +252,7 @@ bool SyncExtensionHelper::ExtensionStatesMatch( ...@@ -252,7 +252,7 @@ bool SyncExtensionHelper::ExtensionStatesMatch(
} }
void SyncExtensionHelper::SetupProfile(Profile* profile) { void SyncExtensionHelper::SetupProfile(Profile* profile) {
extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(true); extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(true, false);
profile_extensions_.insert(make_pair(profile, ExtensionNameMap())); profile_extensions_.insert(make_pair(profile, ExtensionNameMap()));
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "chrome/browser/defaults.h" #include "chrome/browser/defaults.h"
#include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extension_creator.h"
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/pack_extension_job.h" #include "chrome/browser/extensions/pack_extension_job.h"
#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/google/google_util.h" #include "chrome/browser/google/google_util.h"
...@@ -389,6 +390,14 @@ bool StartupBrowserCreatorImpl::Launch(Profile* profile, ...@@ -389,6 +390,14 @@ bool StartupBrowserCreatorImpl::Launch(Profile* profile,
ShellIntegration::MigrateChromiumShortcuts(); ShellIntegration::MigrateChromiumShortcuts();
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
#if defined(ENABLE_EXTENSIONS)
// If we deferred creation of background extension hosts, we want to create
// them now that the session (if any) has been restored.
ExtensionProcessManager* process_manager =
extensions::ExtensionSystem::Get(profile)->process_manager();
process_manager->DeferBackgroundHostCreation(false);
#endif
return true; return true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment