1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ 7 #pragma once 8 9 #include <map> 10 #include <set> 11 #include <string> 12 13 #include "base/memory/ref_counted.h" 14 #include "content/common/notification_observer.h" 15 #include "content/common/notification_registrar.h" 16 #include "ipc/ipc_message.h" 17 18 class GURL; 19 class Profile; 20 class TabContents; 21 22 // This class manages message and event passing between renderer processes. 23 // It maintains a list of processes that are listening to events and a set of 24 // open channels. 25 // 26 // Messaging works this way: 27 // - An extension-owned script context (like a toolstrip or a content script) 28 // adds an event listener to the "onConnect" event. 29 // - Another context calls "extension.connect()" to open a channel to the 30 // extension process, or an extension context calls "tabs.connect(tabId)" to 31 // open a channel to the content scripts for the given tab. The EMS notifies 32 // the target process/tab, which then calls the onConnect event in every 33 // context owned by the connecting extension in that process/tab. 34 // - Once the channel is established, either side can call postMessage to send 35 // a message to the opposite side of the channel, which may have multiple 36 // listeners. 37 // 38 // Terminology: 39 // channel: connection between two ports 40 // port: an IPC::Message::Sender interface and an optional routing_id (in the 41 // case that the port is a tab). The Sender is usually either a 42 // RenderProcessHost or a RenderViewHost. 43 44 // TODO(mpcomplete): Remove refcounting and make Profile the sole owner of this 45 // class. Then we can get rid of ProfileDestroyed(). 46 class ExtensionMessageService 47 : public base::RefCounted<ExtensionMessageService>, 48 public NotificationObserver { 49 public: 50 // A messaging channel. Note that the opening port can be the same as the 51 // receiver, if an extension toolstrip wants to talk to its tab (for example). 52 struct MessageChannel; 53 struct MessagePort; 54 55 // Javascript function name constants. 56 static const char kDispatchOnConnect[]; 57 static const char kDispatchOnDisconnect[]; 58 static const char kDispatchOnMessage[]; 59 60 // Allocates a pair of port ids. 61 // NOTE: this can be called from any thread. 62 static void AllocatePortIdPair(int* port1, int* port2); 63 64 explicit ExtensionMessageService(Profile* profile); 65 66 // Notification that our owning profile is going away. 67 void DestroyingProfile(); 68 69 // Given an extension's ID, opens a channel between the given renderer "port" 70 // and every listening context owned by that extension. |channel_name| is 71 // an optional identifier for use by extension developers. 72 void OpenChannelToExtension( 73 int source_process_id, int source_routing_id, int receiver_port_id, 74 const std::string& source_extension_id, 75 const std::string& target_extension_id, 76 const std::string& channel_name); 77 78 // Same as above, but opens a channel to the tab with the given ID. Messages 79 // are restricted to that tab, so if there are multiple tabs in that process, 80 // only the targeted tab will receive messages. 81 void OpenChannelToTab( 82 int source_process_id, int source_routing_id, int receiver_port_id, 83 int tab_id, const std::string& extension_id, 84 const std::string& channel_name); 85 86 // Given an extension ID, opens a channel between the given 87 // automation "port" or DevTools service and that extension. the 88 // channel will be open to the extension process hosting the 89 // background page and tool strip. 90 // 91 // Returns a port ID to be used for posting messages between the 92 // processes, or -1 if the extension doesn't exist. 93 int OpenSpecialChannelToExtension( 94 const std::string& extension_id, const std::string& channel_name, 95 const std::string& tab_json, IPC::Message::Sender* source); 96 97 // Given an extension ID, opens a channel between the given DevTools 98 // service and the content script for that extension running in the 99 // designated tab. 100 // 101 // Returns a port ID identifying the DevTools end of the channel, to 102 // be used for posting messages. May return -1 on failure, although 103 // the code doesn't detect whether the extension actually exists. 104 int OpenSpecialChannelToTab( 105 const std::string& extension_id, const std::string& channel_name, 106 TabContents* target_tab_contents, IPC::Message::Sender* source); 107 108 // Closes the message channel associated with the given port, and notifies 109 // the other side. 110 void CloseChannel(int port_id); 111 112 // Sends a message from a renderer to the given port. 113 void PostMessageFromRenderer(int port_id, const std::string& message); 114 115 private: 116 friend class base::RefCounted<ExtensionMessageService>; 117 friend class MockExtensionMessageService; 118 119 // A map of channel ID to its channel object. 120 typedef std::map<int, MessageChannel*> MessageChannelMap; 121 122 virtual ~ExtensionMessageService(); 123 124 // Common among Open(Special)Channel* variants. 125 bool OpenChannelImpl( 126 IPC::Message::Sender* source, 127 const std::string& tab_json, 128 const MessagePort& receiver, int receiver_port_id, 129 const std::string& source_extension_id, 130 const std::string& target_extension_id, 131 const std::string& channel_name); 132 133 void CloseChannelImpl(MessageChannelMap::iterator channel_iter, int port_id, 134 bool notify_other_port); 135 136 // NotificationObserver interface. 137 virtual void Observe(NotificationType type, 138 const NotificationSource& source, 139 const NotificationDetails& details); 140 141 // An IPC sender that might be in our list of channels has closed. 142 void OnSenderClosed(IPC::Message::Sender* sender); 143 144 Profile* profile_; 145 146 NotificationRegistrar registrar_; 147 148 MessageChannelMap channels_; 149 150 DISALLOW_COPY_AND_ASSIGN(ExtensionMessageService); 151 }; 152 153 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ 154