Chromium Code Reviews| 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" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 }; | 112 }; |
| 113 | 113 |
| 114 namespace { | 114 namespace { |
| 115 | 115 |
| 116 static base::StaticAtomicSequenceNumber g_next_channel_id; | 116 static base::StaticAtomicSequenceNumber g_next_channel_id; |
| 117 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; | 117 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; |
| 118 | 118 |
| 119 static content::RenderProcessHost* GetExtensionProcess( | 119 static content::RenderProcessHost* GetExtensionProcess( |
| 120 Profile* profile, const std::string& extension_id) { | 120 Profile* profile, const std::string& extension_id) { |
| 121 SiteInstance* site_instance = | 121 SiteInstance* site_instance = |
| 122 ExtensionSystem::Get(profile)->process_manager()-> | 122 ExtensionSystem::Get(profile)->process_manager()->GetSiteInstanceForURL( |
| 123 GetSiteInstanceForURL( | 123 Extension::GetBaseURLFromExtensionId(extension_id)); |
| 124 Extension::GetBaseURLFromExtensionId(extension_id)); | 124 return site_instance->HasProcess() ? site_instance->GetProcess() : NULL; |
| 125 | |
| 126 if (!site_instance->HasProcess()) | |
| 127 return NULL; | |
| 128 | |
| 129 return site_instance->GetProcess(); | |
| 130 } | 125 } |
| 131 | 126 |
| 132 } // namespace | 127 } // namespace |
| 133 | 128 |
| 134 content::RenderProcessHost* | 129 content::RenderProcessHost* |
| 135 MessageService::MessagePort::GetRenderProcessHost() { | 130 MessageService::MessagePort::GetRenderProcessHost() { |
| 136 return NULL; | 131 return NULL; |
| 137 } | 132 } |
| 138 | 133 |
| 139 // static | 134 // static |
| 140 void MessageService::AllocatePortIdPair(int* port1, int* port2) { | 135 void MessageService::AllocatePortIdPair(int* port1, int* port2) { |
| 141 unsigned channel_id = | 136 unsigned channel_id = |
| 142 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2); | 137 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2); |
| 143 | 138 |
| 144 if (channel_id == 0) { | 139 if (channel_id == 0) { |
| 145 int overflow_count = g_channel_id_overflow_count.GetNext(); | 140 int overflow_count = g_channel_id_overflow_count.GetNext(); |
| 146 if (overflow_count > 0) | 141 if (overflow_count > 0) |
| 147 UMA_HISTOGRAM_BOOLEAN("Extensions.AllocatePortIdPairOverflow", true); | 142 UMA_HISTOGRAM_BOOLEAN("Extensions.AllocatePortIdPairOverflow", true); |
| 148 } | 143 } |
| 149 | 144 |
| 150 unsigned port1_id = channel_id * 2; | 145 unsigned port1_id = channel_id * 2; |
| 151 unsigned port2_id = channel_id * 2 + 1; | 146 unsigned port2_id = channel_id * 2 + 1; |
| 152 | 147 |
| 153 // Sanity checks to make sure our channel<->port converters are correct. | 148 // Sanity checks to make sure our channel<->port converters are correct. |
| 154 DCHECK(IS_OPENER_PORT_ID(port1_id)); | 149 DCHECK(IS_OPENER_PORT_ID(port1_id)); |
| 155 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); | 150 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port1_id), port2_id); |
| 156 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); | 151 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port2_id), port1_id); |
| 157 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); | 152 DCHECK_EQ(GET_CHANNEL_ID(port1_id), GET_CHANNEL_ID(port2_id)); |
| 158 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); | 153 DCHECK_EQ(GET_CHANNEL_ID(port1_id), channel_id); |
| 159 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); | 154 DCHECK_EQ(GET_CHANNEL_OPENER_ID(channel_id), port1_id); |
| 160 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); | 155 DCHECK_EQ(GET_CHANNEL_RECEIVERS_ID(channel_id), port2_id); |
| 161 | 156 |
| 162 *port1 = port1_id; | 157 *port1 = port1_id; |
| 163 *port2 = port2_id; | 158 *port2 = port2_id; |
| 164 } | 159 } |
| 165 | 160 |
| 166 MessageService::MessageService(Profile* profile) | 161 MessageService::MessageService(Profile* profile) |
| 167 : lazy_background_task_queue_( | 162 : lazy_background_task_queue_( |
| 168 ExtensionSystem::Get(profile)->lazy_background_task_queue()), | 163 ExtensionSystem::Get(profile)->lazy_background_task_queue()), |
| 169 weak_factory_(this) { | 164 weak_factory_(this) { |
| 170 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 165 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 // process, we will use the incognito EPM to find the right extension process, | 289 // process, we will use the incognito EPM to find the right extension process, |
| 295 // which depends on whether the extension uses spanning or split mode. | 290 // which depends on whether the extension uses spanning or split mode. |
| 296 MessagePort* receiver = new ExtensionMessagePort( | 291 MessagePort* receiver = new ExtensionMessagePort( |
| 297 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, | 292 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, |
| 298 target_extension_id); | 293 target_extension_id); |
| 299 | 294 |
| 300 // Include info about the opener's tab (if it was a tab). | 295 // Include info about the opener's tab (if it was a tab). |
| 301 scoped_ptr<base::DictionaryValue> source_tab; | 296 scoped_ptr<base::DictionaryValue> source_tab; |
| 302 GURL source_url_for_tab; | 297 GURL source_url_for_tab; |
| 303 | 298 |
| 304 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { | 299 if (source_contents) { |
|
not at google - send to devlin
2014/01/23 16:41:59
Maybe we should just always send the tab data and
Lei Zhang
2014/01/23 20:53:12
Again, I'm doing the filter on the browser side be
not at google - send to devlin
2014/01/23 21:07:43
I don't think accidentally giving the tab info to
| |
| 305 // Platform apps can be sent messages, but don't have a Tab concept. | 300 int tab_id = ExtensionTabUtil::GetTabId(source_contents); |
| 306 if (!target_extension->is_platform_app()) | 301 if (tab_id >= 0) { |
| 307 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); | 302 if (target_extension->is_platform_app()) { |
| 303 // Platform apps can be sent messages, but don't have a Tab concept. | |
| 304 // Send this only so that mediaGalleries.addUserSelectedFolder() can | |
| 305 // figure out the context for the call when there is no app window open. | |
| 306 source_tab.reset( | |
| 307 ExtensionTabUtil::CreateTabValueForPlatformApp(source_contents)); | |
| 308 | |
| 309 // Record this so it is possible to verify |target_extension_id| has | |
| 310 // access to the tab with |tab_id|. | |
| 311 int channel_id = GET_CHANNEL_ID(receiver_port_id); | |
| 312 DCHECK(!ContainsKey(pending_dispatches_to_platform_apps_, channel_id)); | |
| 313 pending_dispatches_to_platform_apps_[channel_id] = | |
| 314 std::make_pair(target_extension_id, tab_id); | |
| 315 } else { | |
| 316 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); | |
| 317 } | |
| 318 } | |
| 308 source_url_for_tab = source_url; | 319 source_url_for_tab = source_url; |
| 309 } | 320 } |
| 310 | 321 |
| 311 OpenChannelParams* params = new OpenChannelParams(source, | 322 OpenChannelParams* params = new OpenChannelParams(source, |
| 312 source_tab.Pass(), | 323 source_tab.Pass(), |
| 313 receiver, | 324 receiver, |
| 314 receiver_port_id, | 325 receiver_port_id, |
| 315 source_extension_id, | 326 source_extension_id, |
| 316 target_extension_id, | 327 target_extension_id, |
| 317 source_url_for_tab, | 328 source_url_for_tab, |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 int channel_id = GET_CHANNEL_ID(receiver_port_id); | 515 int channel_id = GET_CHANNEL_ID(receiver_port_id); |
| 505 CHECK(channels_.find(channel_id) == channels_.end()); | 516 CHECK(channels_.find(channel_id) == channels_.end()); |
| 506 channels_[channel_id] = channel; | 517 channels_[channel_id] = channel; |
| 507 pending_lazy_background_page_channels_.erase(channel_id); | 518 pending_lazy_background_page_channels_.erase(channel_id); |
| 508 } | 519 } |
| 509 | 520 |
| 510 void MessageService::CloseChannel(int port_id, | 521 void MessageService::CloseChannel(int port_id, |
| 511 const std::string& error_message) { | 522 const std::string& error_message) { |
| 512 // Note: The channel might be gone already, if the other side closed first. | 523 // Note: The channel might be gone already, if the other side closed first. |
| 513 int channel_id = GET_CHANNEL_ID(port_id); | 524 int channel_id = GET_CHANNEL_ID(port_id); |
| 525 pending_dispatches_to_platform_apps_.erase(channel_id); | |
| 526 | |
| 514 MessageChannelMap::iterator it = channels_.find(channel_id); | 527 MessageChannelMap::iterator it = channels_.find(channel_id); |
| 515 if (it == channels_.end()) { | 528 if (it == channels_.end()) { |
| 516 PendingLazyBackgroundPageChannelMap::iterator pending = | 529 PendingLazyBackgroundPageChannelMap::iterator pending = |
| 517 pending_lazy_background_page_channels_.find(channel_id); | 530 pending_lazy_background_page_channels_.find(channel_id); |
| 518 if (pending != pending_lazy_background_page_channels_.end()) { | 531 if (pending != pending_lazy_background_page_channels_.end()) { |
| 519 lazy_background_task_queue_->AddPendingTask( | 532 lazy_background_task_queue_->AddPendingTask( |
| 520 pending->second.first, pending->second.second, | 533 pending->second.first, pending->second.second, |
| 521 base::Bind(&MessageService::PendingLazyBackgroundPageCloseChannel, | 534 base::Bind(&MessageService::PendingLazyBackgroundPageCloseChannel, |
| 522 weak_factory_.GetWeakPtr(), port_id, error_message)); | 535 weak_factory_.GetWeakPtr(), port_id, error_message)); |
| 523 } | 536 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 542 } | 555 } |
| 543 | 556 |
| 544 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. | 557 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. |
| 545 channel->opener->DecrementLazyKeepaliveCount(); | 558 channel->opener->DecrementLazyKeepaliveCount(); |
| 546 channel->receiver->DecrementLazyKeepaliveCount(); | 559 channel->receiver->DecrementLazyKeepaliveCount(); |
| 547 | 560 |
| 548 delete channel_iter->second; | 561 delete channel_iter->second; |
| 549 channels_.erase(channel_iter); | 562 channels_.erase(channel_iter); |
| 550 } | 563 } |
| 551 | 564 |
| 552 void MessageService::PostMessage( | 565 void MessageService::PostMessage(int source_port_id, const Message& message) { |
| 553 int source_port_id, const Message& message) { | |
| 554 int channel_id = GET_CHANNEL_ID(source_port_id); | 566 int channel_id = GET_CHANNEL_ID(source_port_id); |
| 555 MessageChannelMap::iterator iter = channels_.find(channel_id); | 567 MessageChannelMap::iterator iter = channels_.find(channel_id); |
| 556 if (iter == channels_.end()) { | 568 if (iter == channels_.end()) { |
| 557 // If this channel is pending, queue up the PostMessage to run once | 569 // If this channel is pending, queue up the PostMessage to run once |
| 558 // the channel opens. | 570 // the channel opens. |
| 559 EnqueuePendingMessage(source_port_id, channel_id, message); | 571 EnqueuePendingMessage(source_port_id, channel_id, message); |
| 560 return; | 572 return; |
| 561 } | 573 } |
| 562 | 574 |
| 563 DispatchMessage(source_port_id, iter->second, message); | 575 DispatchMessage(source_port_id, iter->second, message); |
| 564 } | 576 } |
| 565 | 577 |
| 566 void MessageService::PostMessageFromNativeProcess(int port_id, | 578 void MessageService::PostMessageFromNativeProcess(int port_id, |
| 567 const std::string& message) { | 579 const std::string& message) { |
| 568 PostMessage(port_id, Message(message, false /* user_gesture */)); | 580 PostMessage(port_id, Message(message, false /* user_gesture */)); |
| 569 } | 581 } |
| 570 | 582 |
| 583 bool MessageService::CanPlatformAppAccessTab(const std::string app_id, | |
| 584 int tab_id) const { | |
| 585 for (PendingDispatchesToPlatformAppsMap::const_iterator it = | |
| 586 pending_dispatches_to_platform_apps_.begin(); | |
| 587 it != pending_dispatches_to_platform_apps_.end(); ++it) { | |
| 588 const std::pair<std::string, int>& entry = it->second; | |
| 589 if (entry.first == app_id && entry.second == tab_id) | |
| 590 return true; | |
| 591 } | |
| 592 return false; | |
| 593 } | |
| 594 | |
| 571 void MessageService::Observe(int type, | 595 void MessageService::Observe(int type, |
| 572 const content::NotificationSource& source, | 596 const content::NotificationSource& source, |
| 573 const content::NotificationDetails& details) { | 597 const content::NotificationDetails& details) { |
| 574 switch (type) { | 598 switch (type) { |
| 575 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 599 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
| 576 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 600 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
| 577 content::RenderProcessHost* renderer = | 601 content::RenderProcessHost* renderer = |
| 578 content::Source<content::RenderProcessHost>(source).ptr(); | 602 content::Source<content::RenderProcessHost>(source).ptr(); |
| 579 OnProcessClosed(renderer); | 603 OnProcessClosed(renderer); |
| 580 break; | 604 break; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 754 } | 778 } |
| 755 | 779 |
| 756 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, | 780 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, |
| 757 int port_id, | 781 int port_id, |
| 758 const std::string& error_message) { | 782 const std::string& error_message) { |
| 759 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); | 783 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); |
| 760 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); | 784 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); |
| 761 } | 785 } |
| 762 | 786 |
| 763 } // namespace extensions | 787 } // namespace extensions |
| OLD | NEW |