OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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_EVENT_ROUTER_H_ | |
6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_EVENT_ROUTER_H_ | |
7 | |
8 #include <map> | |
9 #include <set> | |
10 #include <string> | |
11 | |
12 #include "base/compiler_specific.h" | |
13 #include "base/memory/linked_ptr.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "base/values.h" | |
16 #include "chrome/browser/extensions/event_listener_map.h" | |
17 #include "chrome/common/extensions/event_filtering_info.h" | |
18 #include "content/public/browser/notification_observer.h" | |
19 #include "content/public/browser/notification_registrar.h" | |
20 #include "ipc/ipc_sender.h" | |
21 | |
22 class GURL; | |
23 class ExtensionHost; | |
24 class ExtensionDevToolsManager; | |
25 class Profile; | |
26 | |
27 namespace content { | |
28 class RenderProcessHost; | |
29 } | |
30 | |
31 namespace extensions { | |
32 class Extension; | |
33 } | |
34 | |
35 struct ExtensionEvent; | |
36 | |
37 using extensions::EventFilteringInfo; | |
38 using extensions::EventListener; | |
39 using extensions::EventListenerMap; | |
40 | |
41 class ExtensionEventRouter : public content::NotificationObserver, | |
42 public extensions::EventListenerMap::Delegate { | |
43 public: | |
44 // These constants convey the state of our knowledge of whether we're in | |
45 // a user-caused gesture as part of DispatchEvent. | |
46 enum UserGestureState { | |
47 USER_GESTURE_UNKNOWN = 0, | |
48 USER_GESTURE_ENABLED = 1, | |
49 USER_GESTURE_NOT_ENABLED = 2, | |
50 }; | |
51 | |
52 // Sends an event via ipc_sender to the given extension. Can be called on | |
53 // any thread. | |
54 static void DispatchEvent(IPC::Sender* ipc_sender, | |
55 const std::string& extension_id, | |
56 const std::string& event_name, | |
57 const base::Value& event_args, | |
58 const GURL& event_url, | |
59 UserGestureState user_gesture, | |
60 const extensions::EventFilteringInfo& info); | |
61 | |
62 // This invocation is deprecated. All future consumers of this API should be | |
63 // sending Values as event arguments, using the above version. | |
64 static void DispatchEvent(IPC::Sender* ipc_sender, | |
65 const std::string& extension_id, | |
66 const std::string& event_name, | |
67 const std::string& event_args, | |
68 const GURL& event_url, | |
69 UserGestureState user_gesture, | |
70 const extensions::EventFilteringInfo& info); | |
71 | |
72 explicit ExtensionEventRouter(Profile* profile); | |
73 virtual ~ExtensionEventRouter(); | |
74 | |
75 // Add or remove the process/extension pair as a listener for |event_name|. | |
76 // Note that multiple extensions can share a process due to process | |
77 // collapsing. Also, a single extension can have 2 processes if it is a split | |
78 // mode extension. | |
79 void AddEventListener(const std::string& event_name, | |
80 content::RenderProcessHost* process, | |
81 const std::string& extension_id); | |
82 void RemoveEventListener(const std::string& event_name, | |
83 content::RenderProcessHost* process, | |
84 const std::string& extension_id); | |
85 | |
86 // Add or remove the extension as having a lazy background page that listens | |
87 // to the event. The difference from the above methods is that these will be | |
88 // remembered even after the process goes away. We use this list to decide | |
89 // which extension pages to load when dispatching an event. | |
90 void AddLazyEventListener(const std::string& event_name, | |
91 const std::string& extension_id); | |
92 void RemoveLazyEventListener(const std::string& event_name, | |
93 const std::string& extension_id); | |
94 | |
95 // If |add_lazy_listener| is true also add the lazy version of this listener. | |
96 void AddFilteredEventListener(const std::string& event_name, | |
97 content::RenderProcessHost* process, | |
98 const std::string& extension_id, | |
99 const base::DictionaryValue& filter, | |
100 bool add_lazy_listener); | |
101 | |
102 // If |remove_lazy_listener| is true also remove the lazy version of this | |
103 // listener. | |
104 void RemoveFilteredEventListener(const std::string& event_name, | |
105 content::RenderProcessHost* process, | |
106 const std::string& extension_id, | |
107 const base::DictionaryValue& filter, | |
108 bool remove_lazy_listener); | |
109 | |
110 // Returns true if there is at least one listener for the given event. | |
111 bool HasEventListener(const std::string& event_name); | |
112 | |
113 // Returns true if the extension is listening to the given event. | |
114 bool ExtensionHasEventListener(const std::string& extension_id, | |
115 const std::string& event_name); | |
116 | |
117 // Send an event to every registered extension renderer. If | |
118 // |restrict_to_profile| is non-NULL, then the event will not be sent to other | |
119 // profiles unless the extension has permission (e.g. incognito tab update -> | |
120 // normal profile only works if extension is allowed incognito access). If | |
121 // |event_url| is not empty, the event is only sent to extension with host | |
122 // permissions for this url. | |
123 void DispatchEventToRenderers( | |
124 const std::string& event_name, | |
125 const std::string& event_args, | |
126 Profile* restrict_to_profile, | |
127 const GURL& event_url, | |
128 extensions::EventFilteringInfo info); | |
129 | |
130 // As above, but defaults |info| to EventFilteringInfo(). | |
131 void DispatchEventToRenderers( | |
132 const std::string& event_name, | |
133 const std::string& event_args, | |
134 Profile* restrict_to_profile, | |
135 const GURL& event_url); | |
136 | |
137 // Same as above, except only send the event to the given extension. | |
138 virtual void DispatchEventToExtension( | |
139 const std::string& extension_id, | |
140 const std::string& event_name, | |
141 const base::Value& event_args, | |
142 Profile* restrict_to_profile, | |
143 const GURL& event_url); | |
144 | |
145 // This invocation is deprecated. The above variant which uses a Value for | |
146 // event_args is to be used instead. | |
147 virtual void DispatchEventToExtension( | |
148 const std::string& extension_id, | |
149 const std::string& event_name, | |
150 const std::string& event_args, | |
151 Profile* restrict_to_profile, | |
152 const GURL& event_url); | |
153 | |
154 // Dispatch an event to particular extension. Also include an | |
155 // explicit user gesture indicator. | |
156 virtual void DispatchEventToExtension( | |
157 const std::string& extension_id, | |
158 const std::string& event_name, | |
159 const std::string& event_args, | |
160 Profile* restrict_to_profile, | |
161 const GURL& event_url, | |
162 UserGestureState user_gesture); | |
163 | |
164 // Send different versions of an event to extensions in different profiles. | |
165 // This is used in the case of sending one event to extensions that have | |
166 // incognito access, and another event to extensions that don't (here), | |
167 // in order to avoid sending 2 events to "spanning" extensions. | |
168 // If |cross_incognito_profile| is non-NULL and different from | |
169 // restrict_to_profile, send the event with cross_incognito_args to the | |
170 // extensions in that profile that can't cross incognito. | |
171 void DispatchEventsToRenderersAcrossIncognito( | |
172 const std::string& event_name, | |
173 const std::string& event_args, | |
174 Profile* restrict_to_profile, | |
175 const std::string& cross_incognito_args, | |
176 const GURL& event_url); | |
177 | |
178 // Record the Event Ack from the renderer. (One less event in-flight.) | |
179 void OnEventAck(Profile* profile, const std::string& extension_id); | |
180 | |
181 private: | |
182 // The extension and process that contains the event listener for a given | |
183 // event. | |
184 struct ListenerProcess; | |
185 | |
186 // A map between an event name and a set of extensions that are listening | |
187 // to that event. | |
188 typedef std::map<std::string, std::set<ListenerProcess> > ListenerMap; | |
189 | |
190 virtual void Observe(int type, | |
191 const content::NotificationSource& source, | |
192 const content::NotificationDetails& details) OVERRIDE; | |
193 | |
194 // Returns true if the given listener map contains a event listeners for | |
195 // the given event. If |extension_id| is non-empty, we also check that that | |
196 // extension is one of the listeners. | |
197 bool HasEventListenerImpl(const ListenerMap& listeners, | |
198 const std::string& extension_id, | |
199 const std::string& event_name); | |
200 | |
201 // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the | |
202 // event is broadcast. | |
203 // An event that just came off the pending list may not be delayed again. | |
204 void DispatchEventImpl(const std::string& restrict_to_extension_id, | |
205 const linked_ptr<ExtensionEvent>& event); | |
206 | |
207 // Ensures that all lazy background pages that are interested in the given | |
208 // event are loaded, and queues the event if the page is not ready yet. | |
209 void DispatchLazyEvent(const std::string& extension_id, | |
210 const linked_ptr<ExtensionEvent>& event); | |
211 | |
212 // Dispatches the event to the specified extension running in |process|. | |
213 void DispatchEventToProcess(const std::string& extension_id, | |
214 content::RenderProcessHost* process, | |
215 const linked_ptr<ExtensionEvent>& event); | |
216 | |
217 // Returns false when the event is scoped to a profile and the listening | |
218 // extension does not have access to events from that profile. Also fills | |
219 // |event_args| with the proper arguments to send, which may differ if | |
220 // the event crosses the incognito boundary. | |
221 bool CanDispatchEventToProfile( | |
222 Profile* profile, | |
223 const extensions::Extension* extension, | |
224 const linked_ptr<ExtensionEvent>& event, | |
225 const base::Value** event_args); | |
226 | |
227 // Possibly loads given extension's background page in preparation to | |
228 // dispatch an event. | |
229 void MaybeLoadLazyBackgroundPageToDispatchEvent( | |
230 Profile* profile, | |
231 const extensions::Extension* extension, | |
232 const linked_ptr<ExtensionEvent>& event); | |
233 | |
234 // Track of the number of dispatched events that have not yet sent an | |
235 // ACK from the renderer. | |
236 void IncrementInFlightEvents(Profile* profile, | |
237 const extensions::Extension* extension); | |
238 | |
239 void DispatchPendingEvent(const linked_ptr<ExtensionEvent>& event, | |
240 ExtensionHost* host); | |
241 | |
242 // Implementation of extensions::EventListenerMap::Delegate. | |
243 virtual void OnListenerAdded(const EventListener* listener) OVERRIDE; | |
244 virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE; | |
245 | |
246 Profile* profile_; | |
247 | |
248 content::NotificationRegistrar registrar_; | |
249 | |
250 scoped_refptr<ExtensionDevToolsManager> extension_devtools_manager_; | |
251 | |
252 EventListenerMap listeners_; | |
253 | |
254 DISALLOW_COPY_AND_ASSIGN(ExtensionEventRouter); | |
255 }; | |
256 | |
257 struct ExtensionEvent { | |
258 std::string event_name; | |
259 scoped_ptr<Value> event_args; | |
260 GURL event_url; | |
261 Profile* restrict_to_profile; | |
262 scoped_ptr<Value> cross_incognito_args; | |
263 ExtensionEventRouter::UserGestureState user_gesture; | |
264 extensions::EventFilteringInfo info; | |
265 | |
266 ExtensionEvent(const std::string& event_name, | |
267 const Value& event_args, | |
268 const GURL& event_url, | |
269 Profile* restrict_to_profile, | |
270 const Value& cross_incognito_args, | |
271 ExtensionEventRouter::UserGestureState user_gesture, | |
272 const extensions::EventFilteringInfo& info); | |
273 | |
274 // TODO(gdk): This variant should be retired once the callers are switched to | |
275 // providing Values instead of just strings. | |
276 ExtensionEvent(const std::string& event_name, | |
277 const std::string& event_args, | |
278 const GURL& event_url, | |
279 Profile* restrict_to_profile, | |
280 const std::string& cross_incognito_args, | |
281 ExtensionEventRouter::UserGestureState user_gesture, | |
282 const extensions::EventFilteringInfo& info); | |
283 | |
284 ExtensionEvent(const std::string& event_name, | |
285 const Value& event_args, | |
286 const GURL& event_url, | |
287 Profile* restrict_to_profile, | |
288 ExtensionEventRouter::UserGestureState user_gesture, | |
289 const extensions::EventFilteringInfo& info); | |
290 | |
291 ~ExtensionEvent(); | |
292 }; | |
293 | |
294 | |
295 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_EVENT_ROUTER_H_ | |
OLD | NEW |