diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-20 01:06:00 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-20 01:06:00 +0000 |
commit | 844550002b16a17c6b5d4e9bd406117e9ec6d9b2 (patch) | |
tree | 800abcd02551cd59c1d5ef4c53eb9487ff977c88 | |
parent | ebc717e8bbba0699fc3527225f622c3e31cbccf1 (diff) | |
download | chromium_src-844550002b16a17c6b5d4e9bd406117e9ec6d9b2.zip chromium_src-844550002b16a17c6b5d4e9bd406117e9ec6d9b2.tar.gz chromium_src-844550002b16a17c6b5d4e9bd406117e9ec6d9b2.tar.bz2 |
Undo my revert at r32524 due to a startup test regression.
ExtensionHosts once again spawn extension processes asynchronously. However,
if the process is already started, we now initialize the RenderView
synchronously. This is so bug 28049 stays fixed.
BUG=28049
Review URL: http://codereview.chromium.org/402101
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32578 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/cocoa/extension_view_mac.mm | 2 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.cc | 78 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.h | 15 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_process_manager.cc | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/extension_view_gtk.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_view.cc | 2 |
6 files changed, 92 insertions, 9 deletions
diff --git a/chrome/browser/cocoa/extension_view_mac.mm b/chrome/browser/cocoa/extension_view_mac.mm index c3ef722c..171cc30 100644 --- a/chrome/browser/cocoa/extension_view_mac.mm +++ b/chrome/browser/cocoa/extension_view_mac.mm @@ -75,5 +75,5 @@ void ExtensionViewMac::CreateWidgetHostView() { // disappear. [render_widget_host_view_->native_view() retain]; - extension_host_->CreateRenderView(render_widget_host_view_); + extension_host_->CreateRenderViewSoon(render_widget_host_view_); } diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 9fce7cd..c037e90 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -4,9 +4,13 @@ #include "chrome/browser/extensions/extension_host.h" +#include <list> + #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/keyboard_codes.h" +#include "base/message_loop.h" +#include "base/singleton.h" #include "base/string_util.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" @@ -49,6 +53,66 @@ bool ExtensionHost::enable_dom_automation_ = false; static const char* kToolstripTextColorSubstitution = "$TEXT_COLOR$"; +// Helper class that rate-limits the creation of renderer processes for +// ExtensionHosts, to avoid blocking the UI. +class ExtensionHost::ProcessCreationQueue { + public: + static ProcessCreationQueue* get() { + return Singleton<ProcessCreationQueue>::get(); + } + + // Add a host to the queue for RenderView creation. + void CreateSoon(ExtensionHost* host) { + queue_.push_back(host); + PostTask(); + } + + // Remove a host from the queue (in case it's being deleted). + void Remove(ExtensionHost* host) { + Queue::iterator it = std::find(queue_.begin(), queue_.end(), host); + if (it != queue_.end()) + queue_.erase(it); + } + + private: + friend class Singleton<ProcessCreationQueue>; + friend struct DefaultSingletonTraits<ProcessCreationQueue>; + ProcessCreationQueue() + : pending_create_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { } + + // Queue up a delayed task to process the next ExtensionHost in the queue. + void PostTask() { + if (!pending_create_) { + MessageLoop::current()->PostTask(FROM_HERE, + method_factory_.NewRunnableMethod( + &ProcessCreationQueue::ProcessOneHost)); + pending_create_ = true; + } + } + + // Create the RenderView for the next host in the queue. + void ProcessOneHost() { + pending_create_ = false; + if (queue_.empty()) + return; // can happen on shutdown + + queue_.front()->CreateRenderViewNow(); + queue_.pop_front(); + + if (!queue_.empty()) + PostTask(); + } + + typedef std::list<ExtensionHost*> Queue; + Queue queue_; + bool pending_create_; + ScopedRunnableMethodFactory<ProcessCreationQueue> method_factory_; +}; + +//////////////// +// ExtensionHost + ExtensionHost::ExtensionHost(Extension* extension, SiteInstance* site_instance, const GURL& url, ViewType::Type host_type) : extension_(extension), @@ -73,6 +137,7 @@ ExtensionHost::~ExtensionHost() { NotificationType::EXTENSION_HOST_DESTROYED, Source<Profile>(profile_), Details<ExtensionHost>(this)); + ProcessCreationQueue::get()->Remove(this); render_view_host_->Shutdown(); // deletes render_view_host } @@ -106,9 +171,20 @@ bool ExtensionHost::IsRenderViewLive() const { return render_view_host_->IsRenderViewLive(); } -void ExtensionHost::CreateRenderView(RenderWidgetHostView* host_view) { +void ExtensionHost::CreateRenderViewSoon(RenderWidgetHostView* host_view) { LOG(INFO) << "Creating RenderView for " + extension_->name(); render_view_host_->set_view(host_view); + if (render_view_host_->process()->HasConnection()) { + // If the process is already started, go ahead and initialize the RenderView + // synchronously. The process creation is the real meaty part that we want + // to defer. + CreateRenderViewNow(); + } else { + ProcessCreationQueue::get()->CreateSoon(this); + } +} + +void ExtensionHost::CreateRenderViewNow() { render_view_host_->CreateRenderView(profile_->GetRequestContext()); NavigateToURL(url_); DCHECK(IsRenderViewLive()); diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index 552bc8c..9407b85 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -44,6 +44,8 @@ class ExtensionHost : public ExtensionPopupHost::PopupDelegate, public NotificationObserver, public JavaScriptMessageBoxClient { public: + class ProcessCreationQueue; + // Enable DOM automation in created render view hosts. static void EnableDOMAutomation() { enable_dom_automation_ = true; } @@ -82,10 +84,10 @@ class ExtensionHost : public ExtensionPopupHost::PopupDelegate, // Returns true if the render view is initialized and didn't crash. bool IsRenderViewLive() const; - // Initializes our RenderViewHost by creating its RenderView and navigating - // to this host's url. Uses host_view for the RenderViewHost's view (can be - // NULL). - void CreateRenderView(RenderWidgetHostView* host_view); + // Prepares to initializes our RenderViewHost by creating its RenderView and + // navigating to this host's url. Uses host_view for the RenderViewHost's view + // (can be NULL). This happens delayed to avoid locking the UI. + void CreateRenderViewSoon(RenderWidgetHostView* host_view); // Sets |url_| and navigates |render_view_host_|. void NavigateToURL(const GURL& url); @@ -156,10 +158,15 @@ class ExtensionHost : public ExtensionPopupHost::PopupDelegate, virtual TabContents* AsTabContents() { return NULL; } private: + friend class ProcessCreationQueue; + // Whether to allow DOM automation for created RenderViewHosts. This is used // for testing. static bool enable_dom_automation_; + // Actually create the RenderView for this host. See CreateRenderViewSoon. + void CreateRenderViewNow(); + // ExtensionFunctionDispatcher::Delegate // If this ExtensionHost has a view, this returns the Browser that view is a // part of. If this is a global background page, we use the active Browser diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index 25a1fc2..02587a4 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -106,7 +106,7 @@ ExtensionHost* ExtensionProcessManager::CreateBackgroundHost( ExtensionHost* host = new ExtensionHost(extension, GetSiteInstanceForURL(url), url, ViewType::EXTENSION_BACKGROUND_PAGE); - host->CreateRenderView(NULL); // create a RenderViewHost with no view + host->CreateRenderViewSoon(NULL); // create a RenderViewHost with no view OnExtensionHostCreated(host, true); return host; } diff --git a/chrome/browser/gtk/extension_view_gtk.cc b/chrome/browser/gtk/extension_view_gtk.cc index 3bbac61..691ce54 100644 --- a/chrome/browser/gtk/extension_view_gtk.cc +++ b/chrome/browser/gtk/extension_view_gtk.cc @@ -49,7 +49,7 @@ void ExtensionViewGtk::CreateWidgetHostView() { render_widget_host_view_ = new RenderWidgetHostViewGtk(render_view_host()); render_widget_host_view_->InitAsChild(); - extension_host_->CreateRenderView(render_widget_host_view_); + extension_host_->CreateRenderViewSoon(render_widget_host_view_); } void ExtensionViewGtk::RenderViewCreated() { diff --git a/chrome/browser/views/extensions/extension_view.cc b/chrome/browser/views/extensions/extension_view.cc index b8bb0a6..7945307 100644 --- a/chrome/browser/views/extensions/extension_view.cc +++ b/chrome/browser/views/extensions/extension_view.cc @@ -108,7 +108,7 @@ void ExtensionView::CreateWidgetHostView() { NOTIMPLEMENTED(); #endif - host_->CreateRenderView(view); + host_->CreateRenderViewSoon(view); SetVisible(false); } |