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