| Index: chrome/browser/extensions/extension_host.cc
|
| diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
|
| index c83bb4694f8fdf773d8e53e4b85ae9345dde6023..3d529e75977ff50582bba96573b8968519252647 100644
|
| --- a/chrome/browser/extensions/extension_host.cc
|
| +++ b/chrome/browser/extensions/extension_host.cc
|
| @@ -4,7 +4,11 @@
|
|
|
| #include "chrome/browser/extensions/extension_host.h"
|
|
|
| +#include <list>
|
| +
|
| #include "app/resource_bundle.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"
|
| @@ -39,6 +43,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),
|
| @@ -59,6 +123,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
|
| }
|
|
|
| @@ -92,8 +157,12 @@ bool ExtensionHost::IsRenderViewLive() const {
|
| return render_view_host_->IsRenderViewLive();
|
| }
|
|
|
| -void ExtensionHost::CreateRenderView(RenderWidgetHostView* host_view) {
|
| +void ExtensionHost::CreateRenderViewSoon(RenderWidgetHostView* host_view) {
|
| render_view_host_->set_view(host_view);
|
| + ProcessCreationQueue::get()->CreateSoon(this);
|
| +}
|
| +
|
| +void ExtensionHost::CreateRenderViewNow() {
|
| render_view_host_->CreateRenderView();
|
| NavigateToURL(url_);
|
| DCHECK(IsRenderViewLive());
|
|
|