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