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 // 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 78 // 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 82 // Sends an event via ipc_sender to the given extension. Can be called on any 83 // thread. 84 static void DispatchEvent(IPC::Sender* ipc_sender, 85 void* browser_context_id, 86 const std::string& extension_id, 87 const std::string& event_name, 88 scoped_ptr<base::ListValue> event_args, 89 UserGestureState user_gesture, 90 const EventFilteringInfo& info); 91 92 // 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); 96 virtual ~EventRouter(); 97 98 // 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. 102 void AddEventListener(const std::string& event_name, 103 content::RenderProcessHost* process, 104 const std::string& extension_id); 105 void RemoveEventListener(const std::string& event_name, 106 content::RenderProcessHost* process, 107 const std::string& extension_id); 108 109 EventListenerMap& listeners() { return listeners_; } 110 111 // 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 120 // Sets the observer to be notified whenever an event is dispatched to an 121 // extension. 122 void SetEventDispatchObserver(EventDispatchObserver* observer); 123 124 // 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 133 // 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 148 // Returns true if there is at least one listener for the given event. 149 bool HasEventListener(const std::string& event_name); 150 151 // 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 155 // 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 161 // 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 168 // 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 175 // Record the Event Ack from the renderer. (One less event in-flight.) 176 void OnEventAck(content::BrowserContext* context, 177 const std::string& extension_id); 178 179 private: 180 FRIEND_TEST_ALL_PREFIXES(EventRouterTest, EventRouterObserver); 181 182 // 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; 189 190 // 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 195 // 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); 200 201 // TODO(gdk): Document this. 202 static void DispatchExtensionMessage( 203 IPC::Sender* ipc_sender, 204 void* browser_context_id, 205 const std::string& extension_id, 206 const std::string& event_name, 207 base::ListValue* event_args, 208 UserGestureState user_gesture, 209 const extensions::EventFilteringInfo& info); 210 211 virtual void Observe(int type, 212 const content::NotificationSource& source, 213 const content::NotificationDetails& details) OVERRIDE; 214 215 // 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 222 // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the 223 // event is broadcast. 224 // An event that just came off the pending list may not be delayed again. 225 void DispatchEventImpl(const std::string& restrict_to_extension_id, 226 const linked_ptr<Event>& event); 227 228 // 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. 230 // 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); 235 236 // Dispatches the event to the specified extension running in |process|. 237 void DispatchEventToProcess(const std::string& extension_id, 238 content::RenderProcessHost* process, 239 const linked_ptr<Event>& event); 240 241 // 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 243 // |event_args| with the proper arguments to send, which may differ if 244 // the event crosses the incognito boundary. 245 bool CanDispatchEventToBrowserContext(content::BrowserContext* context, 246 const Extension* extension, 247 const linked_ptr<Event>& event); 248 249 // Possibly loads given extension's background page in preparation to 250 // dispatch an event. Returns true if the event was queued for subsequent 251 // dispatch, false otherwise. 252 bool MaybeLoadLazyBackgroundPageToDispatchEvent( 253 content::BrowserContext* context, 254 const Extension* extension, 255 const linked_ptr<Event>& event); 256 257 // 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 272 // Track of the number of dispatched events that have not yet sent an 273 // ACK from the renderer. 274 void IncrementInFlightEvents(content::BrowserContext* context, 275 const Extension* extension); 276 277 // static 278 static void IncrementInFlightEventsOnUI( 279 void* browser_context_id, 280 const std::string& extension_id); 281 282 void DispatchPendingEvent(const linked_ptr<Event>& event, 283 ExtensionHost* host); 284 285 // Implementation of EventListenerMap::Delegate. 286 virtual void OnListenerAdded(const EventListener* listener) OVERRIDE; 287 virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE; 288 289 content::BrowserContext* browser_context_; 290 291 // The ExtensionPrefs associated with |browser_context_|. May be NULL in 292 // tests. 293 ExtensionPrefs* extension_prefs_; 294 295 content::NotificationRegistrar registrar_; 296 297 EventListenerMap listeners_; 298 299 // Map from base event name to observer. 300 typedef base::hash_map<std::string, Observer*> ObserverMap; 301 ObserverMap observers_; 302 303 EventDispatchObserver* event_dispatch_observer_; 304 305 DISALLOW_COPY_AND_ASSIGN(EventRouter); 306 }; 307 308 struct Event { 309 typedef base::Callback<void(content::BrowserContext*, 310 const Extension*, 311 base::ListValue*)> WillDispatchCallback; 312 313 // The event to dispatch. 314 std::string event_name; 315 316 // Arguments to send to the event listener. 317 scoped_ptr<base::ListValue> event_args; 318 319 // 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; 323 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. 329 EventRouter::UserGestureState user_gesture; 330 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); 343 344 Event(const std::string& event_name, 345 scoped_ptr<base::ListValue> event_args, 346 content::BrowserContext* restrict_to_browser_context); 347 348 Event(const std::string& event_name, 349 scoped_ptr<base::ListValue> event_args, 350 content::BrowserContext* restrict_to_browser_context, 351 const GURL& event_url, 352 EventRouter::UserGestureState user_gesture, 353 const EventFilteringInfo& info); 354 355 ~Event(); 356 357 // Makes a deep copy of this instance. Ownership is transferred to the 358 // caller. 359 Event* DeepCopy(); 360 }; 361 362 struct EventListenerInfo { 363 EventListenerInfo(const std::string& event_name, 364 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". 368 const std::string event_name; 369 370 const std::string extension_id; 371 content::BrowserContext* browser_context; 372 }; 373 374 struct 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 385 } // namespace extensions 386 387 #endif // EXTENSIONS_BROWSER_EVENT_ROUTER_H_ 388