| 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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |