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