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 |