blob: f0cf6abb288cc526e753c5116158b285c3c35801 [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]5a38dfd2012-07-23 23:22:105#ifndef CHROME_BROWSER_EXTENSIONS_EVENT_ROUTER_H_
6#define CHROME_BROWSER_EXTENSIONS_EVENT_ROUTER_H_
[email protected]2c699652010-10-15 18:22:417
8#include <map>
9#include <set>
10#include <string>
11
[email protected]17902752011-08-31 22:52:5412#include "base/compiler_specific.h"
[email protected]f72d0c62011-08-31 16:27:4413#include "base/memory/linked_ptr.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/ref_counted.h"
[email protected]8a16a032012-06-18 19:37:3115#include "base/values.h"
[email protected]d9e559d2012-07-05 01:04:5716#include "chrome/browser/extensions/event_listener_map.h"
17#include "chrome/common/extensions/event_filtering_info.h"
[email protected]6c2381d2011-10-19 02:52:5318#include "content/public/browser/notification_observer.h"
19#include "content/public/browser/notification_registrar.h"
[email protected]b44f8ad2012-06-15 20:52:5820#include "ipc/ipc_sender.h"
[email protected]2c699652010-10-15 18:22:4121
22class GURL;
[email protected]b6536df2012-03-16 18:55:2323class ExtensionHost;
[email protected]2c699652010-10-15 18:22:4124class ExtensionDevToolsManager;
25class Profile;
[email protected]f3b1a082011-11-18 00:34:3026
27namespace content {
[email protected]2c699652010-10-15 18:22:4128class RenderProcessHost;
[email protected]f3b1a082011-11-18 00:34:3029}
[email protected]2c699652010-10-15 18:22:4130
[email protected]1c321ee2012-05-21 03:02:3431namespace extensions {
32class Extension;
[email protected]5a38dfd2012-07-23 23:22:1033struct Event;
[email protected]1c321ee2012-05-21 03:02:3434
[email protected]5a38dfd2012-07-23 23:22:1035class EventRouter : public content::NotificationObserver,
36 public EventListenerMap::Delegate {
[email protected]2c699652010-10-15 18:22:4137 public:
[email protected]b085856f2012-03-02 04:37:2538 // These constants convey the state of our knowledge of whether we're in
39 // a user-caused gesture as part of DispatchEvent.
40 enum UserGestureState {
41 USER_GESTURE_UNKNOWN = 0,
42 USER_GESTURE_ENABLED = 1,
43 USER_GESTURE_NOT_ENABLED = 2,
44 };
45
[email protected]c357acb42011-06-09 20:52:4246 // Sends an event via ipc_sender to the given extension. Can be called on
47 // any thread.
[email protected]b44f8ad2012-06-15 20:52:5848 static void DispatchEvent(IPC::Sender* ipc_sender,
[email protected]c357acb42011-06-09 20:52:4249 const std::string& extension_id,
50 const std::string& event_name,
[email protected]8a16a032012-06-18 19:37:3151 const base::Value& event_args,
52 const GURL& event_url,
[email protected]d9e559d2012-07-05 01:04:5753 UserGestureState user_gesture,
[email protected]5a38dfd2012-07-23 23:22:1054 const EventFilteringInfo& info);
[email protected]8a16a032012-06-18 19:37:3155
56 // This invocation is deprecated. All future consumers of this API should be
57 // sending Values as event arguments, using the above version.
58 static void DispatchEvent(IPC::Sender* ipc_sender,
59 const std::string& extension_id,
60 const std::string& event_name,
[email protected]c357acb42011-06-09 20:52:4261 const std::string& event_args,
[email protected]b085856f2012-03-02 04:37:2562 const GURL& event_url,
[email protected]d9e559d2012-07-05 01:04:5763 UserGestureState user_gesture,
[email protected]5a38dfd2012-07-23 23:22:1064 const EventFilteringInfo& info);
[email protected]5a7b5eaf2010-11-02 20:52:1965
[email protected]5a38dfd2012-07-23 23:22:1066 explicit EventRouter(Profile* profile);
67 virtual ~EventRouter();
[email protected]2c699652010-10-15 18:22:4168
[email protected]a7ab1b782010-10-21 23:24:1669 // Add or remove the process/extension pair as a listener for |event_name|.
70 // Note that multiple extensions can share a process due to process
71 // collapsing. Also, a single extension can have 2 processes if it is a split
72 // mode extension.
[email protected]2c699652010-10-15 18:22:4173 void AddEventListener(const std::string& event_name,
[email protected]f3b1a082011-11-18 00:34:3074 content::RenderProcessHost* process,
[email protected]a7ab1b782010-10-21 23:24:1675 const std::string& extension_id);
[email protected]2c699652010-10-15 18:22:4176 void RemoveEventListener(const std::string& event_name,
[email protected]f3b1a082011-11-18 00:34:3077 content::RenderProcessHost* process,
[email protected]a7ab1b782010-10-21 23:24:1678 const std::string& extension_id);
[email protected]2c699652010-10-15 18:22:4179
[email protected]36531222012-02-07 19:41:2780 // Add or remove the extension as having a lazy background page that listens
81 // to the event. The difference from the above methods is that these will be
82 // remembered even after the process goes away. We use this list to decide
83 // which extension pages to load when dispatching an event.
84 void AddLazyEventListener(const std::string& event_name,
85 const std::string& extension_id);
86 void RemoveLazyEventListener(const std::string& event_name,
87 const std::string& extension_id);
88
[email protected]d9e559d2012-07-05 01:04:5789 // If |add_lazy_listener| is true also add the lazy version of this listener.
90 void AddFilteredEventListener(const std::string& event_name,
91 content::RenderProcessHost* process,
92 const std::string& extension_id,
93 const base::DictionaryValue& filter,
94 bool add_lazy_listener);
95
96 // If |remove_lazy_listener| is true also remove the lazy version of this
97 // listener.
98 void RemoveFilteredEventListener(const std::string& event_name,
99 content::RenderProcessHost* process,
100 const std::string& extension_id,
101 const base::DictionaryValue& filter,
102 bool remove_lazy_listener);
103
[email protected]2c699652010-10-15 18:22:41104 // Returns true if there is at least one listener for the given event.
105 bool HasEventListener(const std::string& event_name);
106
[email protected]a7ab1b782010-10-21 23:24:16107 // Returns true if the extension is listening to the given event.
108 bool ExtensionHasEventListener(const std::string& extension_id,
109 const std::string& event_name);
110
[email protected]2c699652010-10-15 18:22:41111 // Send an event to every registered extension renderer. If
112 // |restrict_to_profile| is non-NULL, then the event will not be sent to other
113 // profiles unless the extension has permission (e.g. incognito tab update ->
114 // normal profile only works if extension is allowed incognito access). If
115 // |event_url| is not empty, the event is only sent to extension with host
116 // permissions for this url.
[email protected]5a38dfd2012-07-23 23:22:10117 void DispatchEventToRenderers(const std::string& event_name,
118 const std::string& event_args,
119 Profile* restrict_to_profile,
120 const GURL& event_url,
121 EventFilteringInfo info);
[email protected]d9e559d2012-07-05 01:04:57122
123 // As above, but defaults |info| to EventFilteringInfo().
[email protected]5a38dfd2012-07-23 23:22:10124 void DispatchEventToRenderers(const std::string& event_name,
125 const std::string& event_args,
126 Profile* restrict_to_profile,
127 const GURL& event_url);
[email protected]2c699652010-10-15 18:22:41128
[email protected]a7ab1b782010-10-21 23:24:16129 // Same as above, except only send the event to the given extension.
[email protected]5a38dfd2012-07-23 23:22:10130 virtual void DispatchEventToExtension(const std::string& extension_id,
131 const std::string& event_name,
132 const base::Value& event_args,
133 Profile* restrict_to_profile,
134 const GURL& event_url);
[email protected]8a16a032012-06-18 19:37:31135
136 // This invocation is deprecated. The above variant which uses a Value for
137 // event_args is to be used instead.
[email protected]5a38dfd2012-07-23 23:22:10138 virtual void DispatchEventToExtension(const std::string& extension_id,
139 const std::string& event_name,
140 const std::string& event_args,
141 Profile* restrict_to_profile,
142 const GURL& event_url);
[email protected]0a184b52011-06-23 00:41:13143
[email protected]b085856f2012-03-02 04:37:25144 // Dispatch an event to particular extension. Also include an
145 // explicit user gesture indicator.
[email protected]5a38dfd2012-07-23 23:22:10146 virtual void DispatchEventToExtension(const std::string& extension_id,
147 const std::string& event_name,
148 const std::string& event_args,
149 Profile* restrict_to_profile,
150 const GURL& event_url,
151 UserGestureState user_gesture);
[email protected]b085856f2012-03-02 04:37:25152
[email protected]0a184b52011-06-23 00:41:13153 // Send different versions of an event to extensions in different profiles.
154 // This is used in the case of sending one event to extensions that have
155 // incognito access, and another event to extensions that don't (here),
156 // in order to avoid sending 2 events to "spanning" extensions.
157 // If |cross_incognito_profile| is non-NULL and different from
158 // restrict_to_profile, send the event with cross_incognito_args to the
159 // extensions in that profile that can't cross incognito.
160 void DispatchEventsToRenderersAcrossIncognito(
161 const std::string& event_name,
162 const std::string& event_args,
163 Profile* restrict_to_profile,
164 const std::string& cross_incognito_args,
165 const GURL& event_url);
[email protected]2c699652010-10-15 18:22:41166
[email protected]89102012011-11-01 21:23:56167 // Record the Event Ack from the renderer. (One less event in-flight.)
[email protected]7042b682012-04-19 22:57:51168 void OnEventAck(Profile* profile, const std::string& extension_id);
[email protected]89102012011-11-01 21:23:56169
[email protected]fb6ff23b2012-03-13 23:13:42170 private:
[email protected]61f5fc82012-02-15 20:10:45171 // The extension and process that contains the event listener for a given
172 // event.
173 struct ListenerProcess;
174
175 // A map between an event name and a set of extensions that are listening
176 // to that event.
177 typedef std::map<std::string, std::set<ListenerProcess> > ListenerMap;
[email protected]a7ab1b782010-10-21 23:24:16178
[email protected]432115822011-07-10 15:52:27179 virtual void Observe(int type,
[email protected]6c2381d2011-10-19 02:52:53180 const content::NotificationSource& source,
181 const content::NotificationDetails& details) OVERRIDE;
[email protected]2c699652010-10-15 18:22:41182
[email protected]61f5fc82012-02-15 20:10:45183 // Returns true if the given listener map contains a event listeners for
184 // the given event. If |extension_id| is non-empty, we also check that that
185 // extension is one of the listeners.
186 bool HasEventListenerImpl(const ListenerMap& listeners,
187 const std::string& extension_id,
188 const std::string& event_name);
189
[email protected]d9e559d2012-07-05 01:04:57190 // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the
191 // event is broadcast.
[email protected]fb6ff23b2012-03-13 23:13:42192 // An event that just came off the pending list may not be delayed again.
[email protected]d9e559d2012-07-05 01:04:57193 void DispatchEventImpl(const std::string& restrict_to_extension_id,
[email protected]5a38dfd2012-07-23 23:22:10194 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42195
[email protected]d9e559d2012-07-05 01:04:57196 // Ensures that all lazy background pages that are interested in the given
197 // event are loaded, and queues the event if the page is not ready yet.
198 void DispatchLazyEvent(const std::string& extension_id,
[email protected]5a38dfd2012-07-23 23:22:10199 const linked_ptr<Event>& event);
[email protected]d9e559d2012-07-05 01:04:57200
201 // Dispatches the event to the specified extension running in |process|.
202 void DispatchEventToProcess(const std::string& extension_id,
203 content::RenderProcessHost* process,
[email protected]5a38dfd2012-07-23 23:22:10204 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42205
206 // Returns false when the event is scoped to a profile and the listening
207 // extension does not have access to events from that profile. Also fills
208 // |event_args| with the proper arguments to send, which may differ if
209 // the event crosses the incognito boundary.
[email protected]5a38dfd2012-07-23 23:22:10210 bool CanDispatchEventToProfile(Profile* profile,
211 const Extension* extension,
212 const linked_ptr<Event>& event,
213 const base::Value** event_args);
[email protected]fb6ff23b2012-03-13 23:13:42214
[email protected]fb6ff23b2012-03-13 23:13:42215 // Possibly loads given extension's background page in preparation to
216 // dispatch an event.
[email protected]d9e559d2012-07-05 01:04:57217 void MaybeLoadLazyBackgroundPageToDispatchEvent(
[email protected]fb6ff23b2012-03-13 23:13:42218 Profile* profile,
[email protected]5a38dfd2012-07-23 23:22:10219 const Extension* extension,
220 const linked_ptr<Event>& event);
[email protected]fb6ff23b2012-03-13 23:13:42221
[email protected]fb6ff23b2012-03-13 23:13:42222 // Track of the number of dispatched events that have not yet sent an
223 // ACK from the renderer.
[email protected]1c321ee2012-05-21 03:02:34224 void IncrementInFlightEvents(Profile* profile,
[email protected]5a38dfd2012-07-23 23:22:10225 const Extension* extension);
[email protected]fb6ff23b2012-03-13 23:13:42226
[email protected]5a38dfd2012-07-23 23:22:10227 void DispatchPendingEvent(const linked_ptr<Event>& event,
[email protected]b6536df2012-03-16 18:55:23228 ExtensionHost* host);
[email protected]fb6ff23b2012-03-13 23:13:42229
[email protected]5a38dfd2012-07-23 23:22:10230 // Implementation of EventListenerMap::Delegate.
[email protected]d9e559d2012-07-05 01:04:57231 virtual void OnListenerAdded(const EventListener* listener) OVERRIDE;
232 virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE;
233
[email protected]2c699652010-10-15 18:22:41234 Profile* profile_;
235
[email protected]6c2381d2011-10-19 02:52:53236 content::NotificationRegistrar registrar_;
[email protected]2c699652010-10-15 18:22:41237
238 scoped_refptr<ExtensionDevToolsManager> extension_devtools_manager_;
239
[email protected]d9e559d2012-07-05 01:04:57240 EventListenerMap listeners_;
[email protected]36531222012-02-07 19:41:27241
[email protected]5a38dfd2012-07-23 23:22:10242 DISALLOW_COPY_AND_ASSIGN(EventRouter);
[email protected]2c699652010-10-15 18:22:41243};
244
[email protected]5a38dfd2012-07-23 23:22:10245struct Event {
[email protected]d9e559d2012-07-05 01:04:57246 std::string event_name;
247 scoped_ptr<Value> event_args;
248 GURL event_url;
249 Profile* restrict_to_profile;
250 scoped_ptr<Value> cross_incognito_args;
[email protected]5a38dfd2012-07-23 23:22:10251 EventRouter::UserGestureState user_gesture;
252 EventFilteringInfo info;
[email protected]d9e559d2012-07-05 01:04:57253
[email protected]5a38dfd2012-07-23 23:22:10254 Event(const std::string& event_name,
255 const Value& event_args,
256 const GURL& event_url,
257 Profile* restrict_to_profile,
258 const Value& cross_incognito_args,
259 EventRouter::UserGestureState user_gesture,
260 const EventFilteringInfo& info);
[email protected]d9e559d2012-07-05 01:04:57261
262 // TODO(gdk): This variant should be retired once the callers are switched to
263 // providing Values instead of just strings.
[email protected]5a38dfd2012-07-23 23:22:10264 Event(const std::string& event_name,
265 const std::string& event_args,
266 const GURL& event_url,
267 Profile* restrict_to_profile,
268 const std::string& cross_incognito_args,
269 EventRouter::UserGestureState user_gesture,
270 const EventFilteringInfo& info);
[email protected]d9e559d2012-07-05 01:04:57271
[email protected]5a38dfd2012-07-23 23:22:10272 Event(const std::string& event_name,
273 const Value& event_args,
274 const GURL& event_url,
275 Profile* restrict_to_profile,
276 EventRouter::UserGestureState user_gesture,
277 const EventFilteringInfo& info);
[email protected]d9e559d2012-07-05 01:04:57278
[email protected]5a38dfd2012-07-23 23:22:10279 ~Event();
[email protected]d9e559d2012-07-05 01:04:57280};
281
[email protected]5a38dfd2012-07-23 23:22:10282} // namespace extensions
[email protected]d9e559d2012-07-05 01:04:57283
[email protected]5a38dfd2012-07-23 23:22:10284#endif // CHROME_BROWSER_EXTENSIONS_EVENT_ROUTER_H_