#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
-#include "base/gtest_prod_util.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
+#include "base/scoped_observer.h"
#include "base/values.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "extensions/browser/event_listener_map.h"
+#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/event_filtering_info.h"
#include "ipc/ipc_sender.h"
class Extension;
class ExtensionHost;
class ExtensionPrefs;
+class ExtensionRegistry;
struct Event;
struct EventDispatchInfo;
struct EventListenerInfo;
class EventRouter : public content::NotificationObserver,
+ public ExtensionRegistryObserver,
public EventListenerMap::Delegate {
public:
// These constants convey the state of our knowledge of whether we're in
// incognito context. |extension_prefs| may be NULL in tests.
EventRouter(content::BrowserContext* browser_context,
ExtensionPrefs* extension_prefs);
- virtual ~EventRouter();
+ ~EventRouter() override;
- // Add or remove the process/extension pair as a listener for |event_name|.
+ // Add or remove an extension as an event listener for |event_name|.
+ //
// Note that multiple extensions can share a process due to process
// collapsing. Also, a single extension can have 2 processes if it is a split
// mode extension.
content::RenderProcessHost* process,
const std::string& extension_id);
+ // Add or remove a URL as an event listener for |event_name|.
+ void AddEventListenerForURL(const std::string& event_name,
+ content::RenderProcessHost* process,
+ const GURL& listener_url);
+ void RemoveEventListenerForURL(const std::string& event_name,
+ content::RenderProcessHost* process,
+ const GURL& listener_url);
+
EventListenerMap& listeners() { return listeners_; }
// Registers an observer to be notified when an event listener for
const std::string& extension_id);
private:
- FRIEND_TEST_ALL_PREFIXES(EventRouterTest, EventRouterObserver);
+ friend class EventRouterTest;
// The extension and process that contains the event listener for a given
// event.
UserGestureState user_gesture,
const extensions::EventFilteringInfo& info);
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) override;
+ // ExtensionRegistryObserver implementation.
+ void OnExtensionLoaded(content::BrowserContext* browser_context,
+ const Extension* extension) override;
+ void OnExtensionUnloaded(content::BrowserContext* browser_context,
+ const Extension* extension,
+ UnloadedExtensionInfo::Reason reason) override;
// Returns true if the given listener map contains a event listeners for
// the given event. If |extension_id| is non-empty, we also check that that
const linked_ptr<Event>& event,
std::set<EventDispatchIdentifier>* already_dispatched);
- // Dispatches the event to the specified extension running in |process|.
+ // Dispatches the event to the specified extension or URL running in
+ // |process|.
void DispatchEventToProcess(const std::string& extension_id,
+ const GURL& listener_url,
content::RenderProcessHost* process,
const linked_ptr<Event>& event);
ExtensionHost* host);
// Implementation of EventListenerMap::Delegate.
- virtual void OnListenerAdded(const EventListener* listener) OVERRIDE;
- virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE;
+ void OnListenerAdded(const EventListener* listener) override;
+ void OnListenerRemoved(const EventListener* listener) override;
content::BrowserContext* browser_context_;
content::NotificationRegistrar registrar_;
+ ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
+ extension_registry_observer_;
+
EventListenerMap listeners_;
// Map from base event name to observer.
// allowing the caller to provide different arguments depending on the
// extension and profile. This is guaranteed to be called synchronously with
// DispatchEvent, so callers don't need to worry about lifetime.
+ //
+ // NOTE: the Extension argument to this may be NULL because it's possible for
+ // this event to be dispatched to non-extension processes, like WebUI.
WillDispatchCallback will_dispatch_callback;
- // If true, this event will always be dispatched to ephemeral apps, regardless
- // of whether they are running or inactive. Defaults to false.
- // Most events can only be dispatched to ephemeral apps that are already
- // running. Cached ephemeral apps are inactive until launched by the user.
- bool can_load_ephemeral_apps;
-
Event(const std::string& event_name,
scoped_ptr<base::ListValue> event_args);
struct EventListenerInfo {
EventListenerInfo(const std::string& event_name,
const std::string& extension_id,
+ const GURL& listener_url,
content::BrowserContext* browser_context);
// The event name including any sub-event, e.g. "runtime.onStartup" or
// "webRequest.onCompleted/123".
const std::string event_name;
const std::string extension_id;
+ const GURL listener_url;
content::BrowserContext* browser_context;
};