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

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: rebase on top of chrome_browser_extensions.gypi GN changes 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
« no previous file with comments | « extensions/browser/process_manager.h ('k') | extensions/browser/process_manager_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 15 matching lines...) Expand all
26 #include "content/public/browser/web_contents.h" 26 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_contents_delegate.h" 27 #include "content/public/browser/web_contents_delegate.h"
28 #include "content/public/browser/web_contents_observer.h" 28 #include "content/public/browser/web_contents_observer.h"
29 #include "content/public/browser/web_contents_user_data.h" 29 #include "content/public/browser/web_contents_user_data.h"
30 #include "content/public/common/renderer_preferences.h" 30 #include "content/public/common/renderer_preferences.h"
31 #include "content/public/common/url_constants.h" 31 #include "content/public/common/url_constants.h"
32 #include "extensions/browser/extension_host.h" 32 #include "extensions/browser/extension_host.h"
33 #include "extensions/browser/extension_registry.h" 33 #include "extensions/browser/extension_registry.h"
34 #include "extensions/browser/extension_system.h" 34 #include "extensions/browser/extension_system.h"
35 #include "extensions/browser/extensions_browser_client.h" 35 #include "extensions/browser/extensions_browser_client.h"
36 #include "extensions/browser/process_manager_delegate.h"
36 #include "extensions/browser/process_manager_observer.h" 37 #include "extensions/browser/process_manager_observer.h"
37 #include "extensions/browser/view_type_utils.h" 38 #include "extensions/browser/view_type_utils.h"
38 #include "extensions/common/constants.h" 39 #include "extensions/common/constants.h"
39 #include "extensions/common/extension.h" 40 #include "extensions/common/extension.h"
40 #include "extensions/common/extension_messages.h" 41 #include "extensions/common/extension_messages.h"
41 #include "extensions/common/manifest_handlers/background_info.h" 42 #include "extensions/common/manifest_handlers/background_info.h"
42 #include "extensions/common/manifest_handlers/incognito_info.h" 43 #include "extensions/common/manifest_handlers/incognito_info.h"
43 #include "extensions/common/one_shot_event.h" 44 #include "extensions/common/one_shot_event.h"
44 #include "extensions/common/switches.h" 45 #include "extensions/common/switches.h"
45 46
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 239 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
239 content::Source<BrowserContext>(original_context)); 240 content::Source<BrowserContext>(original_context));
240 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, 241 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
241 content::Source<BrowserContext>(context)); 242 content::Source<BrowserContext>(context));
242 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, 243 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
243 content::Source<BrowserContext>(context)); 244 content::Source<BrowserContext>(context));
244 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, 245 registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
245 content::NotificationService::AllSources()); 246 content::NotificationService::AllSources());
246 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED, 247 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
247 content::NotificationService::AllSources()); 248 content::NotificationService::AllSources());
248 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
249 content::Source<BrowserContext>(original_context));
250 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 249 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
251 content::Source<BrowserContext>(context)); 250 content::Source<BrowserContext>(context));
252 if (context->IsOffTheRecord()) { 251 if (context->IsOffTheRecord()) {
253 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 252 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
254 content::Source<BrowserContext>(original_context)); 253 content::Source<BrowserContext>(original_context));
255 } 254 }
256 255
257 // Note: event_page_idle_time_ must be sufficiently larger (e.g. 2x) than 256 // Note: event_page_idle_time_ must be sufficiently larger (e.g. 2x) than
258 // kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals. 257 // kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals.
259 event_page_idle_time_ = base::TimeDelta::FromSeconds(10); 258 event_page_idle_time_ = base::TimeDelta::FromSeconds(10);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 } 299 }
301 300
302 void ProcessManager::RemoveObserver(ProcessManagerObserver* observer) { 301 void ProcessManager::RemoveObserver(ProcessManagerObserver* observer) {
303 observer_list_.RemoveObserver(observer); 302 observer_list_.RemoveObserver(observer);
304 } 303 }
305 304
306 bool ProcessManager::CreateBackgroundHost(const Extension* extension, 305 bool ProcessManager::CreateBackgroundHost(const Extension* extension,
307 const GURL& url) { 306 const GURL& url) {
308 // Hosted apps are taken care of from BackgroundContentsService. Ignore them 307 // Hosted apps are taken care of from BackgroundContentsService. Ignore them
309 // here. 308 // here.
310 if (extension->is_hosted_app() || 309 if (extension->is_hosted_app())
311 !ExtensionsBrowserClient::Get()->
312 IsBackgroundPageAllowed(GetBrowserContext())) {
313 return false; 310 return false;
314 } 311
312 // Don't create hosts if the embedder doesn't allow it.
313 ProcessManagerDelegate* delegate =
314 ExtensionsBrowserClient::Get()->GetProcessManagerDelegate();
315 if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext()))
316 return false;
315 317
316 // Don't create multiple background hosts for an extension. 318 // Don't create multiple background hosts for an extension.
317 if (GetBackgroundHostForExtension(extension->id())) 319 if (GetBackgroundHostForExtension(extension->id()))
318 return true; // TODO(kalman): return false here? It might break things... 320 return true; // TODO(kalman): return false here? It might break things...
319 321
320 ExtensionHost* host = 322 ExtensionHost* host =
321 new ExtensionHost(extension, GetSiteInstanceForURL(url), url, 323 new ExtensionHost(extension, GetSiteInstanceForURL(url), url,
322 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); 324 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
323 host->CreateRenderViewSoon(); 325 host->CreateRenderViewSoon();
324 OnBackgroundHostCreated(host); 326 OnBackgroundHostCreated(host);
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 new ExtensionMsg_CancelSuspend(extension->id())); 615 new ExtensionMsg_CancelSuspend(extension->id()));
614 // This increment / decrement is to simulate an instantaneous event. This 616 // This increment / decrement is to simulate an instantaneous event. This
615 // has the effect of invalidating close_sequence_id, preventing any in 617 // has the effect of invalidating close_sequence_id, preventing any in
616 // progress closes from completing and starting a new close process if 618 // progress closes from completing and starting a new close process if
617 // necessary. 619 // necessary.
618 IncrementLazyKeepaliveCount(extension); 620 IncrementLazyKeepaliveCount(extension);
619 DecrementLazyKeepaliveCount(extension); 621 DecrementLazyKeepaliveCount(extension);
620 } 622 }
621 } 623 }
622 624
623 void ProcessManager::OnBrowserWindowReady() {
624 // If the extension system isn't ready yet the background hosts will be
625 // created via NOTIFICATION_EXTENSIONS_READY below.
626 ExtensionSystem* system = ExtensionSystem::Get(GetBrowserContext());
627 if (!system->ready().is_signaled())
628 return;
629
630 CreateBackgroundHostsForProfileStartup();
631 }
632
633 content::BrowserContext* ProcessManager::GetBrowserContext() const { 625 content::BrowserContext* ProcessManager::GetBrowserContext() const {
634 return site_instance_->GetBrowserContext(); 626 return site_instance_->GetBrowserContext();
635 } 627 }
636 628
637 void ProcessManager::SetKeepaliveImpulseCallbackForTesting( 629 void ProcessManager::SetKeepaliveImpulseCallbackForTesting(
638 const ImpulseCallbackForTesting& callback) { 630 const ImpulseCallbackForTesting& callback) {
639 keepalive_impulse_callback_for_testing_ = callback; 631 keepalive_impulse_callback_for_testing_ = callback;
640 } 632 }
641 633
642 void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting( 634 void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting(
643 const ImpulseCallbackForTesting& callback) { 635 const ImpulseCallbackForTesting& callback) {
644 keepalive_impulse_decrement_callback_for_testing_ = callback; 636 keepalive_impulse_decrement_callback_for_testing_ = callback;
645 } 637 }
646 638
647 void ProcessManager::Observe(int type, 639 void ProcessManager::Observe(int type,
648 const content::NotificationSource& source, 640 const content::NotificationSource& source,
649 const content::NotificationDetails& details) { 641 const content::NotificationDetails& details) {
650 switch (type) { 642 switch (type) {
651 case chrome::NOTIFICATION_EXTENSIONS_READY: 643 case chrome::NOTIFICATION_EXTENSIONS_READY: {
652 case chrome::NOTIFICATION_PROFILE_CREATED: { 644 // TODO(jamescook): Convert this to use ExtensionSystem::ready() instead
653 // Don't load background hosts now if the loading should be deferred. 645 // of a notification.
654 // Instead they will be loaded when a browser window for this profile 646 MaybeCreateStartupBackgroundHosts();
655 // (or an incognito profile from this profile) is ready.
656 if (DeferLoadingBackgroundHosts())
657 break;
658
659 CreateBackgroundHostsForProfileStartup();
660 break; 647 break;
661 } 648 }
662 649
663 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: { 650 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
664 BrowserContext* context = content::Source<BrowserContext>(source).ptr(); 651 BrowserContext* context = content::Source<BrowserContext>(source).ptr();
665 ExtensionSystem* system = ExtensionSystem::Get(context); 652 ExtensionSystem* system = ExtensionSystem::Get(context);
666 if (system->ready().is_signaled()) { 653 if (system->ready().is_signaled()) {
667 // The extension system is ready, so create the background host. 654 // The extension system is ready, so create the background host.
668 const Extension* extension = 655 const Extension* extension =
669 content::Details<const Extension>(details).ptr(); 656 content::Details<const Extension>(details).ptr();
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 return; 764 return;
778 if (attached) { 765 if (attached) {
779 // Keep the lazy background page alive while it's being inspected. 766 // Keep the lazy background page alive while it's being inspected.
780 CancelSuspend(extension); 767 CancelSuspend(extension);
781 IncrementLazyKeepaliveCount(extension); 768 IncrementLazyKeepaliveCount(extension);
782 } else { 769 } else {
783 DecrementLazyKeepaliveCount(extension); 770 DecrementLazyKeepaliveCount(extension);
784 } 771 }
785 } 772 }
786 773
787 void ProcessManager::CreateBackgroundHostsForProfileStartup() { 774 void ProcessManager::MaybeCreateStartupBackgroundHosts() {
788 if (startup_background_hosts_created_ || 775 if (startup_background_hosts_created_)
789 !ExtensionsBrowserClient::Get()->
790 IsBackgroundPageAllowed(GetBrowserContext())) {
791 return; 776 return;
792 }
793 777
794 const ExtensionSet& enabled_extensions = 778 // The embedder might disallow background pages entirely.
795 ExtensionRegistry::Get(GetBrowserContext())->enabled_extensions(); 779 ProcessManagerDelegate* delegate =
796 for (ExtensionSet::const_iterator extension = enabled_extensions.begin(); 780 ExtensionsBrowserClient::Get()->GetProcessManagerDelegate();
797 extension != enabled_extensions.end(); 781 if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext()))
798 ++extension) { 782 return;
799 CreateBackgroundHostForExtensionLoad(this, extension->get());
800 783
801 FOR_EACH_OBSERVER(ProcessManagerObserver, 784 // The embedder might want to defer background page loading. For example,
802 observer_list_, 785 // Chrome defers background page loading when it is launched to show the app
803 OnBackgroundHostStartup(*extension)); 786 // list, then triggers a load later when a browser window opens.
804 } 787 if (delegate &&
788 delegate->DeferCreatingStartupBackgroundHosts(GetBrowserContext()))
789 return;
790
791 CreateStartupBackgroundHosts();
805 startup_background_hosts_created_ = true; 792 startup_background_hosts_created_ = true;
806 793
807 // Background pages should only be loaded once. To prevent any further loads 794 // Background pages should only be loaded once. To prevent any further loads
808 // occurring, we remove the notification listeners. 795 // occurring, we remove the notification listeners.
809 BrowserContext* original_context = 796 BrowserContext* original_context =
810 ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext()); 797 ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext());
811 if (registrar_.IsRegistered( 798 if (registrar_.IsRegistered(
812 this, 799 this,
813 chrome::NOTIFICATION_PROFILE_CREATED,
814 content::Source<BrowserContext>(original_context))) {
815 registrar_.Remove(this,
816 chrome::NOTIFICATION_PROFILE_CREATED,
817 content::Source<BrowserContext>(original_context));
818 }
819 if (registrar_.IsRegistered(
820 this,
821 chrome::NOTIFICATION_EXTENSIONS_READY, 800 chrome::NOTIFICATION_EXTENSIONS_READY,
822 content::Source<BrowserContext>(original_context))) { 801 content::Source<BrowserContext>(original_context))) {
823 registrar_.Remove(this, 802 registrar_.Remove(this,
824 chrome::NOTIFICATION_EXTENSIONS_READY, 803 chrome::NOTIFICATION_EXTENSIONS_READY,
825 content::Source<BrowserContext>(original_context)); 804 content::Source<BrowserContext>(original_context));
826 } 805 }
827 } 806 }
828 807
808 void ProcessManager::CreateStartupBackgroundHosts() {
809 DCHECK(!startup_background_hosts_created_);
810 const ExtensionSet& enabled_extensions =
811 ExtensionRegistry::Get(GetBrowserContext())->enabled_extensions();
812 for (ExtensionSet::const_iterator extension = enabled_extensions.begin();
813 extension != enabled_extensions.end();
814 ++extension) {
815 CreateBackgroundHostForExtensionLoad(this, extension->get());
816
817 FOR_EACH_OBSERVER(ProcessManagerObserver,
818 observer_list_,
819 OnBackgroundHostStartup(*extension));
820 }
821 }
822
829 void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) { 823 void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) {
830 DCHECK_EQ(GetBrowserContext(), host->browser_context()); 824 DCHECK_EQ(GetBrowserContext(), host->browser_context());
831 background_hosts_.insert(host); 825 background_hosts_.insert(host);
832 826
833 if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { 827 if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) {
834 linked_ptr<base::ElapsedTimer> since_suspended( 828 linked_ptr<base::ElapsedTimer> since_suspended(
835 background_page_data_[host->extension()->id()]. 829 background_page_data_[host->extension()->id()].
836 since_suspended.release()); 830 since_suspended.release());
837 if (since_suspended.get()) { 831 if (since_suspended.get()) {
838 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime", 832 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime",
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 // Re-register all RenderViews for this extension. We do this to restore 877 // Re-register all RenderViews for this extension. We do this to restore
884 // the lazy_keepalive_count (if any) to properly reflect the number of open 878 // the lazy_keepalive_count (if any) to properly reflect the number of open
885 // views. 879 // views.
886 for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin(); 880 for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin();
887 it != all_extension_views_.end(); ++it) { 881 it != all_extension_views_.end(); ++it) {
888 if (GetExtensionID(it->first) == extension_id) 882 if (GetExtensionID(it->first) == extension_id)
889 IncrementLazyKeepaliveCountForView(it->first); 883 IncrementLazyKeepaliveCountForView(it->first);
890 } 884 }
891 } 885 }
892 886
893 bool ProcessManager::DeferLoadingBackgroundHosts() const {
894 // The extensions embedder may have special rules about background hosts.
895 return ExtensionsBrowserClient::Get()->DeferLoadingBackgroundHosts(
896 GetBrowserContext());
897 }
898
899 // 887 //
900 // IncognitoProcessManager 888 // IncognitoProcessManager
901 // 889 //
902 890
903 IncognitoProcessManager::IncognitoProcessManager( 891 IncognitoProcessManager::IncognitoProcessManager(
904 BrowserContext* incognito_context, 892 BrowserContext* incognito_context,
905 BrowserContext* original_context, 893 BrowserContext* original_context,
906 ProcessManager* original_manager) 894 ProcessManager* original_manager)
907 : ProcessManager(incognito_context, original_context), 895 : ProcessManager(incognito_context, original_context),
908 original_manager_(original_manager) { 896 original_manager_(original_manager) {
909 DCHECK(incognito_context->IsOffTheRecord()); 897 DCHECK(incognito_context->IsOffTheRecord());
910 898
911 // The original profile will have its own ProcessManager to 899 // The original profile will have its own ProcessManager to
912 // load the background pages of the spanning extensions. This process 900 // load the background pages of the spanning extensions. This process
913 // manager need only worry about the split mode extensions, which is handled 901 // manager need only worry about the split mode extensions, which is handled
914 // in the NOTIFICATION_BROWSER_WINDOW_READY notification handler. 902 // in the NOTIFICATION_BROWSER_WINDOW_READY notification handler.
915 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY, 903 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY,
916 content::Source<BrowserContext>(original_context)); 904 content::Source<BrowserContext>(original_context));
917 registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_CREATED,
918 content::Source<BrowserContext>(original_context));
919 } 905 }
920 906
921 bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension, 907 bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension,
922 const GURL& url) { 908 const GURL& url) {
923 if (IncognitoInfo::IsSplitMode(extension)) { 909 if (IncognitoInfo::IsSplitMode(extension)) {
924 if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled( 910 if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled(
925 extension->id(), GetBrowserContext())) 911 extension->id(), GetBrowserContext()))
926 return ProcessManager::CreateBackgroundHost(extension, url); 912 return ProcessManager::CreateBackgroundHost(extension, url);
927 } else { 913 } else {
928 // Do nothing. If an extension is spanning, then its original-profile 914 // Do nothing. If an extension is spanning, then its original-profile
929 // background page is shared with incognito, so we don't create another. 915 // background page is shared with incognito, so we don't create another.
930 } 916 }
931 return false; 917 return false;
932 } 918 }
933 919
934 SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) { 920 SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
935 ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext()); 921 ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext());
936 if (registry) { 922 if (registry) {
937 const Extension* extension = 923 const Extension* extension =
938 registry->enabled_extensions().GetExtensionOrAppByURL(url); 924 registry->enabled_extensions().GetExtensionOrAppByURL(url);
939 if (extension && !IncognitoInfo::IsSplitMode(extension)) { 925 if (extension && !IncognitoInfo::IsSplitMode(extension)) {
940 return original_manager_->GetSiteInstanceForURL(url); 926 return original_manager_->GetSiteInstanceForURL(url);
941 } 927 }
942 } 928 }
943 return ProcessManager::GetSiteInstanceForURL(url); 929 return ProcessManager::GetSiteInstanceForURL(url);
944 } 930 }
945 931
946 } // namespace extensions 932 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/process_manager.h ('k') | extensions/browser/process_manager_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698