Index: chrome/browser/extensions/message_service.cc |
diff --git a/chrome/browser/extensions/message_service.cc b/chrome/browser/extensions/message_service.cc |
index 8758c13df577ec0dfbe168b1b215a1abc3c2b2fc..eae3d72104a9ec9610c63a2801cf6fd406c1fdd1 100644 |
--- a/chrome/browser/extensions/message_service.cc |
+++ b/chrome/browser/extensions/message_service.cc |
@@ -16,6 +16,7 @@ |
#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/native_message_process.h" |
#include "chrome/browser/extensions/process_map.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/tab_contents/tab_util.h" |
@@ -24,6 +25,7 @@ |
#include "chrome/common/extensions/extension.h" |
#include "chrome/common/extensions/extension_messages.h" |
#include "chrome/common/view_type.h" |
+#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/notification_service.h" |
#include "content/public/browser/render_process_host.h" |
#include "content/public/browser/render_view_host.h" |
@@ -52,18 +54,23 @@ struct MessageService::MessagePort { |
int routing_id; |
std::string extension_id; |
void* background_host_ptr; // used in IncrementLazyKeepaliveCount |
+ // HACK(eriq) |
+ bool is_native; |
+ linked_ptr<NativeMessageProcess> native_process; |
Aaron Boodman
2012/08/09 18:36:12
linked_ptr here is unfortunate, as it makes the li
eaugusti
2012/08/13 23:22:34
Will now be a raw pointer.
|
MessagePort() |
: process(NULL), |
routing_id(MSG_ROUTING_CONTROL), |
- background_host_ptr(NULL) {} |
+ background_host_ptr(NULL), |
+ is_native(false) {} |
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) {} |
+ background_host_ptr(NULL), |
+ is_native(false) {} |
}; |
struct MessageService::MessageChannel { |
@@ -121,8 +128,12 @@ static void DispatchOnDisconnect(const MessageService::MessagePort& port, |
static void DispatchOnMessage(const MessageService::MessagePort& port, |
const std::string& message, |
int target_port_id) { |
- port.process->Send(new ExtensionMsg_DeliverMessage( |
- port.routing_id, target_port_id, message)); |
+ if (port.is_native) { |
+ port.native_process->Send(message); |
+ } else { |
+ port.process->Send(new ExtensionMsg_DeliverMessage( |
+ port.routing_id, target_port_id, message)); |
+ } |
} |
static content::RenderProcessHost* GetExtensionProcess( |
@@ -237,6 +248,93 @@ void MessageService::OpenChannelToExtension( |
OpenChannelImpl(params); |
} |
+void MessageService::OpenChannelToNativeApp( |
+ int source_process_id, |
+ int source_routing_id, |
+ int receiver_port_id, |
+ const std::string& source_extension_id, |
+ const std::string& native_app_name, |
+ const std::string& channel_name, |
+ const std::string& connect_message) { |
+ content::RenderProcessHost* source = |
+ content::RenderProcessHost::FromID(source_process_id); |
+ if (!source) |
+ return; |
+ Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); |
+ |
+ // Note: we use the source's profile here. If the source is an incognito |
+ // process, we will use the incognito EPM to find the right extension process, |
+ // which depends on whether the extension uses spanning or split mode. |
+ MessagePort receiver(GetExtensionProcess(profile, source_extension_id), |
Matt Perry
2012/08/09 02:13:00
The receiver is the target of the connect event -
eaugusti
2012/08/13 23:22:34
Done.
|
+ MSG_ROUTING_CONTROL, |
+ "native"); |
+ WebContents* source_contents = tab_util::GetWebContentsByID( |
+ source_process_id, source_routing_id); |
+ |
+ // Include info about the opener's tab (if it was a tab). |
+ std::string tab_json = "null"; |
+ if (source_contents) { |
+ scoped_ptr<DictionaryValue> tab_value( |
+ ExtensionTabUtil::CreateTabValue(source_contents)); |
+ base::JSONWriter::Write(tab_value.get(), &tab_json); |
+ } |
+ |
+ MessageChannel* channel(new MessageChannel); |
+ channel->opener = MessagePort(source, MSG_ROUTING_CONTROL, |
+ source_extension_id); |
+ channel->receiver = receiver; |
+ |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&MessageService::OpenChannelToNativeAppOnFileThread, |
+ base::Unretained(this), |
+ receiver_port_id, |
+ native_app_name, |
+ channel_name, |
+ connect_message, |
+ channel, |
+ tab_json)); |
+ |
+ // TODO(eriq): This should actually be called after the channel is opened |
+ // successfully. |
+ IncrementLazyKeepaliveCount(&channel->opener); |
+} |
+ |
+void MessageService::OpenChannelToNativeAppOnFileThread( |
Matt Perry
2012/08/09 02:13:00
This class is not threadsafe. Same goes for |chann
eaugusti
2012/08/13 23:22:34
Done.
|
+ int receiver_port_id, |
+ const std::string& native_app_name, |
+ const std::string& channel_name, |
+ const std::string& connect_message, |
+ MessageChannel* channel, |
+ const std::string& tab_json) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ |
+ NativeMessageProcess::MessageType type = NativeMessageProcess::TYPE_CONNECT; |
+ if (channel_name == "chrome.extension.sendNativeMessage") |
+ type = NativeMessageProcess::TYPE_SEND_MESSAGE_REQUEST; |
+ |
+ NativeMessageProcess* native_process = NativeMessageProcess::Create( |
+ native_app_name, connect_message, this, receiver_port_id, type); |
Matt Perry
2012/08/09 02:13:00
What if an extension opens 2 channels to the same
Aaron Boodman
2012/08/09 18:36:12
I think we should just create two. The extension s
eaugusti
2012/08/13 23:22:34
I agree with spawning multiple processes, the nati
|
+ if (!native_process) { |
+ LOG(ERROR) << "Failed to create native process."; |
+ return; |
+ } |
+ channel->receiver.is_native = true; |
+ channel->receiver.native_process.reset(native_process); |
+ |
+ int channel_id = GET_CHANNEL_ID(receiver_port_id); |
+ CHECK(channels_.find(channel_id) == channels_.end()); |
+ channels_[channel_id] = channel; |
+ pending_channels_.erase(channel_id); |
+ |
+ // Send the connect event to the receiver. Give it the opener's port ID (the |
+ // opener has the opposite port ID). |
+ DispatchOnConnect(channel->receiver, receiver_port_id, |
Matt Perry
2012/08/09 02:13:00
I don't think this call makes sense. You're dispat
eaugusti
2012/08/13 23:22:34
You're right, it doesn't make sense.
|
+ channel_name, tab_json, |
+ channel->opener.extension_id, "native"); |
+} |
+ |
void MessageService::OpenChannelToTab( |
int source_process_id, int source_routing_id, int receiver_port_id, |
int tab_id, const std::string& extension_id, |
@@ -348,13 +446,19 @@ void MessageService::CloseChannelImpl( |
if (notify_other_port) { |
const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ? |
channel->receiver : channel->opener; |
- DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id), |
- connection_error); |
+ |
+ if (!port.is_native) { |
+ DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id), |
+ connection_error); |
+ } |
} |
// Balance the addrefs in OpenChannelImpl. |
DecrementLazyKeepaliveCount(&channel->opener); |
- DecrementLazyKeepaliveCount(&channel->receiver); |
+ // The reciever may be native. |
+ if (!channel->receiver.is_native) { |
+ DecrementLazyKeepaliveCount(&channel->receiver); |
+ } |
delete channel_iter->second; |
channels_.erase(channel_iter); |