summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_event_router.cc25
-rw-r--r--chrome/browser/extensions/extension_event_router.h2
-rw-r--r--chrome/browser/extensions/extension_function.cc2
-rw-r--r--chrome/browser/extensions/extension_host.cc27
-rw-r--r--chrome/browser/extensions/extension_host.h3
-rw-r--r--chrome/browser/extensions/extension_message_service.cc86
-rw-r--r--chrome/browser/extensions/extension_process_manager.cc19
-rw-r--r--chrome/browser/extensions/extension_process_manager.h4
-rw-r--r--chrome/browser/extensions/lazy_background_task_queue.cc60
-rw-r--r--chrome/browser/extensions/lazy_background_task_queue.h11
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.cc41
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.h3
-rw-r--r--chrome/common/extensions/extension_messages.h10
-rw-r--r--chrome/renderer/extensions/extension_custom_bindings.cc102
-rw-r--r--chrome/renderer/extensions/extension_dispatcher.cc36
-rw-r--r--chrome/renderer/extensions/extension_helper.cc87
-rw-r--r--chrome/renderer/extensions/extension_helper.h12
17 files changed, 306 insertions, 224 deletions
diff --git a/chrome/browser/extensions/extension_event_router.cc b/chrome/browser/extensions/extension_event_router.cc
index 908c06c..0b957df 100644
--- a/chrome/browser/extensions/extension_event_router.cc
+++ b/chrome/browser/extensions/extension_event_router.cc
@@ -405,20 +405,27 @@ void ExtensionEventRouter::MaybeLoadLazyBackgroundPage(
void ExtensionEventRouter::IncrementInFlightEvents(
Profile* profile, const Extension* extension) {
+ // Only increment in-flight events if the lazy background page is active,
+ // because that's the only time we'll get an ACK.
if (extension->has_lazy_background_page()) {
- profile->GetExtensionProcessManager()->IncrementLazyKeepaliveCount(
- extension);
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile)->process_manager();
+ ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
+ if (host)
+ pm->IncrementLazyKeepaliveCount(extension);
}
}
-void ExtensionEventRouter::OnExtensionEventAck(
+void ExtensionEventRouter::OnEventAck(
Profile* profile, const std::string& extension_id) {
- const Extension* extension = profile->GetExtensionService()->extensions()->
- GetByID(extension_id);
- if (extension && extension->has_lazy_background_page()) {
- profile->GetExtensionProcessManager()->DecrementLazyKeepaliveCount(
- extension);
- }
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile)->process_manager();
+ ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
+ // The event ACK is routed to the background host, so this should never be
+ // NULL.
+ CHECK(host);
+ CHECK(host->extension()->has_lazy_background_page());
+ pm->DecrementLazyKeepaliveCount(host->extension());
}
void ExtensionEventRouter::DispatchPendingEvent(
diff --git a/chrome/browser/extensions/extension_event_router.h b/chrome/browser/extensions/extension_event_router.h
index 2b52cc8..faf80e9 100644
--- a/chrome/browser/extensions/extension_event_router.h
+++ b/chrome/browser/extensions/extension_event_router.h
@@ -121,7 +121,7 @@ class ExtensionEventRouter : public content::NotificationObserver {
const GURL& event_url);
// Record the Event Ack from the renderer. (One less event in-flight.)
- void OnExtensionEventAck(Profile* profile, const std::string& extension_id);
+ void OnEventAck(Profile* profile, const std::string& extension_id);
private:
// The details of an event to be dispatched.
diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc
index b3b3105..b278df8 100644
--- a/chrome/browser/extensions/extension_function.cc
+++ b/chrome/browser/extensions/extension_function.cc
@@ -152,7 +152,7 @@ UIThreadExtensionFunction::UIThreadExtensionFunction()
}
UIThreadExtensionFunction::~UIThreadExtensionFunction() {
- if (dispatcher())
+ if (dispatcher() && render_view_host())
dispatcher()->OnExtensionFunctionCompleted(GetExtension());
}
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index ed4ee74..4a3900f 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -14,6 +14,7 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -470,6 +471,11 @@ bool ExtensionHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_EventAck, OnEventAck)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_IncrementLazyKeepaliveCount,
+ OnIncrementLazyKeepaliveCount)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_DecrementLazyKeepaliveCount,
+ OnDecrementLazyKeepaliveCount)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -479,6 +485,27 @@ void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) {
extension_function_dispatcher_.Dispatch(params, render_view_host());
}
+void ExtensionHost::OnEventAck() {
+ ExtensionEventRouter* router = ExtensionSystem::Get(profile_)->event_router();
+ if (router)
+ router->OnEventAck(profile_, extension_id());
+}
+
+void ExtensionHost::OnIncrementLazyKeepaliveCount() {
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile_)->process_manager();
+ if (pm)
+ pm->IncrementLazyKeepaliveCount(extension());
+}
+
+void ExtensionHost::OnDecrementLazyKeepaliveCount() {
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile_)->process_manager();
+ if (pm)
+ pm->DecrementLazyKeepaliveCount(extension());
+}
+
+
void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) {
render_view_host_ = render_view_host;
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 835f62f..be0208a 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -188,6 +188,9 @@ class ExtensionHost : public content::WebContentsDelegate,
// Message handlers.
void OnRequest(const ExtensionHostMsg_Request_Params& params);
+ void OnEventAck();
+ void OnIncrementLazyKeepaliveCount();
+ void OnDecrementLazyKeepaliveCount();
// Handles keyboard events that were not handled by HandleKeyboardEvent().
// Platform specific implementation may override this method to handle the
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index ccb555e..d041527 100644
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/lazy_background_task_queue.h"
#include "chrome/browser/extensions/process_map.h"
@@ -47,16 +48,25 @@ using content::WebContents;
struct ExtensionMessageService::MessagePort {
content::RenderProcessHost* process;
int routing_id;
- explicit MessagePort(content::RenderProcessHost* process = NULL,
- int routing_id = MSG_ROUTING_CONTROL)
- : process(process), routing_id(routing_id) {}
+ std::string extension_id;
+ void* background_host_ptr; // used in IncrementLazyKeepaliveCount
+
+ MessagePort()
+ : process(NULL),
+ routing_id(MSG_ROUTING_CONTROL),
+ background_host_ptr(NULL) {}
+ MessagePort(content::RenderProcessHost* process,
+ int routing_id,
+ const std::string& extension_id)
+ : process(process),
+ routing_id(routing_id),
+ extension_id(extension_id),
+ background_host_ptr(NULL) {}
};
struct ExtensionMessageService::MessageChannel {
ExtensionMessageService::MessagePort opener;
ExtensionMessageService::MessagePort receiver;
- std::string source_extension_id;
- std::string target_extension_id;
};
struct ExtensionMessageService::OpenChannelParams {
@@ -124,24 +134,30 @@ static content::RenderProcessHost* GetExtensionProcess(
return site_instance->GetProcess();
}
-static void IncrementLazyKeepaliveCount(content::RenderProcessHost* process,
- const std::string& extension_id) {
- Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext());
- const Extension* extension = profile->GetExtensionService()->extensions()->
- GetByID(extension_id);
- if (extension)
- profile->GetExtensionProcessManager()->IncrementLazyKeepaliveCount(
- extension);
+static void IncrementLazyKeepaliveCount(
+ ExtensionMessageService::MessagePort* port) {
+ Profile* profile =
+ Profile::FromBrowserContext(port->process->GetBrowserContext());
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile)->process_manager();
+ ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id);
+ if (host && host->extension()->has_lazy_background_page())
+ pm->IncrementLazyKeepaliveCount(host->extension());
+
+ // Keep track of the background host, so when we decrement, we only do so if
+ // the host hasn't reloaded.
+ port->background_host_ptr = host;
}
-static void DecrementLazyKeepaliveCount(content::RenderProcessHost* process,
- const std::string& extension_id) {
- Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext());
- const Extension* extension = profile->GetExtensionService()->extensions()->
- GetByID(extension_id);
- if (extension)
- profile->GetExtensionProcessManager()->DecrementLazyKeepaliveCount(
- extension);
+static void DecrementLazyKeepaliveCount(
+ ExtensionMessageService::MessagePort* port) {
+ Profile* profile =
+ Profile::FromBrowserContext(port->process->GetBrowserContext());
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile)->process_manager();
+ ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id);
+ if (host && host == port->background_host_ptr)
+ pm->DecrementLazyKeepaliveCount(host->extension());
}
} // namespace
@@ -195,7 +211,8 @@ void ExtensionMessageService::OpenChannelToExtension(
// which depends on whether the extension uses spanning or split mode.
MessagePort receiver(
GetExtensionProcess(profile, target_extension_id),
- MSG_ROUTING_CONTROL);
+ MSG_ROUTING_CONTROL,
+ target_extension_id);
WebContents* source_contents = tab_util::GetWebContentsByID(
source_process_id, source_routing_id);
@@ -237,12 +254,13 @@ void ExtensionMessageService::OpenChannelToTab(
receiver.process = contents->web_contents()->GetRenderProcessHost();
receiver.routing_id =
contents->web_contents()->GetRenderViewHost()->GetRoutingID();
+ receiver.extension_id = extension_id;
}
if (contents && contents->web_contents()->GetController().NeedsReload()) {
// The tab isn't loaded yet. Don't attempt to connect. Treat this as a
// disconnect.
- DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL),
+ DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL, extension_id),
GET_OPPOSITE_PORT_ID(receiver_port_id), true);
return;
}
@@ -269,7 +287,7 @@ bool ExtensionMessageService::OpenChannelImpl(const OpenChannelParams& params) {
if (!params.receiver.process) {
// Treat it as a disconnect.
- DispatchOnDisconnect(MessagePort(params.source, MSG_ROUTING_CONTROL),
+ DispatchOnDisconnect(MessagePort(params.source, MSG_ROUTING_CONTROL, ""),
GET_OPPOSITE_PORT_ID(params.receiver_port_id), true);
return false;
}
@@ -279,10 +297,9 @@ bool ExtensionMessageService::OpenChannelImpl(const OpenChannelParams& params) {
CHECK(params.receiver.process);
MessageChannel* channel(new MessageChannel);
- channel->opener = MessagePort(params.source, MSG_ROUTING_CONTROL);
+ channel->opener = MessagePort(params.source, MSG_ROUTING_CONTROL,
+ params.source_extension_id);
channel->receiver = params.receiver;
- channel->source_extension_id = params.source_extension_id;
- channel->target_extension_id = params.target_extension_id;
CHECK(params.receiver.process);
@@ -300,10 +317,8 @@ bool ExtensionMessageService::OpenChannelImpl(const OpenChannelParams& params) {
params.source_extension_id, params.target_extension_id);
// Keep both ends of the channel alive until the channel is closed.
- IncrementLazyKeepaliveCount(channel->opener.process,
- channel->source_extension_id);
- IncrementLazyKeepaliveCount(channel->receiver.process,
- channel->target_extension_id);
+ IncrementLazyKeepaliveCount(&channel->opener);
+ IncrementLazyKeepaliveCount(&channel->receiver);
return true;
}
@@ -338,10 +353,8 @@ void ExtensionMessageService::CloseChannelImpl(
}
// Balance the addrefs in OpenChannelImpl.
- DecrementLazyKeepaliveCount(channel->opener.process,
- channel->source_extension_id);
- DecrementLazyKeepaliveCount(channel->receiver.process,
- channel->target_extension_id);
+ DecrementLazyKeepaliveCount(&channel->opener);
+ DecrementLazyKeepaliveCount(&channel->receiver);
delete channel_iter->second;
channels_.erase(channel_iter);
@@ -452,6 +465,7 @@ void ExtensionMessageService::PendingOpenChannel(
return;
params.receiver = MessagePort(host->render_process_host(),
- MSG_ROUTING_CONTROL);
+ MSG_ROUTING_CONTROL,
+ params.target_extension_id);
OpenChannelImpl(params);
}
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index 30fcb4d..100059e 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -373,6 +373,12 @@ bool ExtensionProcessManager::HasExtensionHost(ExtensionHost* host) const {
return all_hosts_.find(host) != all_hosts_.end();
}
+bool ExtensionProcessManager::IsBackgroundHostClosing(
+ const std::string& extension_id) {
+ ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
+ return (host && background_page_data_[extension_id].is_closing);
+}
+
int ExtensionProcessManager::GetLazyKeepaliveCount(const Extension* extension) {
if (!extension->has_lazy_background_page())
return 0;
@@ -397,15 +403,10 @@ int ExtensionProcessManager::DecrementLazyKeepaliveCount(
if (!extension->has_lazy_background_page())
return 0;
- // Don't decrement the count if the background page has gone away. This can
- // happen e.g. if an event was dispatched while unloading the page, or if
- // the process is killed/closed while a message port remains open.
- // TODO(mpcomplete): This might be insufficient.. what if the page goes away
- // and comes back before we get here? Then we'll have an imbalanced
- // keepalive count.
- ExtensionHost* host = GetBackgroundHostForExtension(extension->id());
- if (!host)
- return 0;
+ // This should never be called if the background page isn't active.
+ // Otherwise, the count can get out of sync, because we reset it when the
+ // page unloads.
+ CHECK(GetBackgroundHostForExtension(extension->id()));
int& count = background_page_data_[extension->id()].lazy_keepalive_count;
DCHECK_GT(count, 0);
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
index c5a936a..eddf0cf 100644
--- a/chrome/browser/extensions/extension_process_manager.h
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -89,6 +89,10 @@ class ExtensionProcessManager : public content::NotificationObserver {
// Returns true if |host| is managed by this process manager.
bool HasExtensionHost(ExtensionHost* host) const;
+ // Returns true if the (lazy) background host for the given extension has
+ // already been sent the unload event and is shutting down.
+ bool IsBackgroundHostClosing(const std::string& extension_id);
+
// Getter and setter for the lazy background page's keepalive count. This is
// the count of how many outstanding "things" are keeping the page alive.
// When this reaches 0, we will begin the process of shutting down the page.
diff --git a/chrome/browser/extensions/lazy_background_task_queue.cc b/chrome/browser/extensions/lazy_background_task_queue.cc
index bb1b1a2..dbe0ff6 100644
--- a/chrome/browser/extensions/lazy_background_task_queue.cc
+++ b/chrome/browser/extensions/lazy_background_task_queue.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/lazy_background_task_queue.h"
#include "base/callback.h"
+#include "base/message_loop.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -43,10 +44,12 @@ bool LazyBackgroundTaskQueue::ShouldEnqueueTask(
Profile* profile, const Extension* extension) {
DCHECK(extension);
if (extension->has_lazy_background_page()) {
- ExtensionProcessManager* pm = profile->GetExtensionProcessManager();
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile)->process_manager();
ExtensionHost* background_host =
pm->GetBackgroundHostForExtension(extension->id());
- if (!background_host || !background_host->did_stop_loading())
+ if (!background_host || !background_host->did_stop_loading() ||
+ pm->IsBackgroundHostClosing(extension->id()))
return true;
}
@@ -64,16 +67,10 @@ void LazyBackgroundTaskQueue::AddPendingTask(
tasks_list = new PendingTasksList();
pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list);
- // If this is the first enqueued task, ensure the background page
- // is loaded.
- const Extension* extension =
- ExtensionSystem::Get(profile)->extension_service()->
- extensions()->GetByID(extension_id);
- DCHECK(extension->has_lazy_background_page());
- ExtensionProcessManager* pm =
- ExtensionSystem::Get(profile)->process_manager();
- pm->IncrementLazyKeepaliveCount(extension);
- pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
+ // If this is the first enqueued task, and we're not waiting for the
+ // background page to unload, ensure the background page is loaded.
+ if (pending_page_loads_.count(key) == 0)
+ StartLazyBackgroundPage(profile, extension_id);
} else {
tasks_list = it->second.get();
}
@@ -81,6 +78,26 @@ void LazyBackgroundTaskQueue::AddPendingTask(
tasks_list->push_back(task);
}
+void LazyBackgroundTaskQueue::StartLazyBackgroundPage(
+ Profile* profile, const std::string& extension_id) {
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile)->process_manager();
+ if (pm->IsBackgroundHostClosing(extension_id)) {
+ // When the background host finishes closing, we will reload it.
+ pending_page_loads_.insert(PendingTasksKey(profile, extension_id));
+ return;
+ }
+
+ const Extension* extension =
+ ExtensionSystem::Get(profile)->extension_service()->
+ extensions()->GetByID(extension_id);
+ DCHECK(extension->has_lazy_background_page());
+ pm->IncrementLazyKeepaliveCount(extension);
+ pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
+
+ pending_page_loads_.erase(PendingTasksKey(profile, extension_id));
+}
+
void LazyBackgroundTaskQueue::ProcessPendingTasks(
ExtensionHost* host,
Profile* profile,
@@ -130,15 +147,24 @@ void LazyBackgroundTaskQueue::Observe(
break;
}
case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
- // Notify consumers about the load failure when the background host dies.
- // This can happen if the extension crashes. This is not strictly
- // necessary, since we also unload the extension in that case (which
- // dispatches the tasks below), but is a good extra precaution.
Profile* profile = content::Source<Profile>(source).ptr();
ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
if (host->extension_host_type() ==
chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
- ProcessPendingTasks(NULL, profile, host->extension());
+ PendingTasksKey key(profile, host->extension()->id());
+ if (pending_page_loads_.count(key) > 0) {
+ // We were waiting for the background page to unload. We can start it
+ // up again and dispatch any queued events.
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &LazyBackgroundTaskQueue::StartLazyBackgroundPage,
+ AsWeakPtr(), profile, host->extension()->id()));
+ } else {
+ // This may be a load failure (e.g. a crash). In that case, notify
+ // consumers about the load failure. This is not strictly necessary,
+ // since we also unload the extension in that case (which dispatches
+ // the tasks below), but is a good extra precaution.
+ ProcessPendingTasks(NULL, profile, host->extension());
+ }
}
break;
}
diff --git a/chrome/browser/extensions/lazy_background_task_queue.h b/chrome/browser/extensions/lazy_background_task_queue.h
index 12b85ba..abe71b2 100644
--- a/chrome/browser/extensions/lazy_background_task_queue.h
+++ b/chrome/browser/extensions/lazy_background_task_queue.h
@@ -7,11 +7,13 @@
#pragma once
#include <map>
+#include <set>
#include <string>
#include "base/compiler_specific.h"
#include "base/callback_forward.h"
#include "base/memory/linked_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -27,7 +29,9 @@ namespace extensions {
//
// It is the consumer's responsibility to use this class when appropriate, i.e.
// only with extensions that have not-yet-loaded lazy background pages.
-class LazyBackgroundTaskQueue : public content::NotificationObserver {
+class LazyBackgroundTaskQueue
+ : public content::NotificationObserver,
+ public base::SupportsWeakPtr<LazyBackgroundTaskQueue> {
public:
typedef base::Callback<void(ExtensionHost*)> PendingTask;
@@ -56,6 +60,10 @@ class LazyBackgroundTaskQueue : public content::NotificationObserver {
typedef std::vector<PendingTask> PendingTasksList;
typedef std::map<PendingTasksKey,
linked_ptr<PendingTasksList> > PendingTasksMap;
+ typedef std::set<PendingTasksKey> PendingPageLoadList;
+
+ void StartLazyBackgroundPage(Profile* profile,
+ const std::string& extension_id);
// content::NotificationObserver interface.
virtual void Observe(int type,
@@ -72,6 +80,7 @@ class LazyBackgroundTaskQueue : public content::NotificationObserver {
Profile* profile_;
content::NotificationRegistrar registrar_;
PendingTasksMap pending_tasks_;
+ PendingPageLoadList pending_page_loads_;
};
} // namespace extensions
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index c1a0eb8..095057f 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -91,16 +91,11 @@ bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnExtensionAddLazyListener)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener,
OnExtensionRemoveLazyListener)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_ExtensionEventAck, OnExtensionEventAck)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_CloseChannel, OnExtensionCloseChannel)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestForIOThread,
OnExtensionRequestForIOThread)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_ShouldUnloadAck,
OnExtensionShouldUnloadAck)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_IncrementLazyKeepaliveCount,
- OnExtensionIncrementLazyKeepaliveCount)
- IPC_MESSAGE_HANDLER(ExtensionHostMsg_DecrementLazyKeepaliveCount,
- OnExtensionDecrementLazyKeepaliveCount)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_GenerateUniqueID,
OnExtensionGenerateUniqueID)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_UnloadAck, OnExtensionUnloadAck)
@@ -150,12 +145,9 @@ void ChromeRenderMessageFilter::OverrideThreadForMessage(
case ExtensionHostMsg_RemoveListener::ID:
case ExtensionHostMsg_AddLazyListener::ID:
case ExtensionHostMsg_RemoveLazyListener::ID:
- case ExtensionHostMsg_ExtensionEventAck::ID:
case ExtensionHostMsg_CloseChannel::ID:
case ExtensionHostMsg_ShouldUnloadAck::ID:
case ExtensionHostMsg_UnloadAck::ID:
- case ExtensionHostMsg_IncrementLazyKeepaliveCount::ID:
- case ExtensionHostMsg_DecrementLazyKeepaliveCount::ID:
case ChromeViewHostMsg_UpdatedCacheStats::ID:
*thread = BrowserThread::UI;
break;
@@ -388,13 +380,6 @@ void ChromeRenderMessageFilter::OnExtensionRemoveLazyListener(
event_name, extension_id);
}
-void ChromeRenderMessageFilter::OnExtensionEventAck(
- const std::string& extension_id) {
- if (profile_->GetExtensionEventRouter())
- profile_->GetExtensionEventRouter()->OnExtensionEventAck(
- profile_, extension_id);
-}
-
void ChromeRenderMessageFilter::OnExtensionCloseChannel(int port_id,
bool connection_error) {
if (!content::RenderProcessHost::FromID(render_process_id_))
@@ -429,32 +414,6 @@ void ChromeRenderMessageFilter::OnExtensionUnloadAck(
profile_->GetExtensionProcessManager()->OnUnloadAck(extension_id);
}
-void ChromeRenderMessageFilter::OnExtensionIncrementLazyKeepaliveCount(
- const std::string& extension_id) {
- ExtensionService* service =
- ExtensionSystem::Get(profile_)->extension_service();
- ExtensionProcessManager* process_manager =
- ExtensionSystem::Get(profile_)->process_manager();
- if (process_manager && service) {
- const Extension* extension = service->extensions()->GetByID(extension_id);
- if (extension)
- process_manager->IncrementLazyKeepaliveCount(extension);
- }
-}
-
-void ChromeRenderMessageFilter::OnExtensionDecrementLazyKeepaliveCount(
- const std::string& extension_id) {
- ExtensionService* service =
- ExtensionSystem::Get(profile_)->extension_service();
- ExtensionProcessManager* process_manager =
- ExtensionSystem::Get(profile_)->process_manager();
- if (process_manager && service) {
- const Extension* extension = service->extensions()->GetByID(extension_id);
- if (extension)
- process_manager->DecrementLazyKeepaliveCount(extension);
- }
-}
-
void ChromeRenderMessageFilter::OnExtensionGenerateUniqueID(int* unique_id) {
static int next_unique_id = 1;
*unique_id = next_unique_id++;
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h
index 5068f94..0dfb1df 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.h
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.h
@@ -117,7 +117,6 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter {
const std::string& event_name);
void OnExtensionRemoveLazyListener(const std::string& extension_id,
const std::string& event_name);
- void OnExtensionEventAck(const std::string& extension_id);
void OnExtensionCloseChannel(int port_id, bool connection_error);
void OnExtensionRequestForIOThread(
int routing_id,
@@ -125,8 +124,6 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter {
void OnExtensionShouldUnloadAck(const std::string& extension_id,
int sequence_id);
void OnExtensionUnloadAck(const std::string& extension_id);
- void OnExtensionIncrementLazyKeepaliveCount(const std::string& extension_id);
- void OnExtensionDecrementLazyKeepaliveCount(const std::string& extension_id);
void OnExtensionGenerateUniqueID(int* unique_id);
#if defined(USE_TCMALLOC)
void OnRendererTcmalloc(const std::string& output);
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 6cc83ae..ff35b1e 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -331,9 +331,7 @@ IPC_MESSAGE_CONTROL2(ExtensionHostMsg_RemoveLazyListener,
std::string /* name */)
// Notify the browser that an event has finished being dispatched.
-IPC_MESSAGE_CONTROL1(ExtensionHostMsg_ExtensionEventAck,
- std::string /* extension_id */)
-
+IPC_MESSAGE_ROUTED0(ExtensionHostMsg_EventAck)
// Open a channel to all listening contexts owned by the extension with
// the given ID. This always returns a valid port ID which can be used for
@@ -417,13 +415,11 @@ IPC_MESSAGE_CONTROL1(ExtensionHostMsg_UnloadAck,
// Informs the browser to increment the keepalive count for the lazy background
// page, keeping it alive.
-IPC_MESSAGE_CONTROL1(ExtensionHostMsg_IncrementLazyKeepaliveCount,
- std::string /* extension_id */)
+IPC_MESSAGE_ROUTED0(ExtensionHostMsg_IncrementLazyKeepaliveCount)
// Informs the browser there is one less thing keeping the lazy background page
// alive.
-IPC_MESSAGE_CONTROL1(ExtensionHostMsg_DecrementLazyKeepaliveCount,
- std::string /* extension_id */)
+IPC_MESSAGE_ROUTED0(ExtensionHostMsg_DecrementLazyKeepaliveCount)
// Fetches a globally unique ID (for the lifetime of the browser) from the
// browser process.
diff --git a/chrome/renderer/extensions/extension_custom_bindings.cc b/chrome/renderer/extensions/extension_custom_bindings.cc
index 7b177e1..047588c 100644
--- a/chrome/renderer/extensions/extension_custom_bindings.cc
+++ b/chrome/renderer/extensions/extension_custom_bindings.cc
@@ -14,97 +14,16 @@
#include "chrome/renderer/extensions/extension_dispatcher.h"
#include "chrome/renderer/extensions/extension_helper.h"
#include "content/public/renderer/render_view.h"
-#include "content/public/renderer/render_view_visitor.h"
#include "grit/renderer_resources.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
-#include "v8/include/v8.h"
#include "webkit/glue/webkit_glue.h"
+#include "v8/include/v8.h"
namespace extensions {
namespace {
-// A RenderViewVisitor class that iterates through the set of available
-// views, looking for a view of the given type, in the given browser window
-// and within the given extension.
-// Used to accumulate the list of views associated with an extension.
-class ExtensionViewAccumulator : public content::RenderViewVisitor {
- public:
- ExtensionViewAccumulator(const std::string& extension_id,
- int browser_window_id,
- content::ViewType view_type)
- : extension_id_(extension_id),
- browser_window_id_(browser_window_id),
- view_type_(view_type),
- views_(v8::Array::New()),
- index_(0) {
- }
-
- v8::Local<v8::Array> views() { return views_; }
-
- virtual bool Visit(content::RenderView* render_view) {
- ExtensionHelper* helper = ExtensionHelper::Get(render_view);
- if (!ViewTypeMatches(helper->view_type(), view_type_))
- return true;
-
- GURL url = render_view->GetWebView()->mainFrame()->document().url();
- if (!url.SchemeIs(chrome::kExtensionScheme))
- return true;
- const std::string& extension_id = url.host();
- if (extension_id != extension_id_)
- return true;
-
- if (browser_window_id_ != extension_misc::kUnknownWindowId &&
- helper->browser_window_id() != browser_window_id_) {
- return true;
- }
-
- v8::Local<v8::Context> context =
- render_view->GetWebView()->mainFrame()->mainWorldScriptContext();
- if (!context.IsEmpty()) {
- v8::Local<v8::Value> window = context->Global();
- DCHECK(!window.IsEmpty());
-
- if (!OnMatchedView(window))
- return false;
- }
- return true;
- }
-
- private:
- // Called on each view found matching the search criteria. Returns false
- // to terminate the iteration.
- bool OnMatchedView(v8::Local<v8::Value> view_window) {
- views_->Set(v8::Integer::New(index_), view_window);
- index_++;
-
- if (view_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE)
- return false; // There can be only one...
-
- return true;
- }
-
- // Returns true is |type| "isa" |match|.
- static bool ViewTypeMatches(content::ViewType type, content::ViewType match) {
- if (type == match)
- return true;
-
- // INVALID means match all.
- if (match == content::VIEW_TYPE_INVALID)
- return true;
-
- return false;
- }
-
- std::string extension_id_;
- int browser_window_id_;
- content::ViewType view_type_;
- v8::Local<v8::Array> views_;
- int index_;
-};
-
} // namespace
ExtensionCustomBindings::ExtensionCustomBindings(
@@ -159,10 +78,21 @@ v8::Handle<v8::Value> ExtensionCustomBindings::GetExtensionViews(
if (!extension)
return v8::Undefined();
- ExtensionViewAccumulator accumulator(extension->id(), browser_window_id,
- view_type);
- content::RenderView::ForEach(&accumulator);
- return accumulator.views();
+ std::vector<content::RenderView*> views = ExtensionHelper::GetExtensionViews(
+ extension->id(), browser_window_id, view_type);
+ v8::Local<v8::Array> v8_views = v8::Array::New();
+ int v8_index = 0;
+ for (size_t i = 0; i < views.size(); ++i) {
+ v8::Local<v8::Context> context =
+ views[i]->GetWebView()->mainFrame()->mainWorldScriptContext();
+ if (!context.IsEmpty()) {
+ v8::Local<v8::Value> window = context->Global();
+ DCHECK(!window.IsEmpty());
+ v8_views->Set(v8::Integer::New(v8_index++), window);
+ }
+ }
+
+ return v8_views;
}
// static
diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc
index fcfa1e7..9b2744c 100644
--- a/chrome/renderer/extensions/extension_dispatcher.cc
+++ b/chrome/renderer/extensions/extension_dispatcher.cc
@@ -45,6 +45,7 @@
#include "chrome/renderer/native_handler.h"
#include "chrome/renderer/resource_bundle_source_map.h"
#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
#include "grit/renderer_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
@@ -141,10 +142,12 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension {
v8::Handle<v8::Value> IncrementKeepaliveCount(const v8::Arguments& args) {
ChromeV8Context* context =
extension_dispatcher()->v8_context_set().GetCurrent();
- if (IsCurrentContextLazyBackgroundPage(context->extension())) {
- content::RenderThread::Get()->Send(
- new ExtensionHostMsg_IncrementLazyKeepaliveCount(
- context->extension()->id()));
+ if (!context)
+ return v8::Undefined();
+ content::RenderView* render_view = context->GetRenderView();
+ if (IsContextLazyBackgroundPage(render_view, context->extension())) {
+ render_view->Send(new ExtensionHostMsg_IncrementLazyKeepaliveCount(
+ render_view->GetRoutingID()));
}
return v8::Undefined();
}
@@ -152,17 +155,19 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension {
v8::Handle<v8::Value> DecrementKeepaliveCount(const v8::Arguments& args) {
ChromeV8Context* context =
extension_dispatcher()->v8_context_set().GetCurrent();
- if (IsCurrentContextLazyBackgroundPage(context->extension())) {
- content::RenderThread::Get()->Send(
- new ExtensionHostMsg_DecrementLazyKeepaliveCount(
- context->extension()->id()));
+ if (!context)
+ return v8::Undefined();
+ content::RenderView* render_view = context->GetRenderView();
+ if (IsContextLazyBackgroundPage(render_view, context->extension())) {
+ render_view->Send(new ExtensionHostMsg_DecrementLazyKeepaliveCount(
+ render_view->GetRoutingID()));
}
return v8::Undefined();
}
private:
- bool IsCurrentContextLazyBackgroundPage(const Extension* extension) {
- content::RenderView* render_view = GetCurrentRenderView();
+ bool IsContextLazyBackgroundPage(content::RenderView* render_view,
+ const Extension* extension) {
if (!render_view)
return false;
@@ -305,12 +310,17 @@ void ExtensionDispatcher::OnMessageInvoke(const std::string& extension_id,
kInitialExtensionIdleHandlerDelayMs);
}
+ // Tell the browser process when an event has been dispatched with a lazy
+ // background page active.
const Extension* extension = extensions_.GetByID(extension_id);
- // Tell the browser process that the event is dispatched and we're idle.
if (extension && extension->has_lazy_background_page() &&
function_name == kEventDispatchFunction) {
- RenderThread::Get()->Send(
- new ExtensionHostMsg_ExtensionEventAck(extension_id));
+ content::RenderView* background_view =
+ ExtensionHelper::GetBackgroundPage(extension_id);
+ if (background_view) {
+ background_view->Send(new ExtensionHostMsg_EventAck(
+ background_view->GetRoutingID()));
+ }
}
}
diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc
index 73027de..41fd732 100644
--- a/chrome/renderer/extensions/extension_helper.cc
+++ b/chrome/renderer/extensions/extension_helper.cc
@@ -22,7 +22,9 @@
#include "chrome/renderer/extensions/user_script_scheduler.h"
#include "chrome/renderer/extensions/user_script_slave.h"
#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/render_view_visitor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedUserGesture.h"
@@ -48,6 +50,91 @@ namespace {
typedef std::map<WebFrame*, UserScriptScheduler*> SchedulerMap;
static base::LazyInstance<SchedulerMap> g_schedulers =
LAZY_INSTANCE_INITIALIZER;
+
+// A RenderViewVisitor class that iterates through the set of available
+// views, looking for a view of the given type, in the given browser window
+// and within the given extension.
+// Used to accumulate the list of views associated with an extension.
+class ExtensionViewAccumulator : public content::RenderViewVisitor {
+ public:
+ ExtensionViewAccumulator(const std::string& extension_id,
+ int browser_window_id,
+ content::ViewType view_type)
+ : extension_id_(extension_id),
+ browser_window_id_(browser_window_id),
+ view_type_(view_type) {
+ }
+
+ std::vector<content::RenderView*> views() { return views_; }
+
+ // Returns false to terminate the iteration.
+ virtual bool Visit(content::RenderView* render_view) {
+ ExtensionHelper* helper = ExtensionHelper::Get(render_view);
+ if (!ViewTypeMatches(helper->view_type(), view_type_))
+ return true;
+
+ GURL url = render_view->GetWebView()->mainFrame()->document().url();
+ if (!url.SchemeIs(chrome::kExtensionScheme))
+ return true;
+ const std::string& extension_id = url.host();
+ if (extension_id != extension_id_)
+ return true;
+
+ if (browser_window_id_ != extension_misc::kUnknownWindowId &&
+ helper->browser_window_id() != browser_window_id_) {
+ return true;
+ }
+
+ views_.push_back(render_view);
+
+ if (view_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE)
+ return false; // There can be only one...
+ return true;
+ }
+
+ private:
+ // Returns true if |type| "isa" |match|.
+ static bool ViewTypeMatches(content::ViewType type, content::ViewType match) {
+ if (type == match)
+ return true;
+
+ // INVALID means match all.
+ if (match == content::VIEW_TYPE_INVALID)
+ return true;
+
+ return false;
+ }
+
+ std::string extension_id_;
+ int browser_window_id_;
+ content::ViewType view_type_;
+ std::vector<content::RenderView*> views_;
+};
+
+}
+
+// static
+std::vector<content::RenderView*> ExtensionHelper::GetExtensionViews(
+ const std::string& extension_id,
+ int browser_window_id,
+ content::ViewType view_type) {
+ ExtensionViewAccumulator accumulator(
+ extension_id, browser_window_id, view_type);
+ content::RenderView::ForEach(&accumulator);
+ return accumulator.views();
+}
+
+// static
+content::RenderView* ExtensionHelper::GetBackgroundPage(
+ const std::string& extension_id) {
+ ExtensionViewAccumulator accumulator(
+ extension_id, extension_misc::kUnknownWindowId,
+ chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
+ content::RenderView::ForEach(&accumulator);
+ CHECK_LE(accumulator.views().size(), 1u);
+ if (accumulator.views().size() == 0)
+ return NULL;
+ return accumulator.views()[0];
}
ExtensionHelper::ExtensionHelper(content::RenderView* render_view,
diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h
index 0a0b949..a1ed3ed 100644
--- a/chrome/renderer/extensions/extension_helper.h
+++ b/chrome/renderer/extensions/extension_helper.h
@@ -36,6 +36,18 @@ class ExtensionHelper
: public content::RenderViewObserver,
public content::RenderViewObserverTracker<ExtensionHelper> {
public:
+ // Returns a list of extension RenderViews that match the given filter
+ // criteria. If |browser_window_id| is not extension_misc::kUnknownWindowId,
+ // the list is restricted to views in that browser window.
+ static std::vector<content::RenderView*> GetExtensionViews(
+ const std::string& extension_id,
+ int browser_window_id,
+ content::ViewType view_type);
+
+ // Returns the given extension's background page, or NULL if none.
+ static content::RenderView* GetBackgroundPage(
+ const std::string& extension_id);
+
ExtensionHelper(content::RenderView* render_view,
ExtensionDispatcher* extension_dispatcher);
virtual ~ExtensionHelper();