summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/extension_port_container.cc2
-rw-r--r--chrome/browser/extensions/extension_message_service.cc33
-rw-r--r--chrome/browser/extensions/extension_message_service.h37
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc17
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h7
-rw-r--r--chrome/common/render_messages_internal.h5
-rw-r--r--chrome/renderer/extensions/event_bindings.h4
-rw-r--r--chrome/renderer/extensions/renderer_extension_bindings.cc13
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js3
9 files changed, 79 insertions, 42 deletions
diff --git a/chrome/browser/automation/extension_port_container.cc b/chrome/browser/automation/extension_port_container.cc
index 15c2c8e..581da75 100644
--- a/chrome/browser/automation/extension_port_container.cc
+++ b/chrome/browser/automation/extension_port_container.cc
@@ -34,7 +34,7 @@ ExtensionPortContainer::~ExtensionPortContainer() {
DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
if (port_id_ != -1)
- service_->CloseAutomationChannel(port_id_);
+ service_->CloseChannel(port_id_);
}
bool ExtensionPortContainer::PostResponseToExternalPort(
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index 7a65078..0ee4579 100644
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -290,13 +290,28 @@ int ExtensionMessageService::OpenAutomationChannelToExtension(
return port2_id;
}
-void ExtensionMessageService::CloseAutomationChannel(int port_id) {
+void ExtensionMessageService::CloseChannel(int port_id) {
DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
- // TODO(siggi): Cleanup from the tab seems to beat this to the punch.
- // DCHECK(channels_[GET_CHANNEL_ID(port_id)].port1 != NULL);
- // TODO(siggi): should we notify the other side of the port?
- channels_.erase(GET_CHANNEL_ID(port_id));
+ // Note: The channel might be gone already, if the other side closed first.
+ MessageChannelMap::iterator it = channels_.find(GET_CHANNEL_ID(port_id));
+ if (it != channels_.end())
+ CloseChannelImpl(it, port_id);
+}
+
+void ExtensionMessageService::CloseChannelImpl(
+ MessageChannelMap::iterator channel_iter, int port_id) {
+ DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
+
+ // Notify the other side.
+ if (port_id == GET_CHANNEL_PORT1(channel_iter->first)) {
+ DispatchOnDisconnect(channel_iter->second.port2, port_id);
+ } else {
+ DCHECK_EQ(port_id, GET_CHANNEL_PORT2(channel_iter->first));
+ DispatchOnDisconnect(channel_iter->second.port1, port_id);
+ }
+
+ channels_.erase(channel_iter);
}
void ExtensionMessageService::PostMessageFromRenderer(
@@ -365,13 +380,9 @@ void ExtensionMessageService::Observe(NotificationType type,
it != channels_.end(); ) {
MessageChannelMap::iterator current = it++;
if (current->second.port1 == renderer) {
- DispatchOnDisconnect(current->second.port2,
- GET_CHANNEL_PORT1(current->first));
- channels_.erase(current);
+ CloseChannelImpl(current, GET_CHANNEL_PORT1(current->first));
} else if (current->second.port2 == renderer) {
- DispatchOnDisconnect(current->second.port1,
- GET_CHANNEL_PORT2(current->first));
- channels_.erase(current);
+ CloseChannelImpl(current, GET_CHANNEL_PORT2(current->first));
}
}
}
diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h
index dde7280..f128103 100644
--- a/chrome/browser/extensions/extension_message_service.h
+++ b/chrome/browser/extensions/extension_message_service.h
@@ -54,22 +54,17 @@ class ExtensionMessageService : public NotificationObserver {
void AddEventListener(std::string event_name, int render_process_id);
void RemoveEventListener(std::string event_name, int render_process_id);
- // Closes an extension channel for test automation.
- void CloseAutomationChannel(int port_id);
+ // Closes the message channel associated with the given port, and notifies
+ // the other side.
+ void CloseChannel(int port_id);
// Sends a message from a renderer to the given port.
- // TODO(mpcomplete): include the source tab.
void PostMessageFromRenderer(int port_id, const std::string& message);
// Send an event to every registered extension renderer.
void DispatchEventToRenderers(
const std::string& event_name, const std::string& event_args);
- // NotificationObserver interface.
- void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
// Given an extension's ID, opens a channel between the given automation
// "port" and that extension. Returns a channel ID to be used for posting
// messages between the processes, or -1 if the extension doesn't exist.
@@ -78,6 +73,11 @@ class ExtensionMessageService : public NotificationObserver {
const std::string& extension_id,
IPC::Message::Sender* source);
+ // NotificationObserver interface.
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
// --- IO thread only:
// Given an extension's ID, opens a channel between the given renderer "port"
@@ -89,6 +89,16 @@ class ExtensionMessageService : public NotificationObserver {
ResourceMessageFilter* source);
private:
+ // The connection between two ports. It is possible that both ports
+ // refer to the same renderer.
+ struct MessageChannel {
+ IPC::Message::Sender* port1;
+ IPC::Message::Sender* port2;
+ };
+
+ // A map of channel ID to its channel object.
+ typedef std::map<int, MessageChannel> MessageChannelMap;
+
// Allocates a pair of port ids.
// NOTE: this can be called from any thread.
void AllocatePortIdPair(int* port1, int* port2);
@@ -97,6 +107,8 @@ class ExtensionMessageService : public NotificationObserver {
// NOTE: this can be called from any thread.
int GetProcessIdForExtension(const std::string& extension_id);
+ void CloseChannelImpl(MessageChannelMap::iterator channel_iter, int port_id);
+
int OpenChannelToExtensionImpl(const std::string& extension_id,
IPC::Message::Sender* source);
@@ -136,15 +148,6 @@ class ExtensionMessageService : public NotificationObserver {
int source_routing_id, int source_port_id, IPC::Message::Sender* source,
int dest_port_id, int dest_process_id, int source_process_id);
- // The connection between two ports. It is possible that both ports
- // refer to the same renderer.
- struct MessageChannel {
- IPC::Message::Sender* port1;
- IPC::Message::Sender* port2;
- };
-
- // A map of channel ID to its channel object.
- typedef std::map<int, MessageChannel> MessageChannelMap;
MessageChannelMap channels_;
// True if Init has been called.
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 03c961a..a462862 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -671,6 +671,8 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
OnExtensionAddListener)
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRemoveListener,
OnExtensionRemoveListener)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionCloseChannel,
+ OnExtensionCloseChannel)
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP_EX()
@@ -887,14 +889,17 @@ void BrowserRenderProcessHost::Observe(NotificationType type,
void BrowserRenderProcessHost::OnExtensionAddListener(
const std::string& event_name) {
- URLRequestContext* context = profile()->GetRequestContext();
- ExtensionMessageService* ems = ExtensionMessageService::GetInstance(context);
- ems->AddEventListener(event_name, pid());
+ ExtensionMessageService::GetInstance(profile()->GetRequestContext())->
+ AddEventListener(event_name, pid());
}
void BrowserRenderProcessHost::OnExtensionRemoveListener(
const std::string& event_name) {
- URLRequestContext* context = profile()->GetRequestContext();
- ExtensionMessageService* ems = ExtensionMessageService::GetInstance(context);
- ems->RemoveEventListener(event_name, pid());
+ ExtensionMessageService::GetInstance(profile()->GetRequestContext())->
+ RemoveEventListener(event_name, pid());
+}
+
+void BrowserRenderProcessHost::OnExtensionCloseChannel(int port_id) {
+ ExtensionMessageService::GetInstance(profile()->GetRequestContext())->
+ CloseChannel(port_id);
}
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index aee8d2b..d92d9fd 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -87,16 +87,15 @@ class BrowserRenderProcessHost : public RenderProcessHost,
const NotificationSource& source,
const NotificationDetails& details);
- // An extension process started or stopped listening to an event.
- void OnExtensionAddListener(const std::string& event_name);
- void OnExtensionRemoveListener(const std::string& event_name);
-
private:
// Control message handlers.
void OnPageContents(const GURL& url, int32 page_id,
const std::wstring& contents);
void OnUpdatedCacheStats(const WebKit::WebCache::UsageStats& stats);
void SuddenTerminationChanged(bool enabled);
+ void OnExtensionAddListener(const std::string& event_name);
+ void OnExtensionRemoveListener(const std::string& event_name);
+ void OnExtensionCloseChannel(int port_id);
// Initialize support for visited links. Send the renderer process its initial
// set of visited links.
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index a1bcff2..c8de0fe 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1383,6 +1383,11 @@ IPC_BEGIN_MESSAGES(ViewHost)
int /* port_id */,
std::string /* message */)
+ // Send a message to an extension process. The handle is the value returned
+ // by ViewHostMsg_OpenChannelToExtension.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_ExtensionCloseChannel,
+ int /* port_id */)
+
// Message to show a popup menu using native cocoa controls (Mac only).
IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup,
ViewHostMsg_ShowPopup_Params)
diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h
index f2c5f88..285a379 100644
--- a/chrome/renderer/extensions/event_bindings.h
+++ b/chrome/renderer/extensions/event_bindings.h
@@ -27,8 +27,8 @@ class EventBindings {
static void HandleContextDestroyed(WebFrame* frame);
// Calls the given function in each registered context which is listening
- // for events. The function can be an object property, ie:
- // "chromium.Event.dispatch_".
+ // for events. See comments on bindings_utils::CallFunctionInContext for
+ // more details.
static void CallFunction(const std::string& function_name, int argc,
v8::Handle<v8::Value>* argv);
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc
index f719797..4cff1dd 100644
--- a/chrome/renderer/extensions/renderer_extension_bindings.cc
+++ b/chrome/renderer/extensions/renderer_extension_bindings.cc
@@ -46,6 +46,8 @@ class ExtensionImpl : public ExtensionBase {
return v8::FunctionTemplate::New(OpenChannelToExtension);
} else if (name->Equals(v8::String::New("PostMessage"))) {
return v8::FunctionTemplate::New(PostMessage);
+ } else if (name->Equals(v8::String::New("CloseChannel"))) {
+ return v8::FunctionTemplate::New(CloseChannel);
}
return ExtensionBase::GetNativeFunction(name);
}
@@ -83,6 +85,17 @@ class ExtensionImpl : public ExtensionBase {
}
return v8::Undefined();
}
+
+ // Sends a message along the given channel.
+ static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) {
+ if (args.Length() >= 1 && args[0]->IsInt32()) {
+ int port_id = args[0]->Int32Value();
+ // Send via the RenderThread because the RenderView might be closing.
+ EventBindings::GetRenderThread()->Send(
+ new ViewHostMsg_ExtensionCloseChannel(port_id));
+ }
+ return v8::Undefined();
+ }
};
// Convert a ListValue to a vector of V8 values.
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index bf59671..f9d354e 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -10,6 +10,7 @@
var chrome = chrome || {};
(function () {
native function OpenChannelToExtension(id);
+ native function CloseChannel(portId);
native function PostMessage(portId, msg);
native function GetChromeHidden();
@@ -78,7 +79,7 @@ var chrome = chrome || {};
// Disconnects the port from the other end.
chrome.Port.prototype.disconnect = function() {
delete ports[this.portId_];
- //CloseChannel(this.portId_); // TODO(mpcomplete)
+ CloseChannel(this.portId_);
}
// Extension object.