15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifndef EXTENSIONS_BROWSER_EVENT_ROUTER_H_
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define EXTENSIONS_BROWSER_EVENT_ROUTER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/scoped_observer.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_listener_map.h"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/extension_registry_observer.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/event_filtering_info.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sender.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GURL;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class PrefService;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class BrowserContext;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderProcessHost;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ActivityLog;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Extension;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionHost;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionPrefs;
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ExtensionRegistry;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Event;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct EventDispatchInfo;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct EventListenerInfo;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EventRouter : public content::NotificationObserver,
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    public ExtensionRegistryObserver,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    public EventListenerMap::Delegate {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These constants convey the state of our knowledge of whether we're in
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a user-caused gesture as part of DispatchEvent.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum UserGestureState {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    USER_GESTURE_UNKNOWN = 0,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    USER_GESTURE_ENABLED = 1,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    USER_GESTURE_NOT_ENABLED = 2,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The pref key for the list of event names for which an extension has
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // registered from its lazy background page.
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  static const char kRegisteredEvents[];
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Observers register interest in events with a particular name and are
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // notified when a listener is added or removed. Observers are matched by
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the base name of the event (e.g. adding an event listener for event name
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // "foo.onBar/123" will trigger observers registered for "foo.onBar").
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Observer {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Called when a listener is added.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnListenerAdded(const EventListenerInfo& details) {}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Called when a listener is removed.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnListenerRemoved(const EventListenerInfo& details) {}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Gets the EventRouter for |browser_context|.
75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Shorthand for ExtensionSystem::Get(browser_context)->event_router(); it's
76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // a very common operation.
77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  static EventRouter* Get(content::BrowserContext* browser_context);
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Converts event names like "foo.onBar/123" into "foo.onBar". Event names
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // without a "/" are returned unchanged.
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static std::string GetBaseEventName(const std::string& full_event_name);
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sends an event via ipc_sender to the given extension. Can be called on any
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void DispatchEvent(IPC::Sender* ipc_sender,
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            void* browser_context_id,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& extension_id,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& event_name,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            scoped_ptr<base::ListValue> event_args,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            UserGestureState user_gesture,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const EventFilteringInfo& info);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // An EventRouter is shared between |browser_context| and its associated
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // incognito context. |extension_prefs| may be NULL in tests.
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EventRouter(content::BrowserContext* browser_context,
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              ExtensionPrefs* extension_prefs);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~EventRouter();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Add or remove an extension as an event listener for |event_name|.
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  //
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that multiple extensions can share a process due to process
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // collapsing. Also, a single extension can have 2 processes if it is a split
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mode extension.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddEventListener(const std::string& event_name,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        content::RenderProcessHost* process,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const std::string& extension_id);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveEventListener(const std::string& event_name,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           content::RenderProcessHost* process,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::string& extension_id);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Add or remove a URL as an event listener for |event_name|.
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void AddEventListenerForURL(const std::string& event_name,
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              content::RenderProcessHost* process,
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              const GURL& listener_url);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void RemoveEventListenerForURL(const std::string& event_name,
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 content::RenderProcessHost* process,
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const GURL& listener_url);
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListenerMap& listeners() { return listeners_; }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Registers an observer to be notified when an event listener for
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |event_name| is added or removed. There can currently be only one observer
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for each distinct |event_name|.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RegisterObserver(Observer* observer,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const std::string& event_name);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unregisters an observer from all events.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnregisterObserver(Observer* observer);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add or remove the extension as having a lazy background page that listens
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the event. The difference from the above methods is that these will be
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // remembered even after the process goes away. We use this list to decide
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which extension pages to load when dispatching an event.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLazyEventListener(const std::string& event_name,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& extension_id);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveLazyEventListener(const std::string& event_name,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const std::string& extension_id);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |add_lazy_listener| is true also add the lazy version of this listener.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddFilteredEventListener(const std::string& event_name,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                content::RenderProcessHost* process,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& extension_id,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const base::DictionaryValue& filter,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool add_lazy_listener);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |remove_lazy_listener| is true also remove the lazy version of this
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // listener.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveFilteredEventListener(const std::string& event_name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   content::RenderProcessHost* process,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& extension_id,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const base::DictionaryValue& filter,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool remove_lazy_listener);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if there is at least one listener for the given event.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasEventListener(const std::string& event_name);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the extension is listening to the given event.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ExtensionHasEventListener(const std::string& extension_id,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& event_name);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Return or set the list of events for which the given extension has
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // registered.
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::set<std::string> GetRegisteredEvents(const std::string& extension_id);
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void SetRegisteredEvents(const std::string& extension_id,
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           const std::set<std::string>& events);
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Broadcasts an event to every listener registered for that event.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void BroadcastEvent(scoped_ptr<Event> event);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Dispatches an event to the given extension.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DispatchEventToExtension(const std::string& extension_id,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        scoped_ptr<Event> event);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Dispatches |event| to the given extension as if the extension has a lazy
175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // listener for it. NOTE: This should be used rarely, for dispatching events
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // to extensions that haven't had a chance to add their own listeners yet, eg:
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // newly installed extensions.
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void DispatchEventWithLazyListener(const std::string& extension_id,
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                     scoped_ptr<Event> event);
180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the Event Ack from the renderer. (One less event in-flight.)
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void OnEventAck(content::BrowserContext* context,
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  const std::string& extension_id);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  friend class EventRouterTest;
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extension and process that contains the event listener for a given
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ListenerProcess;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A map between an event name and a set of extensions that are listening
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to that event.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, std::set<ListenerProcess> > ListenerMap;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An identifier for an event dispatch that is used to prevent double dispatch
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // due to race conditions between the direct and lazy dispatch paths.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::pair<const content::BrowserContext*, std::string>
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EventDispatchIdentifier;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(gdk): Document this.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void DispatchExtensionMessage(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC::Sender* ipc_sender,
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      void* browser_context_id,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& extension_id,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& event_name,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ListValue* event_args,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UserGestureState user_gesture,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const extensions::EventFilteringInfo& info);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // ExtensionRegistryObserver implementation.
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void OnExtensionLoaded(content::BrowserContext* browser_context,
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const Extension* extension) OVERRIDE;
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void OnExtensionUnloaded(
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserContext* browser_context,
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const Extension* extension,
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      UnloadedExtensionInfo::Reason reason) OVERRIDE;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the given listener map contains a event listeners for
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the given event. If |extension_id| is non-empty, we also check that that
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension is one of the listeners.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasEventListenerImpl(const ListenerMap& listeners,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& extension_id,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& event_name);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event is broadcast.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An event that just came off the pending list may not be delayed again.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DispatchEventImpl(const std::string& restrict_to_extension_id,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const linked_ptr<Event>& event);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensures that all lazy background pages that are interested in the given
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event are loaded, and queues the event if the page is not ready yet.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inserts an EventDispatchIdentifier into |already_dispatched| for each lazy
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event dispatch that is queued.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DispatchLazyEvent(const std::string& extension_id,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const linked_ptr<Event>& event,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         std::set<EventDispatchIdentifier>* already_dispatched);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Dispatches the event to the specified extension or URL running in
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |process|.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DispatchEventToProcess(const std::string& extension_id,
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              const GURL& listener_url,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              content::RenderProcessHost* process,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const linked_ptr<Event>& event);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Returns false when the event is scoped to a context and the listening
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // extension does not have access to events from that context. Also fills
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |event_args| with the proper arguments to send, which may differ if
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the event crosses the incognito boundary.
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool CanDispatchEventToBrowserContext(content::BrowserContext* context,
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        const Extension* extension,
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        const linked_ptr<Event>& event);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Possibly loads given extension's background page in preparation to
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dispatch an event.  Returns true if the event was queued for subsequent
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dispatch, false otherwise.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool MaybeLoadLazyBackgroundPageToDispatchEvent(
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content::BrowserContext* context,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const linked_ptr<Event>& event);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Adds a filter to an event.
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void AddFilterToEvent(const std::string& event_name,
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const std::string& extension_id,
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const base::DictionaryValue* filter);
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Removes a filter from an event.
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void RemoveFilterFromEvent(const std::string& event_name,
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             const std::string& extension_id,
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             const base::DictionaryValue* filter);
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Returns the dictionary of event filters that the given extension has
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // registered.
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const base::DictionaryValue* GetFilteredEvents(
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const std::string& extension_id);
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Track of the number of dispatched events that have not yet sent an
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ACK from the renderer.
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void IncrementInFlightEvents(content::BrowserContext* context,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const Extension* extension);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // static
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  static void IncrementInFlightEventsOnUI(
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      void* browser_context_id,
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const std::string& extension_id);
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DispatchPendingEvent(const linked_ptr<Event>& event,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ExtensionHost* host);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of EventListenerMap::Delegate.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnListenerAdded(const EventListener* listener) OVERRIDE;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  content::BrowserContext* browser_context_;
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The ExtensionPrefs associated with |browser_context_|. May be NULL in
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // tests.
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtensionPrefs* extension_prefs_;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_observer_;
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListenerMap listeners_;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Map from base event name to observer.
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef base::hash_map<std::string, Observer*> ObserverMap;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverMap observers_;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(EventRouter);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Event {
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef base::Callback<void(content::BrowserContext*,
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              const Extension*,
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              base::ListValue*)> WillDispatchCallback;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The event to dispatch.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_name;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Arguments to send to the event listener.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> event_args;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If non-NULL, then the event will not be sent to other BrowserContexts
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // unless the extension has permission (e.g. incognito tab update -> normal
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // tab only works if extension is allowed incognito access).
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  content::BrowserContext* restrict_to_browser_context;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If not empty, the event is only sent to extensions with host permissions
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for this url.
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL event_url;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Whether a user gesture triggered the event.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventRouter::UserGestureState user_gesture;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Extra information used to filter which events are sent to the listener.
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventFilteringInfo filter_info;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If specified, this is called before dispatching an event to each
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // extension. The third argument is a mutable reference to event_args,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // allowing the caller to provide different arguments depending on the
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // extension and profile. This is guaranteed to be called synchronously with
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // DispatchEvent, so callers don't need to worry about lifetime.
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  //
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // NOTE: the Extension argument to this may be NULL because it's possible for
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // this event to be dispatched to non-extension processes, like WebUI.
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WillDispatchCallback will_dispatch_callback;
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Event(const std::string& event_name,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<base::ListValue> event_args);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Event(const std::string& event_name,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<base::ListValue> event_args,
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        content::BrowserContext* restrict_to_browser_context);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Event(const std::string& event_name,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<base::ListValue> event_args,
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        content::BrowserContext* restrict_to_browser_context,
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const GURL& event_url,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EventRouter::UserGestureState user_gesture,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const EventFilteringInfo& info);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Event();
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Makes a deep copy of this instance. Ownership is transferred to the
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // caller.
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Event* DeepCopy();
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct EventListenerInfo {
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventListenerInfo(const std::string& event_name,
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    const std::string& extension_id,
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    const GURL& listener_url,
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    content::BrowserContext* browser_context);
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The event name including any sub-event, e.g. "runtime.onStartup" or
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // "webRequest.onCompleted/123".
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string event_name;
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string extension_id;
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const GURL listener_url;
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  content::BrowserContext* browser_context;
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // EXTENSIONS_BROWSER_EVENT_ROUTER_H_
392