15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/messaging/message_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomic_sequence_num.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/lazy_instance.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/metrics/histogram.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/messaging/extension_message_port.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/messaging/native_message_port.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_host.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_process_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/lazy_background_task_queue.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/process_map.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/background_info.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_messages.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/incognito_handler.h"
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
374311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "content/public/browser/render_widget_host.h"
384311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "content/public/browser/render_widget_host_view.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/site_instance.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::SiteInstance;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since we have 2 ports for every channel, we just index channels by half the
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// port ID.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET_CHANNEL_ID(port_id) ((port_id) / 2)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Port1 is always even, port2 is always odd.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Change even to odd and vice versa, to get the other side of a given channel.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kReceivingEndDoesntExistError[] =
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "Could not establish connection. Receiving end does not exist.";
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kMissingPermissionError[] =
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "Access to native messaging requires nativeMessaging permission.";
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kNativeMessagingNotSupportedError[] =
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "Native Messaging is not supported on this platform.";
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct MessageService::MessageChannel {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MessagePort> opener;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MessagePort> receiver;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct MessageService::OpenChannelParams {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* source;
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::DictionaryValue source_tab;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MessagePort> receiver;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int receiver_port_id;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string source_extension_id;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string target_extension_id;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL source_url;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_name;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes ownership of receiver.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenChannelParams(content::RenderProcessHost* source,
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    scoped_ptr<base::DictionaryValue> source_tab,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    MessagePort* receiver,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int receiver_port_id,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& source_extension_id,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& target_extension_id,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    const GURL& source_url,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& channel_name)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : source(source),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        receiver(receiver),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        receiver_port_id(receiver_port_id),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source_extension_id(source_extension_id),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        target_extension_id(target_extension_id),
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        source_url(source_url),
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        channel_name(channel_name) {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (source_tab)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this->source_tab.Swap(source_tab.get());
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenChannelParams);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::StaticAtomicSequenceNumber g_next_channel_id;
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic base::StaticAtomicSequenceNumber g_channel_id_overflow_count;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static content::RenderProcessHost* GetExtensionProcess(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile, const std::string& extension_id) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SiteInstance* site_instance =
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->process_manager()->
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetSiteInstanceForURL(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Extension::GetBaseURLFromExtensionId(extension_id));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!site_instance->HasProcess())
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return site_instance->GetProcess();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::RenderProcessHost*
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageService::MessagePort::GetRenderProcessHost() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::AllocatePortIdPair(int* port1, int* port2) {
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  unsigned channel_id =
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2);
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (channel_id == 0) {
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int overflow_count = g_channel_id_overflow_count.GetNext();
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (overflow_count > 0)
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      UMA_HISTOGRAM_BOOLEAN("Extensions.AllocatePortIdPairOverflow", true);
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  unsigned port1_id = channel_id * 2;
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  unsigned port2_id = channel_id * 2 + 1;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity checks to make sure our channel<->port converters are correct.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IS_OPENER_PORT_ID(port1_id));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GET_CHANNEL_ID(port1_id) == channel_id);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port1 = port1_id;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port2 = port2_id;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)MessageService::MessageService(Profile* profile)
161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    : lazy_background_task_queue_(
162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          ExtensionSystem::Get(profile)->lazy_background_task_queue()),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_factory_(this) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllBrowserContextsAndSources());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageService::~MessageService() {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channels_.clear();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)static base::LazyInstance<ProfileKeyedAPIFactory<MessageService> >
176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)g_factory = LAZY_INSTANCE_INITIALIZER;
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ProfileKeyedAPIFactory<MessageService>* MessageService::GetFactoryInstance() {
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return &g_factory.Get();
181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)MessageService* MessageService::Get(Profile* profile) {
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return ProfileKeyedAPIFactory<MessageService>::GetForProfile(profile);
186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::OpenChannelToExtension(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_process_id, int source_routing_id, int receiver_port_id,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& source_extension_id,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& target_extension_id,
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& source_url,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& channel_name) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* source =
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost::FromID(source_process_id);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!source)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const Extension* target_extension = ExtensionSystem::Get(profile)->
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extension_service()->extensions()->GetByID(target_extension_id);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!target_extension) {
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DispatchOnDisconnect(
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        source, receiver_port_id, kReceivingEndDoesntExistError);
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ExtensionService* extension_service =
209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->extension_service();
210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (profile->IsOffTheRecord() &&
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !extension_service->IsIncognitoEnabled(target_extension_id)) {
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DispatchOnDisconnect(
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        source, receiver_port_id, kReceivingEndDoesntExistError);
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (source_extension_id != target_extension_id) {
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // It's an external connection. Check the externally_connectable manifest
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // key if it's present. If it's not, we allow connection from any extension
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // but not webpages.
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ExternallyConnectableInfo* externally_connectable =
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        static_cast<ExternallyConnectableInfo*>(
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            target_extension->GetManifestData(
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                extension_manifest_keys::kExternallyConnectable));
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool is_externally_connectable = false;
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (externally_connectable) {
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (source_extension_id.empty()) {
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // No source extension ID so the source was a web page. Check that the
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // URL matches.
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        is_externally_connectable =
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            externally_connectable->matches.MatchesURL(source_url);
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else {
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // Source extension ID so the source was an extension. Check that the
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // extension matches.
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        is_externally_connectable =
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            externally_connectable->IdCanConnect(source_extension_id);
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Default behaviour. Any extension, no webpages.
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      is_externally_connectable = !source_extension_id.empty();
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!is_externally_connectable) {
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Important: use kReceivingEndDoesntExistError here so that we don't
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // leak information about this extension to callers. This way it's
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // indistinguishable from the extension just not existing.
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DispatchOnDisconnect(
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          source, receiver_port_id, kReceivingEndDoesntExistError);
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: we use the source's profile here. If the source is an incognito
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process, we will use the incognito EPM to find the right extension process,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which depends on whether the extension uses spanning or split mode.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePort* receiver = new ExtensionMessagePort(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_extension_id);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* source_contents = tab_util::GetWebContentsByID(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source_process_id, source_routing_id);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Include info about the opener's tab (if it was a tab).
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::DictionaryValue> source_tab;
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL source_url_for_tab;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) {
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Platform apps can be sent messages, but don't have a Tab concept.
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!target_extension->is_platform_app())
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents));
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    source_url_for_tab = source_url;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OpenChannelParams* params = new OpenChannelParams(source,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    source_tab.Pass(),
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    receiver,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    receiver_port_id,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    source_extension_id,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    target_extension_id,
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    source_url_for_tab,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    channel_name);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The target might be a lazy background page. In that case, we have to check
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if it is loaded and ready, and if not, queue up the task and load the
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // page.
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (MaybeAddPendingOpenChannelTask(profile, target_extension, params)) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OpenChannelImpl(make_scoped_ptr(params));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::OpenChannelToNativeApp(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_process_id,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_routing_id,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int receiver_port_id,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& source_extension_id,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& native_app_name) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* source =
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost::FromID(source_process_id);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!source)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionService* extension_service =
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->extension_service();
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_permission = false;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extension_service) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension =
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_service->GetExtensionById(source_extension_id, false);
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    has_permission = extension && extension->HasAPIPermission(
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        APIPermission::kNativeMessaging);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!has_permission) {
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DispatchOnDisconnect(source, receiver_port_id, kMissingPermissionError);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MessageChannel> channel(new MessageChannel());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 source_extension_id));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3264311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // Get handle of the native view and pass it to the native messaging host.
3274311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  gfx::NativeView native_view =
3284311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      content::RenderWidgetHost::FromID(source_process_id, source_routing_id)->
3294311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch          GetView()->GetNativeView();
3304311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<NativeMessageProcessHost> native_process =
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NativeMessageProcessHost::Create(
3334311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch          native_view,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::WeakPtr<NativeMessageProcessHost::Client>(
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              weak_factory_.GetWeakPtr()),
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          source_extension_id, native_app_name, receiver_port_id);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Abandon the channel.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!native_process.get()) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create native process.";
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DispatchOnDisconnect(
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        source, receiver_port_id, kReceivingEndDoesntExistError);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->receiver.reset(new NativeMessagePort(native_process.release()));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep the opener alive until the channel is closed.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->opener->IncrementLazyKeepaliveCount();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChannel(channel.release(), receiver_port_id);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else  // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DispatchOnDisconnect(
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      source, receiver_port_id, kNativeMessagingNotSupportedError);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::OpenChannelToTab(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_process_id, int source_routing_id, int receiver_port_id,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tab_id, const std::string& extension_id,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& channel_name) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* source =
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost::FromID(source_process_id);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!source)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* contents = NULL;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MessagePort> receiver;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ExtensionTabUtil::GetTabById(tab_id, profile, true,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   NULL, NULL, &contents, NULL)) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    receiver.reset(new ExtensionMessagePort(
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contents->GetRenderProcessHost(),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contents->GetRenderViewHost()->GetRoutingID(),
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_id));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (contents && contents->GetController().NeedsReload()) {
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The tab isn't loaded yet. Don't attempt to connect.
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DispatchOnDisconnect(
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        source, receiver_port_id, kReceivingEndDoesntExistError);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<OpenChannelParams> params(new OpenChannelParams(
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        source,
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        scoped_ptr<base::DictionaryValue>(),  // Source tab doesn't make sense
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                              // for opening to tabs.
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        receiver.release(),
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        receiver_port_id,
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extension_id,
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extension_id,
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL(),  // Source URL doesn't make sense for opening to tabs.
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        channel_name));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenChannelImpl(params.Pass());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!params->source)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Closed while in flight.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params->receiver || !params->receiver->GetRenderProcessHost()) {
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DispatchOnDisconnect(params->source,
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         params->receiver_port_id,
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         kReceivingEndDoesntExistError);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add extra paranoid CHECKs, since we have crash reports of this being NULL.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://code.google.com/p/chromium/issues/detail?id=19067
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(params->receiver->GetRenderProcessHost());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageChannel* channel(new MessageChannel);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->opener.reset(new ExtensionMessagePort(params->source,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 MSG_ROUTING_CONTROL,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 params->source_extension_id));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->receiver.reset(params->receiver.release());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(channel->receiver->GetRenderProcessHost());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChannel(channel, params->receiver_port_id);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(channel->receiver->GetRenderProcessHost());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the connect event to the receiver.  Give it the opener's port ID (the
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // opener has the opposite port ID).
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->receiver->DispatchOnConnect(params->receiver_port_id,
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       params->channel_name,
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       params->source_tab,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       params->source_extension_id,
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       params->target_extension_id,
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       params->source_url);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep both ends of the channel alive until the channel is closed.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->opener->IncrementLazyKeepaliveCount();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->receiver->IncrementLazyKeepaliveCount();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channel_id = GET_CHANNEL_ID(receiver_port_id);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(channels_.find(channel_id) == channels_.end());
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channels_[channel_id] = channel;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_channels_.erase(channel_id);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageService::CloseChannel(int port_id,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& error_message) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: The channel might be gone already, if the other side closed first.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channel_id = GET_CHANNEL_ID(port_id);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageChannelMap::iterator it = channels_.find(channel_id);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == channels_.end()) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingChannelMap::iterator pending = pending_channels_.find(channel_id);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending != pending_channels_.end()) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lazy_background_task_queue_->AddPendingTask(
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pending->second.first, pending->second.second,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&MessageService::PendingCloseChannel,
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     weak_factory_.GetWeakPtr(), port_id, error_message));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CloseChannelImpl(it, port_id, error_message, true);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::CloseChannelImpl(
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageChannelMap::iterator channel_iter,
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int closing_port_id,
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& error_message,
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool notify_other_port) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageChannel* channel = channel_iter->second;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify the other side.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (notify_other_port) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessagePort* port = IS_OPENER_PORT_ID(closing_port_id) ?
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel->receiver.get() : channel->opener.get();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    port->DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(closing_port_id),
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               error_message);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->opener->DecrementLazyKeepaliveCount();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel->receiver->DecrementLazyKeepaliveCount();
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete channel_iter->second;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channels_.erase(channel_iter);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::PostMessage(
488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int source_port_id, const std::string& message) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channel_id = GET_CHANNEL_ID(source_port_id);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageChannelMap::iterator iter = channels_.find(channel_id);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == channels_.end()) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this channel is pending, queue up the PostMessage to run once
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the channel opens.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingChannelMap::iterator pending = pending_channels_.find(channel_id);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending != pending_channels_.end()) {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lazy_background_task_queue_->AddPendingTask(
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pending->second.first, pending->second.second,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&MessageService::PendingPostMessage,
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     weak_factory_.GetWeakPtr(), source_port_id, message));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Figure out which port the ID corresponds to.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ?
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter->second->opener.get() : iter->second->receiver.get();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  port->DispatchOnMessage(message, dest_port_id);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MessageService::PostMessageFromNativeProcess(int port_id,
513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                  const std::string& message) {
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PostMessage(port_id, message);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::Observe(int type,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationSource& source,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const content::NotificationDetails& details) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost* renderer =
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::RenderProcessHost>(source).ptr();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnProcessClosed(renderer);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::OnProcessClosed(content::RenderProcessHost* process) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close any channels that share this renderer.  We notify the opposite
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // port that his pair has closed.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (MessageChannelMap::iterator it = channels_.begin();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != channels_.end(); ) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageChannelMap::iterator current = it++;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderProcessHost* opener_process =
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current->second->opener->GetRenderProcessHost();
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderProcessHost* receiver_process =
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current->second->receiver->GetRenderProcessHost();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only notify the other side if it has a different porocess host.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool notify_other_port = opener_process && receiver_process &&
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        opener_process != receiver_process;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (opener_process == process) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first),
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       std::string(), notify_other_port);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (receiver_process == process) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first),
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       std::string(), notify_other_port);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageService::MaybeAddPendingOpenChannelTask(
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Extension* extension,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenChannelParams* params) {
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!BackgroundInfo::HasLazyBackgroundPage(extension))
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the extension uses spanning incognito mode, make sure we're always
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // using the original profile since that is what the extension process
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // will use.
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IncognitoInfo::IsSplitMode(extension))
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile = profile->GetOriginalProfile();
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!lazy_background_task_queue_->ShouldEnqueueTask(profile, extension))
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] =
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PendingChannel(profile, extension->id());
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<OpenChannelParams> scoped_params(params);
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  lazy_background_task_queue_->AddPendingTask(profile, extension->id(),
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&MessageService::PendingOpenChannel,
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 weak_factory_.GetWeakPtr(), base::Passed(&scoped_params),
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 params->source->GetID()));
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageService::PendingOpenChannel(scoped_ptr<OpenChannelParams> params,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int source_process_id,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        ExtensionHost* host) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!host)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // TODO(mpcomplete): notify source of disconnect?
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Re-lookup the source process since it may no longer be valid.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* source =
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost::FromID(source_process_id);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!source)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->source = source;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->receiver.reset(new ExtensionMessagePort(host->render_process_host(),
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  MSG_ROUTING_CONTROL,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  params->target_extension_id));
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenChannelImpl(params.Pass());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source,
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          int port_id,
607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          const std::string& error_message) {
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, "");
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message);
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
613