• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 EXTENSIONS_BROWSER_EVENT_ROUTER_H_
6 #define EXTENSIONS_BROWSER_EVENT_ROUTER_H_
7 
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <utility>
12 
13 #include "base/callback.h"
14 #include "base/compiler_specific.h"
15 #include "base/containers/hash_tables.h"
16 #include "base/gtest_prod_util.h"
17 #include "base/memory/linked_ptr.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/values.h"
20 #include "content/public/browser/notification_observer.h"
21 #include "content/public/browser/notification_registrar.h"
22 #include "extensions/browser/event_listener_map.h"
23 #include "extensions/common/event_filtering_info.h"
24 #include "ipc/ipc_sender.h"
25 
26 class GURL;
27 class PrefService;
28 
29 namespace content {
30 class BrowserContext;
31 class RenderProcessHost;
32 }
33 
34 namespace extensions {
35 class ActivityLog;
36 class Extension;
37 class ExtensionHost;
38 class ExtensionPrefs;
39 
40 struct Event;
41 struct EventDispatchInfo;
42 struct EventListenerInfo;
43 
44 class EventRouter : public content::NotificationObserver,
45                     public EventListenerMap::Delegate {
46  public:
47   // These constants convey the state of our knowledge of whether we're in
48   // a user-caused gesture as part of DispatchEvent.
49   enum UserGestureState {
50     USER_GESTURE_UNKNOWN = 0,
51     USER_GESTURE_ENABLED = 1,
52     USER_GESTURE_NOT_ENABLED = 2,
53   };
54 
55   // The pref key for the list of event names for which an extension has
56   // registered from its lazy background page.
57   static const char kRegisteredEvents[];
58 
59   // Observers register interest in events with a particular name and are
60   // notified when a listener is added or removed. Observers are matched by
61   // the base name of the event (e.g. adding an event listener for event name
62   // "foo.onBar/123" will trigger observers registered for "foo.onBar").
63   class Observer {
64    public:
65     // Called when a listener is added.
OnListenerAdded(const EventListenerInfo & details)66     virtual void OnListenerAdded(const EventListenerInfo& details) {}
67     // Called when a listener is removed.
OnListenerRemoved(const EventListenerInfo & details)68     virtual void OnListenerRemoved(const EventListenerInfo& details) {}
69   };
70 
71   // The EventDispatchObserver is notified on the UI thread whenever
72   // an event is dispatched. There can be only one EventDispatchObserver.
73   class EventDispatchObserver {
74    public:
75     virtual void OnWillDispatchEvent(scoped_ptr<EventDispatchInfo> details) = 0;
76   };
77 
78   // Converts event names like "foo.onBar/123" into "foo.onBar". Event names
79   // without a "/" are returned unchanged.
80   static std::string GetBaseEventName(const std::string& full_event_name);
81 
82   // Sends an event via ipc_sender to the given extension. Can be called on any
83   // thread.
84   static void DispatchEvent(IPC::Sender* ipc_sender,
85                             void* browser_context_id,
86                             const std::string& extension_id,
87                             const std::string& event_name,
88                             scoped_ptr<base::ListValue> event_args,
89                             UserGestureState user_gesture,
90                             const EventFilteringInfo& info);
91 
92   // An EventRouter is shared between |browser_context| and its associated
93   // incognito context. |extension_prefs| may be NULL in tests.
94   EventRouter(content::BrowserContext* browser_context,
95               ExtensionPrefs* extension_prefs);
96   virtual ~EventRouter();
97 
98   // Add or remove the process/extension pair as a listener for |event_name|.
99   // Note that multiple extensions can share a process due to process
100   // collapsing. Also, a single extension can have 2 processes if it is a split
101   // mode extension.
102   void AddEventListener(const std::string& event_name,
103                         content::RenderProcessHost* process,
104                         const std::string& extension_id);
105   void RemoveEventListener(const std::string& event_name,
106                            content::RenderProcessHost* process,
107                            const std::string& extension_id);
108 
listeners()109   EventListenerMap& listeners() { return listeners_; }
110 
111   // Registers an observer to be notified when an event listener for
112   // |event_name| is added or removed. There can currently be only one observer
113   // for each distinct |event_name|.
114   void RegisterObserver(Observer* observer,
115                         const std::string& event_name);
116 
117   // Unregisters an observer from all events.
118   void UnregisterObserver(Observer* observer);
119 
120   // Sets the observer to be notified whenever an event is dispatched to an
121   // extension.
122   void SetEventDispatchObserver(EventDispatchObserver* observer);
123 
124   // Add or remove the extension as having a lazy background page that listens
125   // to the event. The difference from the above methods is that these will be
126   // remembered even after the process goes away. We use this list to decide
127   // which extension pages to load when dispatching an event.
128   void AddLazyEventListener(const std::string& event_name,
129                             const std::string& extension_id);
130   void RemoveLazyEventListener(const std::string& event_name,
131                                const std::string& extension_id);
132 
133   // If |add_lazy_listener| is true also add the lazy version of this listener.
134   void AddFilteredEventListener(const std::string& event_name,
135                                 content::RenderProcessHost* process,
136                                 const std::string& extension_id,
137                                 const base::DictionaryValue& filter,
138                                 bool add_lazy_listener);
139 
140   // If |remove_lazy_listener| is true also remove the lazy version of this
141   // listener.
142   void RemoveFilteredEventListener(const std::string& event_name,
143                                    content::RenderProcessHost* process,
144                                    const std::string& extension_id,
145                                    const base::DictionaryValue& filter,
146                                    bool remove_lazy_listener);
147 
148   // Returns true if there is at least one listener for the given event.
149   bool HasEventListener(const std::string& event_name);
150 
151   // Returns true if the extension is listening to the given event.
152   bool ExtensionHasEventListener(const std::string& extension_id,
153                                  const std::string& event_name);
154 
155   // Return or set the list of events for which the given extension has
156   // registered.
157   std::set<std::string> GetRegisteredEvents(const std::string& extension_id);
158   void SetRegisteredEvents(const std::string& extension_id,
159                            const std::set<std::string>& events);
160 
161   // Broadcasts an event to every listener registered for that event.
162   virtual void BroadcastEvent(scoped_ptr<Event> event);
163 
164   // Dispatches an event to the given extension.
165   virtual void DispatchEventToExtension(const std::string& extension_id,
166                                         scoped_ptr<Event> event);
167 
168   // Dispatches |event| to the given extension as if the extension has a lazy
169   // listener for it. NOTE: This should be used rarely, for dispatching events
170   // to extensions that haven't had a chance to add their own listeners yet, eg:
171   // newly installed extensions.
172   void DispatchEventWithLazyListener(const std::string& extension_id,
173                                      scoped_ptr<Event> event);
174 
175   // Record the Event Ack from the renderer. (One less event in-flight.)
176   void OnEventAck(content::BrowserContext* context,
177                   const std::string& extension_id);
178 
179  private:
180   FRIEND_TEST_ALL_PREFIXES(EventRouterTest, EventRouterObserver);
181 
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   // An identifier for an event dispatch that is used to prevent double dispatch
191   // due to race conditions between the direct and lazy dispatch paths.
192   typedef std::pair<const content::BrowserContext*, std::string>
193       EventDispatchIdentifier;
194 
195   // Sends a notification about an event to the event dispatch observer on the
196   // UI thread. Can be called from any thread.
197   static void NotifyExtensionDispatchObserverOnUIThread(
198       void* browser_context_id,
199       scoped_ptr<EventDispatchInfo> details);
200 
201   // TODO(gdk): Document this.
202   static void DispatchExtensionMessage(
203       IPC::Sender* ipc_sender,
204       void* browser_context_id,
205       const std::string& extension_id,
206       const std::string& event_name,
207       base::ListValue* event_args,
208       UserGestureState user_gesture,
209       const extensions::EventFilteringInfo& info);
210 
211   virtual void Observe(int type,
212                        const content::NotificationSource& source,
213                        const content::NotificationDetails& details) OVERRIDE;
214 
215   // Returns true if the given listener map contains a event listeners for
216   // the given event. If |extension_id| is non-empty, we also check that that
217   // extension is one of the listeners.
218   bool HasEventListenerImpl(const ListenerMap& listeners,
219                             const std::string& extension_id,
220                             const std::string& event_name);
221 
222   // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the
223   // event is broadcast.
224   // An event that just came off the pending list may not be delayed again.
225   void DispatchEventImpl(const std::string& restrict_to_extension_id,
226                          const linked_ptr<Event>& event);
227 
228   // Ensures that all lazy background pages that are interested in the given
229   // event are loaded, and queues the event if the page is not ready yet.
230   // Inserts an EventDispatchIdentifier into |already_dispatched| for each lazy
231   // event dispatch that is queued.
232   void DispatchLazyEvent(const std::string& extension_id,
233                          const linked_ptr<Event>& event,
234                          std::set<EventDispatchIdentifier>* already_dispatched);
235 
236   // Dispatches the event to the specified extension running in |process|.
237   void DispatchEventToProcess(const std::string& extension_id,
238                               content::RenderProcessHost* process,
239                               const linked_ptr<Event>& event);
240 
241   // Returns false when the event is scoped to a context and the listening
242   // extension does not have access to events from that context. Also fills
243   // |event_args| with the proper arguments to send, which may differ if
244   // the event crosses the incognito boundary.
245   bool CanDispatchEventToBrowserContext(content::BrowserContext* context,
246                                         const Extension* extension,
247                                         const linked_ptr<Event>& event);
248 
249   // Possibly loads given extension's background page in preparation to
250   // dispatch an event.  Returns true if the event was queued for subsequent
251   // dispatch, false otherwise.
252   bool MaybeLoadLazyBackgroundPageToDispatchEvent(
253       content::BrowserContext* context,
254       const Extension* extension,
255       const linked_ptr<Event>& event);
256 
257   // Adds a filter to an event.
258   void AddFilterToEvent(const std::string& event_name,
259                         const std::string& extension_id,
260                         const base::DictionaryValue* filter);
261 
262   // Removes a filter from an event.
263   void RemoveFilterFromEvent(const std::string& event_name,
264                              const std::string& extension_id,
265                              const base::DictionaryValue* filter);
266 
267   // Returns the dictionary of event filters that the given extension has
268   // registered.
269   const base::DictionaryValue* GetFilteredEvents(
270       const std::string& extension_id);
271 
272   // Track of the number of dispatched events that have not yet sent an
273   // ACK from the renderer.
274   void IncrementInFlightEvents(content::BrowserContext* context,
275                                const Extension* extension);
276 
277   // static
278   static void IncrementInFlightEventsOnUI(
279       void* browser_context_id,
280       const std::string& extension_id);
281 
282   void DispatchPendingEvent(const linked_ptr<Event>& event,
283                             ExtensionHost* host);
284 
285   // Implementation of EventListenerMap::Delegate.
286   virtual void OnListenerAdded(const EventListener* listener) OVERRIDE;
287   virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE;
288 
289   content::BrowserContext* browser_context_;
290 
291   // The ExtensionPrefs associated with |browser_context_|. May be NULL in
292   // tests.
293   ExtensionPrefs* extension_prefs_;
294 
295   content::NotificationRegistrar registrar_;
296 
297   EventListenerMap listeners_;
298 
299   // Map from base event name to observer.
300   typedef base::hash_map<std::string, Observer*> ObserverMap;
301   ObserverMap observers_;
302 
303   EventDispatchObserver* event_dispatch_observer_;
304 
305   DISALLOW_COPY_AND_ASSIGN(EventRouter);
306 };
307 
308 struct Event {
309   typedef base::Callback<void(content::BrowserContext*,
310                               const Extension*,
311                               base::ListValue*)> WillDispatchCallback;
312 
313   // The event to dispatch.
314   std::string event_name;
315 
316   // Arguments to send to the event listener.
317   scoped_ptr<base::ListValue> event_args;
318 
319   // If non-NULL, then the event will not be sent to other BrowserContexts
320   // unless the extension has permission (e.g. incognito tab update -> normal
321   // tab only works if extension is allowed incognito access).
322   content::BrowserContext* restrict_to_browser_context;
323 
324   // If not empty, the event is only sent to extensions with host permissions
325   // for this url.
326   GURL event_url;
327 
328   // Whether a user gesture triggered the event.
329   EventRouter::UserGestureState user_gesture;
330 
331   // Extra information used to filter which events are sent to the listener.
332   EventFilteringInfo filter_info;
333 
334   // If specified, this is called before dispatching an event to each
335   // extension. The third argument is a mutable reference to event_args,
336   // allowing the caller to provide different arguments depending on the
337   // extension and profile. This is guaranteed to be called synchronously with
338   // DispatchEvent, so callers don't need to worry about lifetime.
339   WillDispatchCallback will_dispatch_callback;
340 
341   Event(const std::string& event_name,
342         scoped_ptr<base::ListValue> event_args);
343 
344   Event(const std::string& event_name,
345         scoped_ptr<base::ListValue> event_args,
346         content::BrowserContext* restrict_to_browser_context);
347 
348   Event(const std::string& event_name,
349         scoped_ptr<base::ListValue> event_args,
350         content::BrowserContext* restrict_to_browser_context,
351         const GURL& event_url,
352         EventRouter::UserGestureState user_gesture,
353         const EventFilteringInfo& info);
354 
355   ~Event();
356 
357   // Makes a deep copy of this instance. Ownership is transferred to the
358   // caller.
359   Event* DeepCopy();
360 };
361 
362 struct EventListenerInfo {
363   EventListenerInfo(const std::string& event_name,
364                     const std::string& extension_id,
365                     content::BrowserContext* browser_context);
366   // The event name including any sub-event, e.g. "runtime.onStartup" or
367   // "webRequest.onCompleted/123".
368   const std::string event_name;
369 
370   const std::string extension_id;
371   content::BrowserContext* browser_context;
372 };
373 
374 struct EventDispatchInfo {
375   EventDispatchInfo(const std::string& extension_id,
376                     const std::string& event_name,
377                     scoped_ptr<ListValue> event_args);
378   ~EventDispatchInfo();
379 
380   const std::string extension_id;
381   const std::string event_name;
382   scoped_ptr<ListValue> event_args;
383 };
384 
385 }  // namespace extensions
386 
387 #endif  // EXTENSIONS_BROWSER_EVENT_ROUTER_H_
388