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

Side by Side Diff: extensions/browser/process_manager.cc

Issue 381283002: Refactor code that defers extension background page loading (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cleanup, fix android 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/process_manager.h" 5 #include "extensions/browser/process_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 235 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
236 content::Source<BrowserContext>(original_context)); 236 content::Source<BrowserContext>(original_context));
237 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, 237 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
238 content::Source<BrowserContext>(context)); 238 content::Source<BrowserContext>(context));
239 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, 239 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
240 content::Source<BrowserContext>(context)); 240 content::Source<BrowserContext>(context));
241 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, 241 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
242 content::NotificationService::AllSources()); 242 content::NotificationService::AllSources());
243 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED, 243 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
244 content::NotificationService::AllSources()); 244 content::NotificationService::AllSources());
245 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
246 content::Source<BrowserContext>(original_context));
247 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 245 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
248 content::Source<BrowserContext>(context)); 246 content::Source<BrowserContext>(context));
249 if (context->IsOffTheRecord()) { 247 if (context->IsOffTheRecord()) {
250 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 248 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
251 content::Source<BrowserContext>(original_context)); 249 content::Source<BrowserContext>(original_context));
252 } 250 }
253 251
254 // Note: event_page_idle_time_ must be sufficiently larger (e.g. 2x) than 252 // Note: event_page_idle_time_ must be sufficiently larger (e.g. 2x) than
255 // kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals. 253 // kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals.
256 event_page_idle_time_ = base::TimeDelta::FromSeconds(10); 254 event_page_idle_time_ = base::TimeDelta::FromSeconds(10);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 } 295 }
298 296
299 void ProcessManager::RemoveObserver(ProcessManagerObserver* observer) { 297 void ProcessManager::RemoveObserver(ProcessManagerObserver* observer) {
300 observer_list_.RemoveObserver(observer); 298 observer_list_.RemoveObserver(observer);
301 } 299 }
302 300
303 bool ProcessManager::CreateBackgroundHost(const Extension* extension, 301 bool ProcessManager::CreateBackgroundHost(const Extension* extension,
304 const GURL& url) { 302 const GURL& url) {
305 // Hosted apps are taken care of from BackgroundContentsService. Ignore them 303 // Hosted apps are taken care of from BackgroundContentsService. Ignore them
306 // here. 304 // here.
307 if (extension->is_hosted_app() || 305 if (extension->is_hosted_app())
308 !ExtensionsBrowserClient::Get()->
309 IsBackgroundPageAllowed(GetBrowserContext())) {
310 return false; 306 return false;
311 } 307
308 // Don't create hosts if the embedder doesn't allow it.
309 ProcessManagerDelegate* delegate =
310 ExtensionsBrowserClient::Get()->GetProcessManagerDelegate();
311 if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext()))
312 return false;
312 313
313 // Don't create multiple background hosts for an extension. 314 // Don't create multiple background hosts for an extension.
314 if (GetBackgroundHostForExtension(extension->id())) 315 if (GetBackgroundHostForExtension(extension->id()))
315 return true; // TODO(kalman): return false here? It might break things... 316 return true; // TODO(kalman): return false here? It might break things...
316 317
317 ExtensionHost* host = 318 ExtensionHost* host =
318 new ExtensionHost(extension, GetSiteInstanceForURL(url), url, 319 new ExtensionHost(extension, GetSiteInstanceForURL(url), url,
319 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 320 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
320 host->CreateRenderViewSoon(); 321 host->CreateRenderViewSoon();
321 OnBackgroundHostCreated(host); 322 OnBackgroundHostCreated(host);
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 new ExtensionMsg_CancelSuspend(extension->id())); 608 new ExtensionMsg_CancelSuspend(extension->id()));
608 // This increment / decrement is to simulate an instantaneous event. This 609 // This increment / decrement is to simulate an instantaneous event. This
609 // has the effect of invalidating close_sequence_id, preventing any in 610 // has the effect of invalidating close_sequence_id, preventing any in
610 // progress closes from completing and starting a new close process if 611 // progress closes from completing and starting a new close process if
611 // necessary. 612 // necessary.
612 IncrementLazyKeepaliveCount(extension); 613 IncrementLazyKeepaliveCount(extension);
613 DecrementLazyKeepaliveCount(extension); 614 DecrementLazyKeepaliveCount(extension);
614 } 615 }
615 } 616 }
616 617
617 void ProcessManager::OnBrowserWindowReady() {
618 // If the extension system isn't ready yet the background hosts will be
619 // created via NOTIFICATION_EXTENSIONS_READY below.
620 ExtensionSystem* system = ExtensionSystem::Get(GetBrowserContext());
621 if (!system->ready().is_signaled())
622 return;
623
624 CreateBackgroundHostsForProfileStartup();
625 }
626
627 content::BrowserContext* ProcessManager::GetBrowserContext() const { 618 content::BrowserContext* ProcessManager::GetBrowserContext() const {
628 return site_instance_->GetBrowserContext(); 619 return site_instance_->GetBrowserContext();
629 } 620 }
630 621
631 void ProcessManager::SetKeepaliveImpulseCallbackForTesting( 622 void ProcessManager::SetKeepaliveImpulseCallbackForTesting(
632 const ImpulseCallbackForTesting& callback) { 623 const ImpulseCallbackForTesting& callback) {
633 keepalive_impulse_callback_for_testing_ = callback; 624 keepalive_impulse_callback_for_testing_ = callback;
634 } 625 }
635 626
636 void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting( 627 void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting(
637 const ImpulseCallbackForTesting& callback) { 628 const ImpulseCallbackForTesting& callback) {
638 keepalive_impulse_decrement_callback_for_testing_ = callback; 629 keepalive_impulse_decrement_callback_for_testing_ = callback;
639 } 630 }
640 631
641 void ProcessManager::Observe(int type, 632 void ProcessManager::Observe(int type,
642 const content::NotificationSource& source, 633 const content::NotificationSource& source,
643 const content::NotificationDetails& details) { 634 const content::NotificationDetails& details) {
644 switch (type) { 635 switch (type) {
645 case chrome::NOTIFICATION_EXTENSIONS_READY: 636 case chrome::NOTIFICATION_EXTENSIONS_READY: {
646 case chrome::NOTIFICATION_PROFILE_CREATED: { 637 // TODO(jamescook): Convert this to use ExtensionSystem::ready() instead
647 // Don't load background hosts now if the loading should be deferred. 638 // of a notification.
648 // Instead they will be loaded when a browser window for this profile 639 MaybeCreateStartupBackgroundHosts();
649 // (or an incognito profile from this profile) is ready.
650 if (DeferLoadingBackgroundHosts())
651 break;
652
653 CreateBackgroundHostsForProfileStartup();
654 break; 640 break;
655 } 641 }
656 642
657 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: { 643 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
658 BrowserContext* context = content::Source<BrowserContext>(source).ptr(); 644 BrowserContext* context = content::Source<BrowserContext>(source).ptr();
659 ExtensionSystem* system = ExtensionSystem::Get(context); 645 ExtensionSystem* system = ExtensionSystem::Get(context);
660 if (system->ready().is_signaled()) { 646 if (system->ready().is_signaled()) {
661 // The extension system is ready, so create the background host. 647 // The extension system is ready, so create the background host.
662 const Extension* extension = 648 const Extension* extension =
663 content::Details<const Extension>(details).ptr(); 649 content::Details<const Extension>(details).ptr();
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 return; 757 return;
772 if (attached) { 758 if (attached) {
773 // Keep the lazy background page alive while it's being inspected. 759 // Keep the lazy background page alive while it's being inspected.
774 CancelSuspend(extension); 760 CancelSuspend(extension);
775 IncrementLazyKeepaliveCount(extension); 761 IncrementLazyKeepaliveCount(extension);
776 } else { 762 } else {
777 DecrementLazyKeepaliveCount(extension); 763 DecrementLazyKeepaliveCount(extension);
778 } 764 }
779 } 765 }
780 766
781 void ProcessManager::CreateBackgroundHostsForProfileStartup() { 767 void ProcessManager::MaybeCreateStartupBackgroundHosts() {
782 if (startup_background_hosts_created_ || 768 if (startup_background_hosts_created_)
783 !ExtensionsBrowserClient::Get()->
784 IsBackgroundPageAllowed(GetBrowserContext())) {
785 return; 769 return;
786 }
787 770
788 const ExtensionSet& enabled_extensions = 771 // The embedder might disallow background pages entirely.
789 ExtensionRegistry::Get(GetBrowserContext())->enabled_extensions(); 772 ProcessManagerDelegate* delegate =
790 for (ExtensionSet::const_iterator extension = enabled_extensions.begin(); 773 ExtensionsBrowserClient::Get()->GetProcessManagerDelegate();
791 extension != enabled_extensions.end(); 774 if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext()))
792 ++extension) { 775 return;
793 CreateBackgroundHostForExtensionLoad(this, extension->get());
794 776
795 FOR_EACH_OBSERVER(ProcessManagerObserver, 777 // The embedder might want to defer background page loading. For example,
796 observer_list_, 778 // Chrome defers background page loading when it is launched to show the app
797 OnBackgroundHostStartup(*extension)); 779 // list, then triggers a load later when a browser window opens.
798 } 780 if (delegate &&
781 delegate->DeferCreatingStartupBackgroundHosts(GetBrowserContext()))
782 return;
783
784 CreateStartupBackgroundHosts();
799 startup_background_hosts_created_ = true; 785 startup_background_hosts_created_ = true;
800 786
801 // Background pages should only be loaded once. To prevent any further loads 787 // Background pages should only be loaded once. To prevent any further loads
802 // occurring, we remove the notification listeners. 788 // occurring, we remove the notification listeners.
803 BrowserContext* original_context = 789 BrowserContext* original_context =
804 ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext()); 790 ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext());
805 if (registrar_.IsRegistered( 791 if (registrar_.IsRegistered(
806 this, 792 this,
807 chrome::NOTIFICATION_PROFILE_CREATED,
808 content::Source<BrowserContext>(original_context))) {
809 registrar_.Remove(this,
810 chrome::NOTIFICATION_PROFILE_CREATED,
811 content::Source<BrowserContext>(original_context));
812 }
813 if (registrar_.IsRegistered(
814 this,
815 chrome::NOTIFICATION_EXTENSIONS_READY, 793 chrome::NOTIFICATION_EXTENSIONS_READY,
816 content::Source<BrowserContext>(original_context))) { 794 content::Source<BrowserContext>(original_context))) {
817 registrar_.Remove(this, 795 registrar_.Remove(this,
818 chrome::NOTIFICATION_EXTENSIONS_READY, 796 chrome::NOTIFICATION_EXTENSIONS_READY,
819 content::Source<BrowserContext>(original_context)); 797 content::Source<BrowserContext>(original_context));
820 } 798 }
821 } 799 }
822 800
801 void ProcessManager::CreateStartupBackgroundHosts() {
802 DCHECK(!startup_background_hosts_created_);
803 const ExtensionSet& enabled_extensions =
804 ExtensionRegistry::Get(GetBrowserContext())->enabled_extensions();
805 for (ExtensionSet::const_iterator extension = enabled_extensions.begin();
806 extension != enabled_extensions.end();
807 ++extension) {
808 CreateBackgroundHostForExtensionLoad(this, extension->get());
809
810 FOR_EACH_OBSERVER(ProcessManagerObserver,
811 observer_list_,
812 OnBackgroundHostStartup(*extension));
813 }
814 }
815
823 void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) { 816 void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) {
824 DCHECK_EQ(GetBrowserContext(), host->browser_context()); 817 DCHECK_EQ(GetBrowserContext(), host->browser_context());
825 background_hosts_.insert(host); 818 background_hosts_.insert(host);
826 819
827 if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { 820 if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) {
828 linked_ptr<base::ElapsedTimer> since_suspended( 821 linked_ptr<base::ElapsedTimer> since_suspended(
829 background_page_data_[host->extension()->id()]. 822 background_page_data_[host->extension()->id()].
830 since_suspended.release()); 823 since_suspended.release());
831 if (since_suspended.get()) { 824 if (since_suspended.get()) {
832 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime", 825 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime",
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 // Re-register all RenderViews for this extension. We do this to restore 870 // Re-register all RenderViews for this extension. We do this to restore
878 // the lazy_keepalive_count (if any) to properly reflect the number of open 871 // the lazy_keepalive_count (if any) to properly reflect the number of open
879 // views. 872 // views.
880 for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin(); 873 for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin();
881 it != all_extension_views_.end(); ++it) { 874 it != all_extension_views_.end(); ++it) {
882 if (GetExtensionID(it->first) == extension_id) 875 if (GetExtensionID(it->first) == extension_id)
883 IncrementLazyKeepaliveCountForView(it->first); 876 IncrementLazyKeepaliveCountForView(it->first);
884 } 877 }
885 } 878 }
886 879
887 bool ProcessManager::DeferLoadingBackgroundHosts() const {
888 // The extensions embedder may have special rules about background hosts.
889 return ExtensionsBrowserClient::Get()->DeferLoadingBackgroundHosts(
890 GetBrowserContext());
891 }
892
893 // 880 //
894 // IncognitoProcessManager 881 // IncognitoProcessManager
895 // 882 //
896 883
897 IncognitoProcessManager::IncognitoProcessManager( 884 IncognitoProcessManager::IncognitoProcessManager(
898 BrowserContext* incognito_context, 885 BrowserContext* incognito_context,
899 BrowserContext* original_context, 886 BrowserContext* original_context,
900 ProcessManager* original_manager) 887 ProcessManager* original_manager)
901 : ProcessManager(incognito_context, original_context), 888 : ProcessManager(incognito_context, original_context),
902 original_manager_(original_manager) { 889 original_manager_(original_manager) {
903 DCHECK(incognito_context->IsOffTheRecord()); 890 DCHECK(incognito_context->IsOffTheRecord());
904 891
905 // The original profile will have its own ProcessManager to 892 // The original profile will have its own ProcessManager to
906 // load the background pages of the spanning extensions. This process 893 // load the background pages of the spanning extensions. This process
907 // manager need only worry about the split mode extensions, which is handled 894 // manager need only worry about the split mode extensions, which is handled
908 // in the NOTIFICATION_BROWSER_WINDOW_READY notification handler. 895 // in the NOTIFICATION_BROWSER_WINDOW_READY notification handler.
909 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY, 896 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY,
910 content::Source<BrowserContext>(original_context)); 897 content::Source<BrowserContext>(original_context));
911 registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_CREATED,
912 content::Source<BrowserContext>(original_context));
913 } 898 }
914 899
915 bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension, 900 bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension,
916 const GURL& url) { 901 const GURL& url) {
917 if (IncognitoInfo::IsSplitMode(extension)) { 902 if (IncognitoInfo::IsSplitMode(extension)) {
918 if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled( 903 if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled(
919 extension->id(), GetBrowserContext())) 904 extension->id(), GetBrowserContext()))
920 return ProcessManager::CreateBackgroundHost(extension, url); 905 return ProcessManager::CreateBackgroundHost(extension, url);
921 } else { 906 } else {
922 // Do nothing. If an extension is spanning, then its original-profile 907 // Do nothing. If an extension is spanning, then its original-profile
923 // background page is shared with incognito, so we don't create another. 908 // background page is shared with incognito, so we don't create another.
924 } 909 }
925 return false; 910 return false;
926 } 911 }
927 912
928 SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) { 913 SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
929 ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext()); 914 ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext());
930 if (registry) { 915 if (registry) {
931 const Extension* extension = 916 const Extension* extension =
932 registry->enabled_extensions().GetExtensionOrAppByURL(url); 917 registry->enabled_extensions().GetExtensionOrAppByURL(url);
933 if (extension && !IncognitoInfo::IsSplitMode(extension)) { 918 if (extension && !IncognitoInfo::IsSplitMode(extension)) {
934 return original_manager_->GetSiteInstanceForURL(url); 919 return original_manager_->GetSiteInstanceForURL(url);
935 } 920 }
936 } 921 }
937 return ProcessManager::GetSiteInstanceForURL(url); 922 return ProcessManager::GetSiteInstanceForURL(url);
938 } 923 }
939 924
940 } // namespace extensions 925 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698