Chromium Code Reviews| 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); |