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