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