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/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/chrome_notification_types.h" |
16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" | 16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" |
17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h" | 17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h" |
18 #include "chrome/browser/extensions/api/messaging/native_message_port.h" | 18 #include "chrome/browser/extensions/api/messaging/native_message_port.h" |
| 19 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
19 #include "chrome/browser/extensions/extension_host.h" | 20 #include "chrome/browser/extensions/extension_host.h" |
20 #include "chrome/browser/extensions/extension_service.h" | 21 #include "chrome/browser/extensions/extension_service.h" |
21 #include "chrome/browser/extensions/extension_tab_util.h" | 22 #include "chrome/browser/extensions/extension_tab_util.h" |
22 #include "chrome/browser/extensions/extension_util.h" | 23 #include "chrome/browser/extensions/extension_util.h" |
23 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
24 #include "chrome/browser/tab_contents/tab_util.h" | 25 #include "chrome/browser/tab_contents/tab_util.h" |
25 #include "chrome/common/extensions/extension_messages.h" | 26 #include "chrome/common/extensions/extension_messages.h" |
26 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h" | 27 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h" |
27 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
28 #include "content/public/browser/render_process_host.h" | 29 #include "content/public/browser/render_process_host.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 }; | 113 }; |
113 | 114 |
114 namespace { | 115 namespace { |
115 | 116 |
116 static base::StaticAtomicSequenceNumber g_next_channel_id; | 117 static base::StaticAtomicSequenceNumber g_next_channel_id; |
117 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; | 118 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; |
118 | 119 |
119 static content::RenderProcessHost* GetExtensionProcess( | 120 static content::RenderProcessHost* GetExtensionProcess( |
120 Profile* profile, const std::string& extension_id) { | 121 Profile* profile, const std::string& extension_id) { |
121 SiteInstance* site_instance = | 122 SiteInstance* site_instance = |
122 ExtensionSystem::Get(profile)->process_manager()-> | 123 ExtensionSystem::Get(profile)->process_manager()->GetSiteInstanceForURL( |
123 GetSiteInstanceForURL( | 124 Extension::GetBaseURLFromExtensionId(extension_id)); |
124 Extension::GetBaseURLFromExtensionId(extension_id)); | 125 return site_instance->HasProcess() ? site_instance->GetProcess() : NULL; |
125 | |
126 if (!site_instance->HasProcess()) | |
127 return NULL; | |
128 | |
129 return site_instance->GetProcess(); | |
130 } | 126 } |
131 | 127 |
132 } // namespace | 128 } // namespace |
133 | 129 |
134 content::RenderProcessHost* | 130 content::RenderProcessHost* |
135 MessageService::MessagePort::GetRenderProcessHost() { | 131 MessageService::MessagePort::GetRenderProcessHost() { |
136 return NULL; | 132 return NULL; |
137 } | 133 } |
138 | 134 |
139 // static | 135 // static |
140 void MessageService::AllocatePortIdPair(int* port1, int* port2) { | 136 void MessageService::AllocatePortIdPair(int* port1, int* port2) { |
141 unsigned channel_id = | 137 unsigned channel_id = |
142 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2); | 138 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2); |
143 | 139 |
144 if (channel_id == 0) { | 140 if (channel_id == 0) { |
145 int overflow_count = g_channel_id_overflow_count.GetNext(); | 141 int overflow_count = g_channel_id_overflow_count.GetNext(); |
146 if (overflow_count > 0) | 142 if (overflow_count > 0) |
147 UMA_HISTOGRAM_BOOLEAN("Extensions.AllocatePortIdPairOverflow", true); | 143 UMA_HISTOGRAM_BOOLEAN("Extensions.AllocatePortIdPairOverflow", true); |
148 } | 144 } |
149 | 145 |
150 unsigned port1_id = channel_id * 2; | 146 unsigned port1_id = channel_id * 2; |
151 unsigned port2_id = channel_id * 2 + 1; | 147 unsigned port2_id = channel_id * 2 + 1; |
152 | 148 |
153 // Sanity checks to make sure our channel<->port converters are correct. | 149 // Sanity checks to make sure our channel<->port converters are correct. |
154 DCHECK(IS_OPENER_PORT_ID(port1_id)); | 150 DCHECK(IS_OPENER_PORT_ID(port1_id)); |
155 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); | 151 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port1_id), port2_id); |
156 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); | 152 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port2_id), port1_id); |
157 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); | 153 DCHECK_EQ(GET_CHANNEL_ID(port1_id), GET_CHANNEL_ID(port2_id)); |
158 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); | 154 DCHECK_EQ(GET_CHANNEL_ID(port1_id), channel_id); |
159 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); | 155 DCHECK_EQ(GET_CHANNEL_OPENER_ID(channel_id), port1_id); |
160 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); | 156 DCHECK_EQ(GET_CHANNEL_RECEIVERS_ID(channel_id), port2_id); |
161 | 157 |
162 *port1 = port1_id; | 158 *port1 = port1_id; |
163 *port2 = port2_id; | 159 *port2 = port2_id; |
164 } | 160 } |
165 | 161 |
166 MessageService::MessageService(Profile* profile) | 162 MessageService::MessageService(Profile* profile) |
167 : lazy_background_task_queue_( | 163 : lazy_background_task_queue_( |
168 ExtensionSystem::Get(profile)->lazy_background_task_queue()), | 164 ExtensionSystem::Get(profile)->lazy_background_task_queue()), |
169 weak_factory_(this) { | 165 weak_factory_(this) { |
170 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 166 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 // which depends on whether the extension uses spanning or split mode. | 289 // which depends on whether the extension uses spanning or split mode. |
294 MessagePort* receiver = new ExtensionMessagePort( | 290 MessagePort* receiver = new ExtensionMessagePort( |
295 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, | 291 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, |
296 target_extension_id); | 292 target_extension_id); |
297 | 293 |
298 // Include info about the opener's tab (if it was a tab). | 294 // Include info about the opener's tab (if it was a tab). |
299 scoped_ptr<base::DictionaryValue> source_tab; | 295 scoped_ptr<base::DictionaryValue> source_tab; |
300 GURL source_url_for_tab; | 296 GURL source_url_for_tab; |
301 | 297 |
302 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { | 298 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { |
303 // Platform apps can be sent messages, but don't have a Tab concept. | 299 // Only the tab id is useful to platform apps for internal use. The |
304 if (!target_extension->is_platform_app()) | 300 // unnecessary bits will be stripped out in |
305 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); | 301 // MessagingBindings::DispatchOnConnect(). |
| 302 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); |
306 source_url_for_tab = source_url; | 303 source_url_for_tab = source_url; |
307 } | 304 } |
308 | 305 |
309 OpenChannelParams* params = new OpenChannelParams(source, | 306 OpenChannelParams* params = new OpenChannelParams(source, |
310 source_tab.Pass(), | 307 source_tab.Pass(), |
311 receiver, | 308 receiver, |
312 receiver_port_id, | 309 receiver_port_id, |
313 source_extension_id, | 310 source_extension_id, |
314 target_extension_id, | 311 target_extension_id, |
315 source_url_for_tab, | 312 source_url_for_tab, |
316 channel_name, | 313 channel_name, |
317 include_tls_channel_id); | 314 include_tls_channel_id); |
318 | 315 |
319 // If the target requests the TLS channel id, begin the lookup for it. | 316 // If the target requests the TLS channel id, begin the lookup for it. |
320 // The target might also be a lazy background page, checked next, but the | 317 // The target might also be a lazy background page, checked next, but the |
321 // loading of lazy background pages continues asynchronously, so enqueue | 318 // loading of lazy background pages continues asynchronously, so enqueue |
322 // messages awaiting TLS channel ID first. | 319 // messages awaiting TLS channel ID first. |
323 if (include_tls_channel_id) { | 320 if (include_tls_channel_id) { |
324 pending_tls_channel_id_channels_[GET_CHANNEL_ID(params->receiver_port_id)] | 321 pending_tls_channel_id_channels_[GET_CHANNEL_ID(params->receiver_port_id)] |
325 = PendingMessagesQueue(); | 322 = PendingMessagesQueue(); |
326 property_provider_.GetDomainBoundCert(profile, params->source_url, | 323 property_provider_.GetDomainBoundCert( |
| 324 profile, |
| 325 source_url, |
327 base::Bind(&MessageService::GotDomainBoundCert, | 326 base::Bind(&MessageService::GotDomainBoundCert, |
328 weak_factory_.GetWeakPtr(), | 327 weak_factory_.GetWeakPtr(), |
329 base::Passed(make_scoped_ptr(params)))); | 328 base::Passed(make_scoped_ptr(params)))); |
330 return; | 329 return; |
331 } | 330 } |
332 | 331 |
333 // The target might be a lazy background page. In that case, we have to check | 332 // The target might be a lazy background page. In that case, we have to check |
334 // if it is loaded and ready, and if not, queue up the task and load the | 333 // if it is loaded and ready, and if not, queue up the task and load the |
335 // page. | 334 // page. |
336 if (MaybeAddPendingLazyBackgroundPageOpenChannelTask(profile, | 335 if (MaybeAddPendingLazyBackgroundPageOpenChannelTask(profile, |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 } | 543 } |
545 | 544 |
546 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. | 545 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. |
547 channel->opener->DecrementLazyKeepaliveCount(); | 546 channel->opener->DecrementLazyKeepaliveCount(); |
548 channel->receiver->DecrementLazyKeepaliveCount(); | 547 channel->receiver->DecrementLazyKeepaliveCount(); |
549 | 548 |
550 delete channel_iter->second; | 549 delete channel_iter->second; |
551 channels_.erase(channel_iter); | 550 channels_.erase(channel_iter); |
552 } | 551 } |
553 | 552 |
554 void MessageService::PostMessage( | 553 void MessageService::PostMessage(int source_port_id, const Message& message) { |
555 int source_port_id, const Message& message) { | |
556 int channel_id = GET_CHANNEL_ID(source_port_id); | 554 int channel_id = GET_CHANNEL_ID(source_port_id); |
557 MessageChannelMap::iterator iter = channels_.find(channel_id); | 555 MessageChannelMap::iterator iter = channels_.find(channel_id); |
558 if (iter == channels_.end()) { | 556 if (iter == channels_.end()) { |
559 // If this channel is pending, queue up the PostMessage to run once | 557 // If this channel is pending, queue up the PostMessage to run once |
560 // the channel opens. | 558 // the channel opens. |
561 EnqueuePendingMessage(source_port_id, channel_id, message); | 559 EnqueuePendingMessage(source_port_id, channel_id, message); |
562 return; | 560 return; |
563 } | 561 } |
564 | 562 |
565 DispatchMessage(source_port_id, iter->second, message); | 563 DispatchMessage(source_port_id, iter->second, message); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 } | 754 } |
757 | 755 |
758 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, | 756 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, |
759 int port_id, | 757 int port_id, |
760 const std::string& error_message) { | 758 const std::string& error_message) { |
761 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); | 759 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); |
762 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); | 760 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); |
763 } | 761 } |
764 | 762 |
765 } // namespace extensions | 763 } // namespace extensions |
OLD | NEW |