blob: d65adb097db5af8d3cfab6a0b9e89e55960936fc [file] [log] [blame]
[email protected]9e6720a2012-01-24 02:30:561// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]2c699652010-10-15 18:22:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]34423532013-11-21 18:13:105#ifndef EXTENSIONS_BROWSER_EVENT_ROUTER_H_
6#define EXTENSIONS_BROWSER_EVENT_ROUTER_H_
[email protected]2c699652010-10-15 18:22:417
8#include <map>
9#include <set>
10#include <string>
[email protected]f3270a02012-10-26 15:54:0511#include <utility>
[email protected]2c699652010-10-15 18:22:4112
[email protected]6e850922012-12-05 03:22:4813#include "base/callback.h"
[email protected]17902752011-08-31 22:52:5414#include "base/compiler_specific.h"
[email protected]14c1c232013-06-11 17:52:4415#include "base/containers/hash_tables.h"
[email protected]c761a962013-11-20 04:19:4116#include "base/gtest_prod_util.h"
[email protected]f72d0c62011-08-31 16:27:4417#include "base/memory/linked_ptr.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/ref_counted.h"
[email protected]8a16a032012-06-18 19:37:3119#include "base/values.h"
[email protected]6c2381d2011-10-19 02:52:5320#include "content/public/browser/notification_observer.h"
21#include "content/public/browser/notification_registrar.h"
[email protected]a0e26d42013-11-20 07:04:0422#include "extensions/browser/event_listener_map.h"
[email protected]4b3e1922013-02-12 04:45:5823#include "extensions/common/event_filtering_info.h"
[email protected]b44f8ad2012-06-15 20:52:5824#include "ipc/ipc_sender.h"
[email protected]2c699652010-10-15 18:22:4125
26class GURL;
[email protected]45fd94172013-11-13 03:29:5227class PrefService;
[email protected]f3b1a082011-11-18 00:34:3028
29namespace content {
[email protected]7061be92013-02-18 15:44:0230class BrowserContext;
[email protected]2c699652010-10-15 18:22:4131class RenderProcessHost;
[email protected]f3b1a082011-11-18 00:34:3032}
[email protected]2c699652010-10-15 18:22:4133
[email protected]1c321ee52012-05-21 03:02:3434namespace extensions {
[email protected]c2ed3f692013-01-31 20:37:3635class ActivityLog;
[email protected]1c321ee52012-05-21 03:02:3436class Extension;
[email protected]3a1dc572012-07-31 22:25:1337class ExtensionHost;
[email protected]79cb81bb2012-09-20 02:23:3138class ExtensionPrefs;
[email protected]3a1dc572012-07-31 22:25:1339
[email protected]5a38dfd2012-07-23 23:22:1040struct Event;
[email protected]72e280f92013-11-20 02:02:3441struct EventDispatchInfo;
[email protected]954e13492012-11-15 03:18:2342struct EventListenerInfo;
[email protected]1c321ee52012-05-21 03:02:3443
[email protected]5a38dfd2012-07-23 23:22:1044class EventRouter : public content::NotificationObserver,
45 public EventListenerMap::Delegate {
[email protected]2c699652010-10-15 18:22:4146 public:
[email protected]b085856f2012-03-02 04:37:2547 // 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
[email protected]e74d43c72013-05-17 19:01:4155 // 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
[email protected]c4dc5cc2012-11-09 08:48:3959 // Observers register interest in events with a particular name and are
[email protected]c761a962013-11-20 04:19:4160 // 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").
[email protected]c4dc5cc2012-11-09 08:48:3963 class Observer {
64 public:
65 // Called when a listener is added.
[email protected]954e13492012-11-15 03:18:2366 virtual void OnListenerAdded(const EventListenerInfo& details) {}
[email protected]c4dc5cc2012-11-09 08:48:3967 // Called when a listener is removed.
[email protected]954e13492012-11-15 03:18:2368 virtual void OnListenerRemoved(const EventListenerInfo& details) {}
[email protected]c4dc5cc2012-11-09 08:48:3969 };
70
[email protected]72e280f92013-11-20 02:02:3471 // 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
[email protected]c761a962013-11-20 04:19:4178 // 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
[email protected]c9bd90f2012-08-07 23:58:1582 // Sends an event via ipc_sender to the given extension. Can be called on any
83 // thread.
[email protected]b44f8ad2012-06-15 20:52:5884 static void DispatchEvent(IPC::Sender* ipc_sender,
[email protected]513b8032013-11-18 07:47:4985 void* browser_context_id,
[email protected]c357acb42011-06-09 20:52:4286 const std::string& extension_id,
87 const std::string& event_name,
[email protected]c9bd90f2012-08-07 23:58:1588 scoped_ptr<base::ListValue> event_args,
[email protected]d9e559d2012-07-05 01:04:5789 UserGestureState user_gesture,
[email protected]5a38dfd2012-07-23 23:22:1090 const EventFilteringInfo& info);
[email protected]5a7b5eaf2010-11-02 20:52:1991
[email protected]45fd94172013-11-13 03:29:5292 // 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);
[email protected]5a38dfd2012-07-23 23:22:1096 virtual ~EventRouter();
[email protected]2c699652010-10-15 18:22:4197
[email protected]a7ab1b782010-10-21 23:24:1698 // 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.
[email protected]2c699652010-10-15 18:22:41102 void AddEventListener(const std::string& event_name,
[email protected]f3b1a082011-11-18 00:34:30103 content::RenderProcessHost* process,
[email protected]a7ab1b782010-10-21 23:24:16104 const std::string& extension_id);
[email protected]2c699652010-10-15 18:22:41105 void RemoveEventListener(const std::string& event_name,
[email protected]f3b1a082011-11-18 00:34:30106 content::RenderProcessHost* process,
[email protected]a7ab1b782010-10-21 23:24:16107 const std::string& extension_id);
[email protected]2c699652010-10-15 18:22:41108
[email protected]f34706be2012-09-04 07:32:09109 EventListenerMap& listeners() { return listeners_; }
110
[email protected]c4dc5cc2012-11-09 08:48:39111 // 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
[email protected]72e280f92013-11-20 02:02:34120 // Sets the observer to be notified whenever an event is dispatched to an
121 // extension.
122 void SetEventDispatchObserver(EventDispatchObserver* observer);
123
[email protected]36531222012-02-07 19:41:27124 // 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
[email protected]d9e559d2012-07-05 01:04:57133 // 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
[email protected]2c699652010-10-15 18:22:41148 // Returns true if there is at least one listener for the given event.
149 bool HasEventListener(const std::string& event_name);
150
[email protected]a7ab1b782010-10-21 23:24:16151 // 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
[email protected]e74d43c72013-05-17 19:01:41155 // 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
[email protected]6e850922012-12-05 03:22:48161 // 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
[email protected]42d24742013-07-23 05:25:55168 // 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
[email protected]89102012011-11-01 21:23:56175 // Record the Event Ack from the renderer. (One less event in-flight.)
[email protected]45fd94172013-11-13 03:29:52176 void OnEventAck(content::BrowserContext* context,
177 const std::string& extension_id);
[email protected]89102012011-11-01 21:23:56178
[email protected]fb6ff23b2012-03-13 23:13:42179 private:
[email protected]c761a962013-11-20 04:19:41180 FRIEND_TEST_ALL_PREFIXES(EventRouterTest, EventRouterObserver);
181
[email protected]61f5fc82012-02-15 20:10:45182 // 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;
[email protected]a7ab1b782010-10-21 23:24:16189
[email protected]f3270a02012-10-26 15:54:05190 // 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
[email protected]72e280f92013-11-20 02:02:34195 // 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);
[email protected]c2ed3f692013-01-31 20:37:36200
[email protected]c9bd90f2012-08-07 23:58:15201 // TODO(gdk): Document this.
202 static void DispatchExtensionMessage(
203 IPC::Sender* ipc_sender,
[email protected]513b8032013-11-18 07:47:49204 void* browser_context_id,
[email protected]c9bd90f2012-08-07 23:58:15205 const std::string& extension_id,
206 const std::string& event_name,
207 base::ListValue* event_args,
[email protected]c9bd90f2012-08-07 23:58:15208 UserGestureState user_gesture,
209 const extensions::EventFilteringInfo& info);
210
[email protected]432115822011-07-10 15:52:27211 virtual void Observe(int type,
[email protected]6c2381d2011-10-19 02:52:53212 const content::NotificationSource& source,
213 const content::NotificationDetails& details) OVERRIDE;
[email protected]2c699652010-10-15 18:22:41214
[email protected]61f5fc82012-02-15 20:10:45215 // 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
[email protected]d9e559d2012-07-05 01:04:57222 // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the
223 // event is broadcast.
[email protected]fb6ff23b2012-03-13 23:13:42224 // An event that just came off the pending list may not be delayed again.
[email protected]d9e559d2012-07-05 01:04:57225 void DispatchEventImpl(const std::string& restrict_to_extension_id,
[email protected]5a38dfd2012-07-23 23:22:10226 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42227
[email protected]d9e559d2012-07-05 01:04:57228 // 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.
[email protected]f3270a02012-10-26 15:54:05230 // 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);
[email protected]d9e559d2012-07-05 01:04:57235
236 // Dispatches the event to the specified extension running in |process|.
237 void DispatchEventToProcess(const std::string& extension_id,
238 content::RenderProcessHost* process,
[email protected]5a38dfd2012-07-23 23:22:10239 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42240
[email protected]45fd94172013-11-13 03:29:52241 // 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
[email protected]fb6ff23b2012-03-13 23:13:42243 // |event_args| with the proper arguments to send, which may differ if
244 // the event crosses the incognito boundary.
[email protected]45fd94172013-11-13 03:29:52245 bool CanDispatchEventToBrowserContext(content::BrowserContext* context,
246 const Extension* extension,
247 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42248
[email protected]fb6ff23b2012-03-13 23:13:42249 // Possibly loads given extension's background page in preparation to
[email protected]6b527572012-10-12 18:00:43250 // dispatch an event. Returns true if the event was queued for subsequent
251 // dispatch, false otherwise.
252 bool MaybeLoadLazyBackgroundPageToDispatchEvent(
[email protected]45fd94172013-11-13 03:29:52253 content::BrowserContext* context,
[email protected]5a38dfd2012-07-23 23:22:10254 const Extension* extension,
255 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42256
[email protected]e74d43c72013-05-17 19:01:41257 // 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
[email protected]fb6ff23b2012-03-13 23:13:42272 // Track of the number of dispatched events that have not yet sent an
273 // ACK from the renderer.
[email protected]45fd94172013-11-13 03:29:52274 void IncrementInFlightEvents(content::BrowserContext* context,
[email protected]5a38dfd2012-07-23 23:22:10275 const Extension* extension);
[email protected]fb6ff23b2012-03-13 23:13:42276
[email protected]db9f2142013-05-27 22:56:16277 // static
278 static void IncrementInFlightEventsOnUI(
[email protected]513b8032013-11-18 07:47:49279 void* browser_context_id,
[email protected]db9f2142013-05-27 22:56:16280 const std::string& extension_id);
281
[email protected]5a38dfd2012-07-23 23:22:10282 void DispatchPendingEvent(const linked_ptr<Event>& event,
[email protected]b6536df2012-03-16 18:55:23283 ExtensionHost* host);
[email protected]fb6ff23b2012-03-13 23:13:42284
[email protected]5a38dfd2012-07-23 23:22:10285 // Implementation of EventListenerMap::Delegate.
[email protected]d9e559d2012-07-05 01:04:57286 virtual void OnListenerAdded(const EventListener* listener) OVERRIDE;
287 virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE;
288
[email protected]45fd94172013-11-13 03:29:52289 content::BrowserContext* browser_context_;
290
[email protected]513b8032013-11-18 07:47:49291 // The ExtensionPrefs associated with |browser_context_|. May be NULL in
292 // tests.
[email protected]45fd94172013-11-13 03:29:52293 ExtensionPrefs* extension_prefs_;
[email protected]2c699652010-10-15 18:22:41294
[email protected]6c2381d2011-10-19 02:52:53295 content::NotificationRegistrar registrar_;
[email protected]2c699652010-10-15 18:22:41296
[email protected]d81d3a192012-11-09 00:32:50297 EventListenerMap listeners_;
[email protected]58c90952012-11-09 00:03:30298
[email protected]c761a962013-11-20 04:19:41299 // Map from base event name to observer.
[email protected]cf118b962012-12-11 03:08:22300 typedef base::hash_map<std::string, Observer*> ObserverMap;
[email protected]c4dc5cc2012-11-09 08:48:39301 ObserverMap observers_;
302
[email protected]72e280f92013-11-20 02:02:34303 EventDispatchObserver* event_dispatch_observer_;
304
[email protected]5a38dfd2012-07-23 23:22:10305 DISALLOW_COPY_AND_ASSIGN(EventRouter);
[email protected]2c699652010-10-15 18:22:41306};
307
[email protected]5a38dfd2012-07-23 23:22:10308struct Event {
[email protected]45fd94172013-11-13 03:29:52309 typedef base::Callback<void(content::BrowserContext*,
310 const Extension*,
311 base::ListValue*)> WillDispatchCallback;
[email protected]6e850922012-12-05 03:22:48312
313 // The event to dispatch.
[email protected]d9e559d2012-07-05 01:04:57314 std::string event_name;
[email protected]6e850922012-12-05 03:22:48315
316 // Arguments to send to the event listener.
[email protected]c9bd90f2012-08-07 23:58:15317 scoped_ptr<base::ListValue> event_args;
[email protected]6e850922012-12-05 03:22:48318
[email protected]45fd94172013-11-13 03:29:52319 // 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;
[email protected]6e850922012-12-05 03:22:48323
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.
[email protected]5a38dfd2012-07-23 23:22:10329 EventRouter::UserGestureState user_gesture;
[email protected]6e850922012-12-05 03:22:48330
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);
[email protected]d9e559d2012-07-05 01:04:57343
[email protected]5a38dfd2012-07-23 23:22:10344 Event(const std::string& event_name,
[email protected]c9bd90f2012-08-07 23:58:15345 scoped_ptr<base::ListValue> event_args,
[email protected]45fd94172013-11-13 03:29:52346 content::BrowserContext* restrict_to_browser_context);
[email protected]f0eb58a2012-12-17 22:10:49347
348 Event(const std::string& event_name,
349 scoped_ptr<base::ListValue> event_args,
[email protected]45fd94172013-11-13 03:29:52350 content::BrowserContext* restrict_to_browser_context,
[email protected]6e850922012-12-05 03:22:48351 const GURL& event_url,
[email protected]5a38dfd2012-07-23 23:22:10352 EventRouter::UserGestureState user_gesture,
353 const EventFilteringInfo& info);
[email protected]d9e559d2012-07-05 01:04:57354
[email protected]5a38dfd2012-07-23 23:22:10355 ~Event();
[email protected]6e850922012-12-05 03:22:48356
357 // Makes a deep copy of this instance. Ownership is transferred to the
358 // caller.
359 Event* DeepCopy();
[email protected]d9e559d2012-07-05 01:04:57360};
361
[email protected]954e13492012-11-15 03:18:23362struct EventListenerInfo {
363 EventListenerInfo(const std::string& event_name,
[email protected]c761a962013-11-20 04:19:41364 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".
[email protected]954e13492012-11-15 03:18:23368 const std::string event_name;
[email protected]c761a962013-11-20 04:19:41369
[email protected]954e13492012-11-15 03:18:23370 const std::string extension_id;
[email protected]c761a962013-11-20 04:19:41371 content::BrowserContext* browser_context;
[email protected]954e13492012-11-15 03:18:23372};
373
[email protected]72e280f92013-11-20 02:02:34374struct 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
[email protected]5a38dfd2012-07-23 23:22:10385} // namespace extensions
[email protected]d9e559d2012-07-05 01:04:57386
[email protected]34423532013-11-21 18:13:10387#endif // EXTENSIONS_BROWSER_EVENT_ROUTER_H_