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