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