OLD | NEW |
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/api/messaging/message_service.h" | 5 #include "chrome/browser/extensions/api/messaging/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/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
15 #include "base/values.h" | |
16 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/chrome_notification_types.h" |
17 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" | 16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" |
18 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h" | 17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h" |
19 #include "chrome/browser/extensions/api/messaging/native_message_port.h" | 18 #include "chrome/browser/extensions/api/messaging/native_message_port.h" |
20 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" | 19 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
21 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
22 #include "chrome/browser/extensions/extension_tab_util.h" | 21 #include "chrome/browser/extensions/extension_tab_util.h" |
23 #include "chrome/browser/extensions/extension_util.h" | 22 #include "chrome/browser/extensions/extension_util.h" |
24 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
25 #include "chrome/browser/tab_contents/tab_util.h" | 24 #include "chrome/browser/tab_contents/tab_util.h" |
26 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
| 26 #include "content/public/browser/render_frame_host.h" |
27 #include "content/public/browser/render_process_host.h" | 27 #include "content/public/browser/render_process_host.h" |
28 #include "content/public/browser/render_view_host.h" | 28 #include "content/public/browser/render_view_host.h" |
29 #include "content/public/browser/render_widget_host.h" | 29 #include "content/public/browser/render_widget_host.h" |
30 #include "content/public/browser/render_widget_host_view.h" | 30 #include "content/public/browser/render_widget_host_view.h" |
31 #include "content/public/browser/site_instance.h" | 31 #include "content/public/browser/site_instance.h" |
32 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
33 #include "extensions/browser/extension_host.h" | 33 #include "extensions/browser/extension_host.h" |
34 #include "extensions/browser/extension_system.h" | 34 #include "extensions/browser/extension_system.h" |
35 #include "extensions/browser/extensions_browser_client.h" | 35 #include "extensions/browser/extensions_browser_client.h" |
36 #include "extensions/browser/lazy_background_task_queue.h" | 36 #include "extensions/browser/lazy_background_task_queue.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 "administrator."; | 111 "administrator."; |
112 #endif | 112 #endif |
113 | 113 |
114 struct MessageService::MessageChannel { | 114 struct MessageService::MessageChannel { |
115 scoped_ptr<MessagePort> opener; | 115 scoped_ptr<MessagePort> opener; |
116 scoped_ptr<MessagePort> receiver; | 116 scoped_ptr<MessagePort> receiver; |
117 }; | 117 }; |
118 | 118 |
119 struct MessageService::OpenChannelParams { | 119 struct MessageService::OpenChannelParams { |
120 content::RenderProcessHost* source; | 120 content::RenderProcessHost* source; |
121 base::DictionaryValue source_tab; | 121 scoped_ptr<base::DictionaryValue> source_tab; |
| 122 int source_frame_id; |
122 scoped_ptr<MessagePort> receiver; | 123 scoped_ptr<MessagePort> receiver; |
123 int receiver_port_id; | 124 int receiver_port_id; |
124 std::string source_extension_id; | 125 std::string source_extension_id; |
125 std::string target_extension_id; | 126 std::string target_extension_id; |
126 GURL source_url; | 127 GURL source_url; |
127 std::string channel_name; | 128 std::string channel_name; |
128 bool include_tls_channel_id; | 129 bool include_tls_channel_id; |
129 std::string tls_channel_id; | 130 std::string tls_channel_id; |
130 | 131 |
131 // Takes ownership of receiver. | 132 // Takes ownership of receiver. |
132 OpenChannelParams(content::RenderProcessHost* source, | 133 OpenChannelParams(content::RenderProcessHost* source, |
133 scoped_ptr<base::DictionaryValue> source_tab, | 134 scoped_ptr<base::DictionaryValue> source_tab, |
| 135 int source_frame_id, |
134 MessagePort* receiver, | 136 MessagePort* receiver, |
135 int receiver_port_id, | 137 int receiver_port_id, |
136 const std::string& source_extension_id, | 138 const std::string& source_extension_id, |
137 const std::string& target_extension_id, | 139 const std::string& target_extension_id, |
138 const GURL& source_url, | 140 const GURL& source_url, |
139 const std::string& channel_name, | 141 const std::string& channel_name, |
140 bool include_tls_channel_id) | 142 bool include_tls_channel_id) |
141 : source(source), | 143 : source(source), |
| 144 source_frame_id(source_frame_id), |
142 receiver(receiver), | 145 receiver(receiver), |
143 receiver_port_id(receiver_port_id), | 146 receiver_port_id(receiver_port_id), |
144 source_extension_id(source_extension_id), | 147 source_extension_id(source_extension_id), |
145 target_extension_id(target_extension_id), | 148 target_extension_id(target_extension_id), |
146 source_url(source_url), | 149 source_url(source_url), |
147 channel_name(channel_name), | 150 channel_name(channel_name), |
148 include_tls_channel_id(include_tls_channel_id) { | 151 include_tls_channel_id(include_tls_channel_id) { |
149 if (source_tab) | 152 if (source_tab) |
150 this->source_tab.Swap(source_tab.get()); | 153 this->source_tab = source_tab.Pass(); |
151 } | 154 } |
152 | 155 |
153 private: | 156 private: |
154 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); | 157 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); |
155 }; | 158 }; |
156 | 159 |
157 namespace { | 160 namespace { |
158 | 161 |
159 static base::StaticAtomicSequenceNumber g_next_channel_id; | 162 static base::StaticAtomicSequenceNumber g_next_channel_id; |
160 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; | 163 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 if (!is_externally_connectable) { | 294 if (!is_externally_connectable) { |
292 // Important: use kReceivingEndDoesntExistError here so that we don't | 295 // Important: use kReceivingEndDoesntExistError here so that we don't |
293 // leak information about this extension to callers. This way it's | 296 // leak information about this extension to callers. This way it's |
294 // indistinguishable from the extension just not existing. | 297 // indistinguishable from the extension just not existing. |
295 DispatchOnDisconnect( | 298 DispatchOnDisconnect( |
296 source, receiver_port_id, kReceivingEndDoesntExistError); | 299 source, receiver_port_id, kReceivingEndDoesntExistError); |
297 return; | 300 return; |
298 } | 301 } |
299 } | 302 } |
300 | 303 |
301 WebContents* source_contents = tab_util::GetWebContentsByID( | 304 WebContents* source_contents = tab_util::GetWebContentsByFrameID( |
302 source_process_id, source_routing_id); | 305 source_process_id, source_routing_id); |
303 | 306 |
304 if (context->IsOffTheRecord() && | 307 if (context->IsOffTheRecord() && |
305 !util::IsIncognitoEnabled(target_extension_id, context)) { | 308 !util::IsIncognitoEnabled(target_extension_id, context)) { |
306 // Give the user a chance to accept an incognito connection from the web if | 309 // Give the user a chance to accept an incognito connection from the web if |
307 // they haven't already, with the conditions: | 310 // they haven't already, with the conditions: |
308 // - Only for spanning-mode incognito. We don't want the complication of | 311 // - Only for spanning-mode incognito. We don't want the complication of |
309 // spinning up an additional process here which might need to do some | 312 // spinning up an additional process here which might need to do some |
310 // setup that we're not expecting. | 313 // setup that we're not expecting. |
311 // - Only for extensions that can't normally be enabled in incognito, since | 314 // - Only for extensions that can't normally be enabled in incognito, since |
(...skipping 13 matching lines...) Expand all Loading... |
325 // Note: we use the source's profile here. If the source is an incognito | 328 // Note: we use the source's profile here. If the source is an incognito |
326 // process, we will use the incognito EPM to find the right extension process, | 329 // process, we will use the incognito EPM to find the right extension process, |
327 // which depends on whether the extension uses spanning or split mode. | 330 // which depends on whether the extension uses spanning or split mode. |
328 MessagePort* receiver = new ExtensionMessagePort( | 331 MessagePort* receiver = new ExtensionMessagePort( |
329 GetExtensionProcess(context, target_extension_id), | 332 GetExtensionProcess(context, target_extension_id), |
330 MSG_ROUTING_CONTROL, | 333 MSG_ROUTING_CONTROL, |
331 target_extension_id); | 334 target_extension_id); |
332 | 335 |
333 // Include info about the opener's tab (if it was a tab). | 336 // Include info about the opener's tab (if it was a tab). |
334 scoped_ptr<base::DictionaryValue> source_tab; | 337 scoped_ptr<base::DictionaryValue> source_tab; |
| 338 int source_frame_id = -1; |
335 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { | 339 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { |
336 // Only the tab id is useful to platform apps for internal use. The | 340 // Only the tab id is useful to platform apps for internal use. The |
337 // unnecessary bits will be stripped out in | 341 // unnecessary bits will be stripped out in |
338 // MessagingBindings::DispatchOnConnect(). | 342 // MessagingBindings::DispatchOnConnect(). |
339 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); | 343 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); |
| 344 |
| 345 content::RenderFrameHost* rfh = |
| 346 content::RenderFrameHost::FromID(source_process_id, source_routing_id); |
| 347 // Main frame's frameId is 0. |
| 348 if (rfh) |
| 349 source_frame_id = !rfh->GetParent() ? 0 : source_routing_id; |
340 } | 350 } |
341 | 351 |
342 OpenChannelParams* params = new OpenChannelParams( | 352 OpenChannelParams* params = new OpenChannelParams( |
343 source, source_tab.Pass(), receiver, receiver_port_id, | 353 source, source_tab.Pass(), source_frame_id, receiver, receiver_port_id, |
344 source_extension_id, target_extension_id, source_url, channel_name, | 354 source_extension_id, target_extension_id, source_url, channel_name, |
345 include_tls_channel_id); | 355 include_tls_channel_id); |
346 | 356 |
347 // If the target requests the TLS channel id, begin the lookup for it. | 357 // If the target requests the TLS channel id, begin the lookup for it. |
348 // The target might also be a lazy background page, checked next, but the | 358 // The target might also be a lazy background page, checked next, but the |
349 // loading of lazy background pages continues asynchronously, so enqueue | 359 // loading of lazy background pages continues asynchronously, so enqueue |
350 // messages awaiting TLS channel ID first. | 360 // messages awaiting TLS channel ID first. |
351 if (include_tls_channel_id) { | 361 if (include_tls_channel_id) { |
352 pending_tls_channel_id_channels_[GET_CHANNEL_ID(params->receiver_port_id)] | 362 pending_tls_channel_id_channels_[GET_CHANNEL_ID(params->receiver_port_id)] |
353 = PendingMessagesQueue(); | 363 = PendingMessagesQueue(); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 content::RenderProcessHost* source = | 466 content::RenderProcessHost* source = |
457 content::RenderProcessHost::FromID(source_process_id); | 467 content::RenderProcessHost::FromID(source_process_id); |
458 if (!source) | 468 if (!source) |
459 return; | 469 return; |
460 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); | 470 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); |
461 | 471 |
462 WebContents* contents = NULL; | 472 WebContents* contents = NULL; |
463 scoped_ptr<MessagePort> receiver; | 473 scoped_ptr<MessagePort> receiver; |
464 if (ExtensionTabUtil::GetTabById(tab_id, profile, true, | 474 if (ExtensionTabUtil::GetTabById(tab_id, profile, true, |
465 NULL, NULL, &contents, NULL)) { | 475 NULL, NULL, &contents, NULL)) { |
| 476 // TODO(robwu): Update logic so that frames that are not hosted in the main |
| 477 // frame's process can also receive the port. |
466 receiver.reset(new ExtensionMessagePort( | 478 receiver.reset(new ExtensionMessagePort( |
467 contents->GetRenderProcessHost(), | 479 contents->GetRenderProcessHost(), |
468 contents->GetRenderViewHost()->GetRoutingID(), | 480 contents->GetMainFrame()->GetRoutingID(), |
469 extension_id)); | 481 extension_id)); |
470 } | 482 } |
471 | 483 |
472 if (contents && contents->GetController().NeedsReload()) { | 484 if (contents && contents->GetController().NeedsReload()) { |
473 // The tab isn't loaded yet. Don't attempt to connect. | 485 // The tab isn't loaded yet. Don't attempt to connect. |
474 DispatchOnDisconnect( | 486 DispatchOnDisconnect( |
475 source, receiver_port_id, kReceivingEndDoesntExistError); | 487 source, receiver_port_id, kReceivingEndDoesntExistError); |
476 return; | 488 return; |
477 } | 489 } |
478 | 490 |
479 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( | 491 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( |
480 source, | 492 source, |
481 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense | 493 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense |
482 // for opening to tabs. | 494 // for opening to tabs. |
| 495 -1, // If there is no tab, then there is no frame either. |
483 receiver.release(), | 496 receiver.release(), |
484 receiver_port_id, | 497 receiver_port_id, |
485 extension_id, | 498 extension_id, |
486 extension_id, | 499 extension_id, |
487 GURL(), // Source URL doesn't make sense for opening to tabs. | 500 GURL(), // Source URL doesn't make sense for opening to tabs. |
488 channel_name, | 501 channel_name, |
489 false)); // Connections to tabs don't get TLS channel IDs. | 502 false)); // Connections to tabs don't get TLS channel IDs. |
490 OpenChannelImpl(params.Pass()); | 503 OpenChannelImpl(params.Pass()); |
491 } | 504 } |
492 | 505 |
(...skipping 21 matching lines...) Expand all Loading... |
514 CHECK(channel->receiver->GetRenderProcessHost()); | 527 CHECK(channel->receiver->GetRenderProcessHost()); |
515 | 528 |
516 AddChannel(channel, params->receiver_port_id); | 529 AddChannel(channel, params->receiver_port_id); |
517 | 530 |
518 CHECK(channel->receiver->GetRenderProcessHost()); | 531 CHECK(channel->receiver->GetRenderProcessHost()); |
519 | 532 |
520 // Send the connect event to the receiver. Give it the opener's port ID (the | 533 // Send the connect event to the receiver. Give it the opener's port ID (the |
521 // opener has the opposite port ID). | 534 // opener has the opposite port ID). |
522 channel->receiver->DispatchOnConnect(params->receiver_port_id, | 535 channel->receiver->DispatchOnConnect(params->receiver_port_id, |
523 params->channel_name, | 536 params->channel_name, |
524 params->source_tab, | 537 params->source_tab.Pass(), |
| 538 params->source_frame_id, |
525 params->source_extension_id, | 539 params->source_extension_id, |
526 params->target_extension_id, | 540 params->target_extension_id, |
527 params->source_url, | 541 params->source_url, |
528 params->tls_channel_id); | 542 params->tls_channel_id); |
529 | 543 |
530 // Keep both ends of the channel alive until the channel is closed. | 544 // Keep both ends of the channel alive until the channel is closed. |
531 channel->opener->IncrementLazyKeepaliveCount(); | 545 channel->opener->IncrementLazyKeepaliveCount(); |
532 channel->receiver->IncrementLazyKeepaliveCount(); | 546 channel->receiver->IncrementLazyKeepaliveCount(); |
533 return true; | 547 return true; |
534 } | 548 } |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 } | 797 } |
784 | 798 |
785 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, | 799 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, |
786 int port_id, | 800 int port_id, |
787 const std::string& error_message) { | 801 const std::string& error_message) { |
788 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); | 802 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); |
789 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); | 803 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); |
790 } | 804 } |
791 | 805 |
792 } // namespace extensions | 806 } // namespace extensions |
OLD | NEW |