OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 | 7 |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/linked_ptr.h" | 12 #include "base/linked_ptr.h" |
13 #include "base/lock.h" | 13 #include "base/lock.h" |
| 14 #include "base/ref_counted.h" |
14 #include "chrome/common/ipc_message.h" | 15 #include "chrome/common/ipc_message.h" |
15 #include "chrome/common/notification_registrar.h" | 16 #include "chrome/common/notification_registrar.h" |
16 | 17 |
17 class MessageLoop; | 18 class MessageLoop; |
| 19 class Profile; |
18 class RenderProcessHost; | 20 class RenderProcessHost; |
19 class ResourceMessageFilter; | 21 class ResourceMessageFilter; |
20 class URLRequestContext; | 22 class URLRequestContext; |
21 | 23 |
22 // This class manages message and event passing between renderer processes. | 24 // This class manages message and event passing between renderer processes. |
23 // It maintains a list of processes that are listening to events (including | 25 // It maintains a list of processes that are listening to events and a set of |
24 // messaging events), as well as a set of open channels. | 26 // open channels. |
25 // | 27 // |
26 // Messaging works this way: | 28 // Messaging works this way: |
27 // - An extension-owned script context (like a toolstrip or a content script) | 29 // - An extension-owned script context (like a toolstrip or a content script) |
28 // adds an event listener to the "onConnect" event. We keep track here of a | 30 // adds an event listener to the "onConnect" event. |
29 // list of "listeners" that registered interest in receiving extension | 31 // - Another context calls "extension.connect()" to open a channel to the |
30 // messages. | 32 // extension process, or an extension context calls "tabs.connect(tabId)" to |
31 // - Another context calls "connect()" to open a channel to every listener | 33 // open a channel to the content scripts for the given tab. The EMS notifies |
32 // owned by the same extension. This is a broadcast event, so every listener | 34 // the target process/tab, which then calls the onConnect event in every |
33 // will get notified. | 35 // context owned by the connecting extension in that process/tab. |
34 // - 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 |
35 // 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 |
36 // listeners. | 38 // listeners. |
37 // | 39 // |
38 // Terminology: | 40 // Terminology: |
39 // channel: connection between two ports (one side of which can have multiple | 41 // channel: connection between two ports |
40 // listeners) | 42 // port: an IPC::Message::Sender interface and an optional routing_id (in the |
41 // port: one or more IPC::Message::Sender interfaces through which we | 43 // case that the port is a tab). The Sender is usually either a |
42 // communicate to process(es). These are generally RenderProcessHosts. | 44 // RenderProcessHost or a RenderViewHost. |
43 class ExtensionMessageService : public NotificationObserver { | 45 class ExtensionMessageService : |
| 46 public base::RefCountedThreadSafe<ExtensionMessageService>, |
| 47 public NotificationObserver { |
44 public: | 48 public: |
45 // Javascript function name constants. | 49 // Javascript function name constants. |
46 static const char kDispatchOnConnect[]; | 50 static const char kDispatchOnConnect[]; |
47 static const char kDispatchOnDisconnect[]; | 51 static const char kDispatchOnDisconnect[]; |
48 static const char kDispatchOnMessage[]; | 52 static const char kDispatchOnMessage[]; |
49 static const char kDispatchEvent[]; | 53 static const char kDispatchEvent[]; |
50 static const char kDispatchError[]; | 54 static const char kDispatchError[]; |
51 | 55 |
52 // Returns the message service for the given context. Messages can only | 56 // A messaging channel. Note that the opening port can be the same as the |
53 // be sent within a single context. | 57 // receiver, if an extension toolstrip wants to talk to its tab (for example). |
54 static ExtensionMessageService* GetInstance(URLRequestContext* context); | 58 struct MessageChannel; |
55 | 59 struct MessagePort; |
56 ExtensionMessageService(); | |
57 | 60 |
58 // --- UI thread only: | 61 // --- UI thread only: |
59 | 62 |
60 // UI-thread specific initialization. Does nothing if called more than once. | 63 ExtensionMessageService(Profile* profile); |
61 void Init(); | 64 ~ExtensionMessageService(); |
| 65 |
| 66 // Notification that our owning profile is going away. |
| 67 void ProfileDestroyed() { profile_ = NULL; } |
62 | 68 |
63 // Add or remove |render_process_pid| as a listener for |event_name|. | 69 // Add or remove |render_process_pid| as a listener for |event_name|. |
64 void AddEventListener(std::string event_name, int render_process_id); | 70 void AddEventListener(std::string event_name, int render_process_id); |
65 void RemoveEventListener(std::string event_name, int render_process_id); | 71 void RemoveEventListener(std::string event_name, int render_process_id); |
66 | 72 |
67 // Closes the message channel associated with the given port, and notifies | 73 // Closes the message channel associated with the given port, and notifies |
68 // the other side. | 74 // the other side. |
69 void CloseChannel(int port_id); | 75 void CloseChannel(int port_id); |
70 | 76 |
71 // Sends a message from a renderer to the given port. | 77 // Sends a message from a renderer to the given port. |
72 void PostMessageFromRenderer(int port_id, const std::string& message); | 78 void PostMessageFromRenderer(int port_id, const std::string& message); |
73 | 79 |
74 // Send an event to every registered extension renderer. | 80 // Send an event to every registered extension renderer. |
75 void DispatchEventToRenderers( | 81 void DispatchEventToRenderers( |
76 const std::string& event_name, const std::string& event_args); | 82 const std::string& event_name, const std::string& event_args); |
77 | 83 |
78 // Given an extension's ID, opens a channel between the given automation | 84 // Given an extension's ID, opens a channel between the given automation |
79 // "port" and that extension. Returns a channel ID to be used for posting | 85 // "port" and that extension. Returns a channel ID to be used for posting |
80 // messages between the processes, or -1 if the extension doesn't exist. | 86 // messages between the processes, or -1 if the extension doesn't exist. |
81 int OpenAutomationChannelToExtension(int source_process_id, | 87 int OpenAutomationChannelToExtension(int source_process_id, |
82 int routing_id, | 88 int routing_id, |
83 const std::string& extension_id, | 89 const std::string& extension_id, |
84 IPC::Message::Sender* source); | 90 IPC::Message::Sender* source); |
85 | 91 |
86 // NotificationObserver interface. | |
87 void Observe(NotificationType type, | |
88 const NotificationSource& source, | |
89 const NotificationDetails& details); | |
90 | |
91 // --- IO thread only: | 92 // --- IO thread only: |
92 | 93 |
93 // Given an extension's ID, opens a channel between the given renderer "port" | 94 // Given an extension's ID, opens a channel between the given renderer "port" |
94 // and every listening context owned by that extension. Returns a port ID | 95 // and every listening context owned by that extension. Returns a port ID |
95 // to be used for posting messages between the processes. |channel_name| is | 96 // to be used for posting messages between the processes. |channel_name| is |
96 // an optional identifier for use by extension developers. | 97 // an optional identifier for use by extension developers. |
97 // This runs on the IO thread so that it can be used in a synchronous IPC | 98 // This runs on the IO thread so that it can be used in a synchronous IPC |
98 // message. | 99 // message. |
99 int OpenChannelToExtension(int routing_id, const std::string& extension_id, | 100 int OpenChannelToExtension(int routing_id, const std::string& extension_id, |
100 const std::string& channel_name, | 101 const std::string& channel_name, |
101 ResourceMessageFilter* source); | 102 ResourceMessageFilter* source); |
102 | 103 |
| 104 // Same as above, but opens a channel to the tab with the given ID. Messages |
| 105 // are restricted to that tab, so if there are multiple tabs in that process, |
| 106 // only the targeted tab will receive messages. |
| 107 int OpenChannelToTab(int routing_id, int tab_id, |
| 108 const std::string& extension_id, |
| 109 const std::string& channel_name, |
| 110 ResourceMessageFilter* source); |
| 111 |
103 private: | 112 private: |
104 // A messaging channel. Since messages are broadcast, the channel can have | |
105 // multiple processes listening for messages. Note that the opening port | |
106 // can also be among the receivers, if an extension toolstrip wants to talk | |
107 // to its tab (for example). | |
108 struct MessageChannel { | |
109 typedef std::set<IPC::Message::Sender*> Ports; | |
110 Ports opener; // only 1 opener, but we use a set to simplify logic | |
111 Ports receivers; | |
112 }; | |
113 | |
114 // A map of channel ID to its channel object. | 113 // A map of channel ID to its channel object. |
115 typedef std::map<int, linked_ptr<MessageChannel> > MessageChannelMap; | 114 typedef std::map<int, linked_ptr<MessageChannel> > MessageChannelMap; |
116 | 115 |
117 // Allocates a pair of port ids. | 116 // Allocates a pair of port ids. |
118 // NOTE: this can be called from any thread. | 117 // NOTE: this can be called from any thread. |
119 void AllocatePortIdPair(int* port1, int* port2); | 118 void AllocatePortIdPair(int* port1, int* port2); |
120 | 119 |
121 void CloseChannelImpl(MessageChannelMap::iterator channel_iter, int port_id); | 120 void CloseChannelImpl(MessageChannelMap::iterator channel_iter, int port_id); |
122 | 121 |
123 // The UI message loop, used for posting tasks. | 122 // The UI message loop, used for posting tasks. |
124 MessageLoop* ui_loop_; | 123 MessageLoop* ui_loop_; |
125 | 124 |
126 // --- UI thread only: | 125 // --- UI thread only: |
127 | 126 |
128 // Handles channel creation and notifies the destinations that a channel was | 127 // Handles channel creation and notifies the destinations that a channel was |
129 // opened. | 128 // opened. |
130 void OpenChannelOnUIThread(int source_routing_id, | 129 void OpenChannelToExtensionOnUIThread( |
131 int source_port_id, int source_process_id, | 130 int source_process_id, int source_routing_id, int receiver_port_id, |
132 const std::string& extension_id, const std::string& channel_name); | 131 const std::string& extension_id, const std::string& channel_name); |
| 132 |
| 133 void OpenChannelToTabOnUIThread( |
| 134 int source_process_id, int source_routing_id, int receiver_port_id, |
| 135 int tab_id, const std::string& extension_id, |
| 136 const std::string& channel_name); |
133 | 137 |
134 // Common between OpenChannelOnUIThread and OpenAutomationChannelToExtension. | 138 // Common between OpenChannelOnUIThread and OpenAutomationChannelToExtension. |
135 void OpenChannelOnUIThreadImpl( | 139 void OpenChannelOnUIThreadImpl( |
136 int source_routing_id, int source_port_id, int source_process_id, | 140 IPC::Message::Sender* source, int source_process_id, int source_routing_id, |
137 IPC::Message::Sender* source, const std::string& extension_id, | 141 const MessagePort& receiver, int receiver_port_id, |
138 const std::string& channel_name); | 142 const std::string& extension_id, const std::string& channel_name); |
| 143 |
| 144 // NotificationObserver interface. |
| 145 void Observe(NotificationType type, |
| 146 const NotificationSource& source, |
| 147 const NotificationDetails& details); |
| 148 |
| 149 // An IPC sender that might be in our list of channels has closed. |
| 150 void OnSenderClosed(IPC::Message::Sender* sender); |
| 151 |
| 152 Profile* profile_; |
139 | 153 |
140 NotificationRegistrar registrar_; | 154 NotificationRegistrar registrar_; |
141 | 155 |
142 MessageChannelMap channels_; | 156 MessageChannelMap channels_; |
143 | 157 |
144 // A map between an event name and a set of process id's that are listening | 158 // A map between an event name and a set of process id's that are listening |
145 // to that event. | 159 // to that event. |
146 typedef std::map<std::string, std::set<int> > ListenerMap; | 160 typedef std::map<std::string, std::set<int> > ListenerMap; |
147 ListenerMap listeners_; | 161 ListenerMap listeners_; |
148 | 162 |
149 // --- UI or IO thread: | 163 // --- UI or IO thread: |
150 | 164 |
151 // True if Init has been called. | |
152 bool initialized_; | |
153 | |
154 // For generating unique channel IDs. | 165 // For generating unique channel IDs. |
155 int next_port_id_; | 166 int next_port_id_; |
156 | 167 |
157 // Protects the next_port_id_ variable, since it can be | 168 // Protects the next_port_id_ variable, since it can be |
158 // used on the IO thread or the UI thread. | 169 // used on the IO thread or the UI thread. |
159 Lock next_port_id_lock_; | 170 Lock next_port_id_lock_; |
160 | 171 |
161 DISALLOW_COPY_AND_ASSIGN(ExtensionMessageService); | 172 DISALLOW_COPY_AND_ASSIGN(ExtensionMessageService); |
162 }; | 173 }; |
163 | 174 |
164 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ | 175 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_ |
OLD | NEW |