Index: chrome/browser/extensions/extension_message_service.cc |
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc |
deleted file mode 100644 |
index d9f547740f78cec3fe2a58643b9dd7100dd4cce0..0000000000000000000000000000000000000000 |
--- a/chrome/browser/extensions/extension_message_service.cc |
+++ /dev/null |
@@ -1,472 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/extensions/extension_message_service.h" |
- |
-#include "base/atomic_sequence_num.h" |
-#include "base/bind.h" |
-#include "base/callback.h" |
-#include "base/json/json_writer.h" |
-#include "base/stl_util.h" |
-#include "base/values.h" |
-#include "chrome/browser/extensions/extension_host.h" |
-#include "chrome/browser/extensions/extension_process_manager.h" |
-#include "chrome/browser/extensions/extension_service.h" |
-#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/process_map.h" |
-#include "chrome/browser/profiles/profile.h" |
-#include "chrome/browser/tab_contents/tab_util.h" |
-#include "chrome/browser/ui/tab_contents/tab_contents.h" |
-#include "chrome/common/chrome_notification_types.h" |
-#include "chrome/common/extensions/extension.h" |
-#include "chrome/common/extensions/extension_messages.h" |
-#include "chrome/common/view_type.h" |
-#include "content/public/browser/notification_service.h" |
-#include "content/public/browser/render_process_host.h" |
-#include "content/public/browser/render_view_host.h" |
-#include "content/public/browser/site_instance.h" |
-#include "content/public/browser/web_contents.h" |
- |
-using content::SiteInstance; |
-using content::WebContents; |
- |
-// Since we have 2 ports for every channel, we just index channels by half the |
-// port ID. |
-#define GET_CHANNEL_ID(port_id) ((port_id) / 2) |
-#define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) |
-#define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) |
- |
-// Port1 is always even, port2 is always odd. |
-#define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) |
- |
-// Change even to odd and vice versa, to get the other side of a given channel. |
-#define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) |
- |
-struct ExtensionMessageService::MessagePort { |
- content::RenderProcessHost* process; |
- int routing_id; |
- std::string extension_id; |
- void* background_host_ptr; // used in IncrementLazyKeepaliveCount |
- |
- MessagePort() |
- : process(NULL), |
- routing_id(MSG_ROUTING_CONTROL), |
- background_host_ptr(NULL) {} |
- 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) {} |
-}; |
- |
-struct ExtensionMessageService::MessageChannel { |
- ExtensionMessageService::MessagePort opener; |
- ExtensionMessageService::MessagePort receiver; |
-}; |
- |
-struct ExtensionMessageService::OpenChannelParams { |
- content::RenderProcessHost* source; |
- std::string tab_json; |
- MessagePort receiver; |
- int receiver_port_id; |
- std::string source_extension_id; |
- std::string target_extension_id; |
- std::string channel_name; |
- |
- OpenChannelParams(content::RenderProcessHost* source, |
- const std::string& tab_json, |
- const MessagePort& receiver, |
- int receiver_port_id, |
- const std::string& source_extension_id, |
- const std::string& target_extension_id, |
- const std::string& channel_name) |
- : source(source), |
- tab_json(tab_json), |
- receiver(receiver), |
- receiver_port_id(receiver_port_id), |
- source_extension_id(source_extension_id), |
- target_extension_id(target_extension_id), |
- channel_name(channel_name) {} |
-}; |
- |
-namespace { |
- |
-static base::StaticAtomicSequenceNumber g_next_channel_id; |
- |
-static void DispatchOnConnect(const ExtensionMessageService::MessagePort& port, |
- int dest_port_id, |
- const std::string& channel_name, |
- const std::string& tab_json, |
- const std::string& source_extension_id, |
- const std::string& target_extension_id) { |
- port.process->Send(new ExtensionMsg_DispatchOnConnect( |
- port.routing_id, dest_port_id, channel_name, |
- tab_json, source_extension_id, target_extension_id)); |
-} |
- |
-static void DispatchOnDisconnect( |
- const ExtensionMessageService::MessagePort& port, int source_port_id, |
- bool connection_error) { |
- port.process->Send(new ExtensionMsg_DispatchOnDisconnect( |
- port.routing_id, source_port_id, connection_error)); |
-} |
- |
-static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, |
- const std::string& message, int target_port_id) { |
- port.process->Send(new ExtensionMsg_DeliverMessage( |
- port.routing_id, target_port_id, message)); |
-} |
- |
-static content::RenderProcessHost* GetExtensionProcess( |
- Profile* profile, const std::string& extension_id) { |
- SiteInstance* site_instance = |
- profile->GetExtensionProcessManager()->GetSiteInstanceForURL( |
- extensions::Extension::GetBaseURLFromExtensionId(extension_id)); |
- |
- if (!site_instance->HasProcess()) |
- return NULL; |
- |
- return site_instance->GetProcess(); |
-} |
- |
-static void IncrementLazyKeepaliveCount( |
- ExtensionMessageService::MessagePort* port) { |
- Profile* profile = |
- Profile::FromBrowserContext(port->process->GetBrowserContext()); |
- ExtensionProcessManager* pm = |
- extensions::ExtensionSystem::Get(profile)->process_manager(); |
- ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id); |
- if (host && host->extension()->has_lazy_background_page()) |
- pm->IncrementLazyKeepaliveCount(host->extension()); |
- |
- // Keep track of the background host, so when we decrement, we only do so if |
- // the host hasn't reloaded. |
- port->background_host_ptr = host; |
-} |
- |
-static void DecrementLazyKeepaliveCount( |
- ExtensionMessageService::MessagePort* port) { |
- Profile* profile = |
- Profile::FromBrowserContext(port->process->GetBrowserContext()); |
- ExtensionProcessManager* pm = |
- extensions::ExtensionSystem::Get(profile)->process_manager(); |
- ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id); |
- if (host && host == port->background_host_ptr) |
- pm->DecrementLazyKeepaliveCount(host->extension()); |
-} |
- |
-} // namespace |
- |
-// static |
-void ExtensionMessageService::AllocatePortIdPair(int* port1, int* port2) { |
- int channel_id = g_next_channel_id.GetNext(); |
- int port1_id = channel_id * 2; |
- int port2_id = channel_id * 2 + 1; |
- |
- // Sanity checks to make sure our channel<->port converters are correct. |
- DCHECK(IS_OPENER_PORT_ID(port1_id)); |
- DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); |
- DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); |
- DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); |
- DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); |
- DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); |
- DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); |
- |
- *port1 = port1_id; |
- *port2 = port2_id; |
-} |
- |
-ExtensionMessageService::ExtensionMessageService( |
- extensions::LazyBackgroundTaskQueue* queue) |
- : lazy_background_task_queue_(queue) { |
- registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
- content::NotificationService::AllBrowserContextsAndSources()); |
- registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
- content::NotificationService::AllBrowserContextsAndSources()); |
-} |
- |
-ExtensionMessageService::~ExtensionMessageService() { |
- STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); |
- channels_.clear(); |
-} |
- |
-void ExtensionMessageService::OpenChannelToExtension( |
- int source_process_id, int source_routing_id, int receiver_port_id, |
- const std::string& source_extension_id, |
- const std::string& target_extension_id, |
- const std::string& channel_name) { |
- 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, target_extension_id), |
- MSG_ROUTING_CONTROL, |
- target_extension_id); |
- 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); |
- } |
- |
- OpenChannelParams params(source, tab_json, receiver, receiver_port_id, |
- source_extension_id, target_extension_id, |
- channel_name); |
- |
- // The target might be a lazy background page. In that case, we have to check |
- // if it is loaded and ready, and if not, queue up the task and load the |
- // page. |
- if (MaybeAddPendingOpenChannelTask(profile, params)) |
- return; |
- |
- OpenChannelImpl(params); |
-} |
- |
-void ExtensionMessageService::OpenChannelToTab( |
- int source_process_id, int source_routing_id, int receiver_port_id, |
- int tab_id, const std::string& extension_id, |
- const std::string& channel_name) { |
- content::RenderProcessHost* source = |
- content::RenderProcessHost::FromID(source_process_id); |
- if (!source) |
- return; |
- Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); |
- |
- TabContents* contents = NULL; |
- MessagePort receiver; |
- if (ExtensionTabUtil::GetTabById(tab_id, profile, true, |
- NULL, NULL, &contents, NULL)) { |
- receiver.process = contents->web_contents()->GetRenderProcessHost(); |
- receiver.routing_id = |
- contents->web_contents()->GetRenderViewHost()->GetRoutingID(); |
- receiver.extension_id = extension_id; |
- } |
- |
- if (contents && contents->web_contents()->GetController().NeedsReload()) { |
- // The tab isn't loaded yet. Don't attempt to connect. Treat this as a |
- // disconnect. |
- DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL, extension_id), |
- GET_OPPOSITE_PORT_ID(receiver_port_id), true); |
- return; |
- } |
- |
- 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); |
- } |
- |
- OpenChannelParams params(source, tab_json, receiver, receiver_port_id, |
- extension_id, extension_id, channel_name); |
- OpenChannelImpl(params); |
-} |
- |
-bool ExtensionMessageService::OpenChannelImpl(const OpenChannelParams& params) { |
- if (!params.source) |
- return false; // Closed while in flight. |
- |
- if (!params.receiver.process) { |
- // Treat it as a disconnect. |
- DispatchOnDisconnect(MessagePort(params.source, MSG_ROUTING_CONTROL, ""), |
- GET_OPPOSITE_PORT_ID(params.receiver_port_id), true); |
- return false; |
- } |
- |
- // Add extra paranoid CHECKs, since we have crash reports of this being NULL. |
- // http://code.google.com/p/chromium/issues/detail?id=19067 |
- CHECK(params.receiver.process); |
- |
- MessageChannel* channel(new MessageChannel); |
- channel->opener = MessagePort(params.source, MSG_ROUTING_CONTROL, |
- params.source_extension_id); |
- channel->receiver = params.receiver; |
- |
- CHECK(params.receiver.process); |
- |
- int channel_id = GET_CHANNEL_ID(params.receiver_port_id); |
- CHECK(channels_.find(channel_id) == channels_.end()); |
- channels_[channel_id] = channel; |
- pending_channels_.erase(channel_id); |
- |
- CHECK(params.receiver.process); |
- |
- // Send the connect event to the receiver. Give it the opener's port ID (the |
- // opener has the opposite port ID). |
- DispatchOnConnect(params.receiver, params.receiver_port_id, |
- params.channel_name, params.tab_json, |
- params.source_extension_id, params.target_extension_id); |
- |
- // Keep both ends of the channel alive until the channel is closed. |
- IncrementLazyKeepaliveCount(&channel->opener); |
- IncrementLazyKeepaliveCount(&channel->receiver); |
- return true; |
-} |
- |
-void ExtensionMessageService::CloseChannel(int port_id, bool connection_error) { |
- // Note: The channel might be gone already, if the other side closed first. |
- int channel_id = GET_CHANNEL_ID(port_id); |
- MessageChannelMap::iterator it = channels_.find(channel_id); |
- if (it == channels_.end()) { |
- PendingChannelMap::iterator pending = pending_channels_.find(channel_id); |
- if (pending != pending_channels_.end()) { |
- lazy_background_task_queue_->AddPendingTask( |
- pending->second.first, pending->second.second, |
- base::Bind(&ExtensionMessageService::PendingCloseChannel, |
- base::Unretained(this), port_id, connection_error)); |
- } |
- return; |
- } |
- CloseChannelImpl(it, port_id, connection_error, true); |
-} |
- |
-void ExtensionMessageService::CloseChannelImpl( |
- MessageChannelMap::iterator channel_iter, int closing_port_id, |
- bool connection_error, bool notify_other_port) { |
- MessageChannel* channel = channel_iter->second; |
- |
- // Notify the other side. |
- 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); |
- } |
- |
- // Balance the addrefs in OpenChannelImpl. |
- DecrementLazyKeepaliveCount(&channel->opener); |
- DecrementLazyKeepaliveCount(&channel->receiver); |
- |
- delete channel_iter->second; |
- channels_.erase(channel_iter); |
-} |
- |
-void ExtensionMessageService::PostMessageFromRenderer( |
- int source_port_id, const std::string& message) { |
- int channel_id = GET_CHANNEL_ID(source_port_id); |
- MessageChannelMap::iterator iter = channels_.find(channel_id); |
- if (iter == channels_.end()) { |
- // If this channel is pending, queue up the PostMessage to run once |
- // the channel opens. |
- PendingChannelMap::iterator pending = pending_channels_.find(channel_id); |
- if (pending != pending_channels_.end()) { |
- lazy_background_task_queue_->AddPendingTask( |
- pending->second.first, pending->second.second, |
- base::Bind(&ExtensionMessageService::PendingPostMessage, |
- base::Unretained(this), source_port_id, message)); |
- } |
- return; |
- } |
- |
- // Figure out which port the ID corresponds to. |
- int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); |
- const MessagePort& port = IS_OPENER_PORT_ID(dest_port_id) ? |
- iter->second->opener : iter->second->receiver; |
- |
- DispatchOnMessage(port, message, dest_port_id); |
-} |
- |
-void ExtensionMessageService::Observe( |
- int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- switch (type) { |
- case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
- case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
- content::RenderProcessHost* renderer = |
- content::Source<content::RenderProcessHost>(source).ptr(); |
- OnProcessClosed(renderer); |
- break; |
- } |
- default: |
- NOTREACHED(); |
- return; |
- } |
-} |
- |
-void ExtensionMessageService::OnProcessClosed( |
- content::RenderProcessHost* process) { |
- // Close any channels that share this renderer. We notify the opposite |
- // port that his pair has closed. |
- for (MessageChannelMap::iterator it = channels_.begin(); |
- it != channels_.end(); ) { |
- MessageChannelMap::iterator current = it++; |
- // If both sides are the same renderer, and it is closing, there is no |
- // "other" port, so there's no need to notify it. |
- bool notify_other_port = |
- current->second->opener.process != current->second->receiver.process; |
- |
- if (current->second->opener.process == process) { |
- CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), |
- false, notify_other_port); |
- } else if (current->second->receiver.process == process) { |
- CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), |
- false, notify_other_port); |
- } |
- } |
-} |
- |
-bool ExtensionMessageService::MaybeAddPendingOpenChannelTask( |
- Profile* profile, |
- const OpenChannelParams& params) { |
- ExtensionService* service = profile->GetExtensionService(); |
- const std::string& extension_id = params.target_extension_id; |
- const extensions::Extension* extension = service->extensions()->GetByID( |
- extension_id); |
- if (extension && extension->has_lazy_background_page()) { |
- // If the extension uses spanning incognito mode, make sure we're always |
- // using the original profile since that is what the extension process |
- // will use. |
- if (!extension->incognito_split_mode()) |
- profile = profile->GetOriginalProfile(); |
- |
- if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) { |
- lazy_background_task_queue_->AddPendingTask(profile, extension_id, |
- base::Bind(&ExtensionMessageService::PendingOpenChannel, |
- base::Unretained(this), params, params.source->GetID())); |
- pending_channels_[GET_CHANNEL_ID(params.receiver_port_id)] = |
- PendingChannel(profile, extension_id); |
- return true; |
- } |
- } |
- |
- return false; |
-} |
- |
-void ExtensionMessageService::PendingOpenChannel( |
- const OpenChannelParams& params_in, |
- int source_process_id, |
- ExtensionHost* host) { |
- if (!host) |
- return; // TODO(mpcomplete): notify source of disconnect? |
- |
- // Re-lookup the source process since it may no longer be valid. |
- OpenChannelParams params = params_in; |
- params.source = content::RenderProcessHost::FromID(source_process_id); |
- if (!params.source) |
- return; |
- |
- params.receiver = MessagePort(host->render_process_host(), |
- MSG_ROUTING_CONTROL, |
- params.target_extension_id); |
- OpenChannelImpl(params); |
-} |