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