Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: chrome/browser/extensions/message_service.cc

Issue 10818013: Native Messaging! (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Everything is Different! Merged with MessageService Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/message_service.h" 5 #include "chrome/browser/extensions/message_service.h"
6 6
7 #include "base/atomic_sequence_num.h" 7 #include "base/atomic_sequence_num.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chrome/browser/extensions/extension_host.h" 13 #include "chrome/browser/extensions/extension_host.h"
14 #include "chrome/browser/extensions/extension_process_manager.h" 14 #include "chrome/browser/extensions/extension_process_manager.h"
15 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/extensions/extension_system.h"
17 #include "chrome/browser/extensions/extension_tab_util.h" 17 #include "chrome/browser/extensions/extension_tab_util.h"
18 #include "chrome/browser/extensions/lazy_background_task_queue.h" 18 #include "chrome/browser/extensions/lazy_background_task_queue.h"
19 #include "chrome/browser/extensions/native_message_process.h"
19 #include "chrome/browser/extensions/process_map.h" 20 #include "chrome/browser/extensions/process_map.h"
20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/tab_contents/tab_util.h" 22 #include "chrome/browser/tab_contents/tab_util.h"
22 #include "chrome/browser/ui/tab_contents/tab_contents.h" 23 #include "chrome/browser/ui/tab_contents/tab_contents.h"
23 #include "chrome/common/chrome_notification_types.h" 24 #include "chrome/common/chrome_notification_types.h"
24 #include "chrome/common/extensions/extension.h" 25 #include "chrome/common/extensions/extension.h"
25 #include "chrome/common/extensions/extension_messages.h" 26 #include "chrome/common/extensions/extension_messages.h"
26 #include "chrome/common/view_type.h" 27 #include "chrome/common/view_type.h"
28 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/render_process_host.h" 30 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/render_view_host.h" 31 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/site_instance.h" 32 #include "content/public/browser/site_instance.h"
31 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
32 34
33 using content::SiteInstance; 35 using content::SiteInstance;
34 using content::WebContents; 36 using content::WebContents;
35 37
36 // Since we have 2 ports for every channel, we just index channels by half the 38 // Since we have 2 ports for every channel, we just index channels by half the
37 // port ID. 39 // port ID.
38 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) 40 #define GET_CHANNEL_ID(port_id) ((port_id) / 2)
39 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) 41 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2)
40 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) 42 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1)
41 43
42 // Port1 is always even, port2 is always odd. 44 // Port1 is always even, port2 is always odd.
43 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) 45 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0)
44 46
45 // Change even to odd and vice versa, to get the other side of a given channel. 47 // Change even to odd and vice versa, to get the other side of a given channel.
46 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) 48 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1)
47 49
48 namespace extensions { 50 namespace extensions {
49 51
50 struct MessageService::MessagePort { 52 struct MessageService::MessagePort {
Matt Perry 2012/08/09 02:13:00 maybe we should turn this into an interface that d
Aaron Boodman 2012/08/09 18:36:12 /me is shocked to here mpcomplete say 'interface'.
eaugusti 2012/08/13 23:22:34 Done.
51 content::RenderProcessHost* process; 53 content::RenderProcessHost* process;
52 int routing_id; 54 int routing_id;
53 std::string extension_id; 55 std::string extension_id;
54 void* background_host_ptr; // used in IncrementLazyKeepaliveCount 56 void* background_host_ptr; // used in IncrementLazyKeepaliveCount
57 // HACK(eriq)
58 bool is_native;
59 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.
55 60
56 MessagePort() 61 MessagePort()
57 : process(NULL), 62 : process(NULL),
58 routing_id(MSG_ROUTING_CONTROL), 63 routing_id(MSG_ROUTING_CONTROL),
59 background_host_ptr(NULL) {} 64 background_host_ptr(NULL),
65 is_native(false) {}
60 MessagePort(content::RenderProcessHost* process, 66 MessagePort(content::RenderProcessHost* process,
61 int routing_id, 67 int routing_id,
62 const std::string& extension_id) 68 const std::string& extension_id)
63 : process(process), 69 : process(process),
64 routing_id(routing_id), 70 routing_id(routing_id),
65 extension_id(extension_id), 71 extension_id(extension_id),
66 background_host_ptr(NULL) {} 72 background_host_ptr(NULL),
73 is_native(false) {}
67 }; 74 };
68 75
69 struct MessageService::MessageChannel { 76 struct MessageService::MessageChannel {
70 MessageService::MessagePort opener; 77 MessageService::MessagePort opener;
71 MessageService::MessagePort receiver; 78 MessageService::MessagePort receiver;
72 }; 79 };
73 80
74 struct MessageService::OpenChannelParams { 81 struct MessageService::OpenChannelParams {
75 content::RenderProcessHost* source; 82 content::RenderProcessHost* source;
76 std::string tab_json; 83 std::string tab_json;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 static void DispatchOnDisconnect(const MessageService::MessagePort& port, 121 static void DispatchOnDisconnect(const MessageService::MessagePort& port,
115 int source_port_id, 122 int source_port_id,
116 bool connection_error) { 123 bool connection_error) {
117 port.process->Send(new ExtensionMsg_DispatchOnDisconnect( 124 port.process->Send(new ExtensionMsg_DispatchOnDisconnect(
118 port.routing_id, source_port_id, connection_error)); 125 port.routing_id, source_port_id, connection_error));
119 } 126 }
120 127
121 static void DispatchOnMessage(const MessageService::MessagePort& port, 128 static void DispatchOnMessage(const MessageService::MessagePort& port,
122 const std::string& message, 129 const std::string& message,
123 int target_port_id) { 130 int target_port_id) {
124 port.process->Send(new ExtensionMsg_DeliverMessage( 131 if (port.is_native) {
125 port.routing_id, target_port_id, message)); 132 port.native_process->Send(message);
133 } else {
134 port.process->Send(new ExtensionMsg_DeliverMessage(
135 port.routing_id, target_port_id, message));
136 }
126 } 137 }
127 138
128 static content::RenderProcessHost* GetExtensionProcess( 139 static content::RenderProcessHost* GetExtensionProcess(
129 Profile* profile, const std::string& extension_id) { 140 Profile* profile, const std::string& extension_id) {
130 SiteInstance* site_instance = 141 SiteInstance* site_instance =
131 profile->GetExtensionProcessManager()->GetSiteInstanceForURL( 142 profile->GetExtensionProcessManager()->GetSiteInstanceForURL(
132 Extension::GetBaseURLFromExtensionId(extension_id)); 143 Extension::GetBaseURLFromExtensionId(extension_id));
133 144
134 if (!site_instance->HasProcess()) 145 if (!site_instance->HasProcess())
135 return NULL; 146 return NULL;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 241
231 // The target might be a lazy background page. In that case, we have to check 242 // The target might be a lazy background page. In that case, we have to check
232 // if it is loaded and ready, and if not, queue up the task and load the 243 // if it is loaded and ready, and if not, queue up the task and load the
233 // page. 244 // page.
234 if (MaybeAddPendingOpenChannelTask(profile, params)) 245 if (MaybeAddPendingOpenChannelTask(profile, params))
235 return; 246 return;
236 247
237 OpenChannelImpl(params); 248 OpenChannelImpl(params);
238 } 249 }
239 250
251 void MessageService::OpenChannelToNativeApp(
252 int source_process_id,
253 int source_routing_id,
254 int receiver_port_id,
255 const std::string& source_extension_id,
256 const std::string& native_app_name,
257 const std::string& channel_name,
258 const std::string& connect_message) {
259 content::RenderProcessHost* source =
260 content::RenderProcessHost::FromID(source_process_id);
261 if (!source)
262 return;
263 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
264
265 // Note: we use the source's profile here. If the source is an incognito
266 // process, we will use the incognito EPM to find the right extension process,
267 // which depends on whether the extension uses spanning or split mode.
268 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.
269 MSG_ROUTING_CONTROL,
270 "native");
271 WebContents* source_contents = tab_util::GetWebContentsByID(
272 source_process_id, source_routing_id);
273
274 // Include info about the opener's tab (if it was a tab).
275 std::string tab_json = "null";
276 if (source_contents) {
277 scoped_ptr<DictionaryValue> tab_value(
278 ExtensionTabUtil::CreateTabValue(source_contents));
279 base::JSONWriter::Write(tab_value.get(), &tab_json);
280 }
281
282 MessageChannel* channel(new MessageChannel);
283 channel->opener = MessagePort(source, MSG_ROUTING_CONTROL,
284 source_extension_id);
285 channel->receiver = receiver;
286
287 content::BrowserThread::PostTask(
288 content::BrowserThread::FILE,
289 FROM_HERE,
290 base::Bind(&MessageService::OpenChannelToNativeAppOnFileThread,
291 base::Unretained(this),
292 receiver_port_id,
293 native_app_name,
294 channel_name,
295 connect_message,
296 channel,
297 tab_json));
298
299 // TODO(eriq): This should actually be called after the channel is opened
300 // successfully.
301 IncrementLazyKeepaliveCount(&channel->opener);
302 }
303
304 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.
305 int receiver_port_id,
306 const std::string& native_app_name,
307 const std::string& channel_name,
308 const std::string& connect_message,
309 MessageChannel* channel,
310 const std::string& tab_json) {
311 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
312
313 NativeMessageProcess::MessageType type = NativeMessageProcess::TYPE_CONNECT;
314 if (channel_name == "chrome.extension.sendNativeMessage")
315 type = NativeMessageProcess::TYPE_SEND_MESSAGE_REQUEST;
316
317 NativeMessageProcess* native_process = NativeMessageProcess::Create(
318 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
319 if (!native_process) {
320 LOG(ERROR) << "Failed to create native process.";
321 return;
322 }
323 channel->receiver.is_native = true;
324 channel->receiver.native_process.reset(native_process);
325
326 int channel_id = GET_CHANNEL_ID(receiver_port_id);
327 CHECK(channels_.find(channel_id) == channels_.end());
328 channels_[channel_id] = channel;
329 pending_channels_.erase(channel_id);
330
331 // Send the connect event to the receiver. Give it the opener's port ID (the
332 // opener has the opposite port ID).
333 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.
334 channel_name, tab_json,
335 channel->opener.extension_id, "native");
336 }
337
240 void MessageService::OpenChannelToTab( 338 void MessageService::OpenChannelToTab(
241 int source_process_id, int source_routing_id, int receiver_port_id, 339 int source_process_id, int source_routing_id, int receiver_port_id,
242 int tab_id, const std::string& extension_id, 340 int tab_id, const std::string& extension_id,
243 const std::string& channel_name) { 341 const std::string& channel_name) {
244 content::RenderProcessHost* source = 342 content::RenderProcessHost* source =
245 content::RenderProcessHost::FromID(source_process_id); 343 content::RenderProcessHost::FromID(source_process_id);
246 if (!source) 344 if (!source)
247 return; 345 return;
248 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 346 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
249 347
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 439
342 void MessageService::CloseChannelImpl( 440 void MessageService::CloseChannelImpl(
343 MessageChannelMap::iterator channel_iter, int closing_port_id, 441 MessageChannelMap::iterator channel_iter, int closing_port_id,
344 bool connection_error, bool notify_other_port) { 442 bool connection_error, bool notify_other_port) {
345 MessageChannel* channel = channel_iter->second; 443 MessageChannel* channel = channel_iter->second;
346 444
347 // Notify the other side. 445 // Notify the other side.
348 if (notify_other_port) { 446 if (notify_other_port) {
349 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ? 447 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ?
350 channel->receiver : channel->opener; 448 channel->receiver : channel->opener;
351 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id), 449
352 connection_error); 450 if (!port.is_native) {
451 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id),
452 connection_error);
453 }
353 } 454 }
354 455
355 // Balance the addrefs in OpenChannelImpl. 456 // Balance the addrefs in OpenChannelImpl.
356 DecrementLazyKeepaliveCount(&channel->opener); 457 DecrementLazyKeepaliveCount(&channel->opener);
357 DecrementLazyKeepaliveCount(&channel->receiver); 458 // The reciever may be native.
459 if (!channel->receiver.is_native) {
460 DecrementLazyKeepaliveCount(&channel->receiver);
461 }
358 462
359 delete channel_iter->second; 463 delete channel_iter->second;
360 channels_.erase(channel_iter); 464 channels_.erase(channel_iter);
361 } 465 }
362 466
363 void MessageService::PostMessageFromRenderer( 467 void MessageService::PostMessageFromRenderer(
364 int source_port_id, const std::string& message) { 468 int source_port_id, const std::string& message) {
365 int channel_id = GET_CHANNEL_ID(source_port_id); 469 int channel_id = GET_CHANNEL_ID(source_port_id);
366 MessageChannelMap::iterator iter = channels_.find(channel_id); 470 MessageChannelMap::iterator iter = channels_.find(channel_id);
367 if (iter == channels_.end()) { 471 if (iter == channels_.end()) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 if (!params.source) 566 if (!params.source)
463 return; 567 return;
464 568
465 params.receiver = MessagePort(host->render_process_host(), 569 params.receiver = MessagePort(host->render_process_host(),
466 MSG_ROUTING_CONTROL, 570 MSG_ROUTING_CONTROL,
467 params.target_extension_id); 571 params.target_extension_id);
468 OpenChannelImpl(params); 572 OpenChannelImpl(params);
469 } 573 }
470 574
471 } // namespace extensions 575 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698