| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_event_router.h" | 5 #include "chrome/browser/extensions/extension_event_router.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 | 58 |
| 59 bool operator<(const ListenerProcess& that) const { | 59 bool operator<(const ListenerProcess& that) const { |
| 60 if (process < that.process) | 60 if (process < that.process) |
| 61 return true; | 61 return true; |
| 62 if (process == that.process && extension_id < that.extension_id) | 62 if (process == that.process && extension_id < that.extension_id) |
| 63 return true; | 63 return true; |
| 64 return false; | 64 return false; |
| 65 } | 65 } |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 struct ExtensionEventRouter::ExtensionEvent { | |
| 69 std::string event_name; | |
| 70 std::string event_args; | |
| 71 GURL event_url; | |
| 72 Profile* restrict_to_profile; | |
| 73 std::string cross_incognito_args; | |
| 74 UserGestureState user_gesture; | |
| 75 | |
| 76 ExtensionEvent(const std::string& event_name, | |
| 77 const std::string& event_args, | |
| 78 const GURL& event_url, | |
| 79 Profile* restrict_to_profile, | |
| 80 const std::string& cross_incognito_args, | |
| 81 UserGestureState user_gesture) | |
| 82 : event_name(event_name), | |
| 83 event_args(event_args), | |
| 84 event_url(event_url), | |
| 85 restrict_to_profile(restrict_to_profile), | |
| 86 cross_incognito_args(cross_incognito_args), | |
| 87 user_gesture(user_gesture) {} | |
| 88 }; | |
| 89 | |
| 90 // static | 68 // static |
| 91 void ExtensionEventRouter::DispatchEvent(IPC::Message::Sender* ipc_sender, | 69 void ExtensionEventRouter::DispatchEvent( |
| 92 const std::string& extension_id, | 70 IPC::Message::Sender* ipc_sender, |
| 93 const std::string& event_name, | 71 const std::string& extension_id, |
| 94 const std::string& event_args, | 72 const std::string& event_name, |
| 95 const GURL& event_url, | 73 const std::string& event_args, |
| 96 UserGestureState user_gesture) { | 74 const GURL& event_url, |
| 75 UserGestureState user_gesture, |
| 76 const extensions::EventFilteringInfo& info) { |
| 97 ListValue args; | 77 ListValue args; |
| 98 args.Set(0, Value::CreateStringValue(event_name)); | 78 args.Set(0, Value::CreateStringValue(event_name)); |
| 99 args.Set(1, Value::CreateStringValue(event_args)); | 79 args.Set(1, Value::CreateStringValue(event_args)); |
| 80 args.Set(2, Value::CreateStringValue(info.AsJSONString())); |
| 100 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | 81 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, |
| 101 extension_id, kDispatchEvent, args, event_url, | 82 extension_id, kDispatchEvent, args, event_url, |
| 102 user_gesture == USER_GESTURE_ENABLED)); | 83 user_gesture == USER_GESTURE_ENABLED)); |
| 103 } | 84 } |
| 104 | 85 |
| 105 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) | 86 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) |
| 106 : profile_(profile), | 87 : profile_(profile), |
| 107 extension_devtools_manager_( | 88 extension_devtools_manager_( |
| 108 ExtensionSystem::Get(profile)->devtools_manager()) { | 89 ExtensionSystem::Get(profile)->devtools_manager()), |
| 90 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 109 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 91 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 110 content::NotificationService::AllSources()); | 92 content::NotificationService::AllSources()); |
| 111 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 93 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 112 content::NotificationService::AllSources()); | 94 content::NotificationService::AllSources()); |
| 113 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 95 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| 114 content::Source<Profile>(profile_)); | 96 content::Source<Profile>(profile_)); |
| 115 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 97 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 116 content::Source<Profile>(profile_)); | 98 content::Source<Profile>(profile_)); |
| 117 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | 99 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
| 118 content::Source<Profile>(profile_)); | 100 content::Source<Profile>(profile_)); |
| 119 } | 101 } |
| 120 | 102 |
| 121 ExtensionEventRouter::~ExtensionEventRouter() {} | 103 ExtensionEventRouter::~ExtensionEventRouter() {} |
| 122 | 104 |
| 123 void ExtensionEventRouter::AddEventListener( | 105 void ExtensionEventRouter::AddEventListener( |
| 124 const std::string& event_name, | 106 const std::string& event_name, |
| 125 content::RenderProcessHost* process, | 107 content::RenderProcessHost* process, |
| 126 const std::string& extension_id) { | 108 const std::string& extension_id) { |
| 127 ListenerProcess listener(process, extension_id); | 109 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( |
| 128 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; | 110 event_name, extension_id, process, scoped_ptr<DictionaryValue>()))); |
| 129 listeners_[event_name].insert(listener); | |
| 130 | 111 |
| 131 if (extension_devtools_manager_.get()) | 112 if (extension_devtools_manager_.get()) |
| 132 extension_devtools_manager_->AddEventListener(event_name, | 113 extension_devtools_manager_->AddEventListener(event_name, |
| 133 process->GetID()); | 114 process->GetID()); |
| 134 | 115 |
| 135 // We lazily tell the TaskManager to start updating when listeners to the | 116 // We lazily tell the TaskManager to start updating when listeners to the |
| 136 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. | 117 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. |
| 137 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || | 118 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || |
| 138 event_name.compare( | 119 event_name.compare( |
| 139 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) | 120 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) |
| 140 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); | 121 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); |
| 141 } | 122 } |
| 142 | 123 |
| 143 void ExtensionEventRouter::RemoveEventListener( | 124 void ExtensionEventRouter::RemoveEventListener( |
| 144 const std::string& event_name, | 125 const std::string& event_name, |
| 145 content::RenderProcessHost* process, | 126 content::RenderProcessHost* process, |
| 146 const std::string& extension_id) { | 127 const std::string& extension_id) { |
| 147 ListenerProcess listener(process, extension_id); | 128 scoped_ptr<EventListener> listener(new EventListener( |
| 148 DCHECK_EQ(listeners_[event_name].count(listener), 1u) << | 129 event_name, extension_id, process, scoped_ptr<DictionaryValue>())); |
| 149 " PID=" << process->GetID() << " extension=" << extension_id << | 130 listeners_.RemoveListener(*listener); |
| 150 " event=" << event_name; | 131 } |
| 151 listeners_[event_name].erase(listener); | |
| 152 // Note: extension_id may point to data in the now-deleted listeners_ object. | |
| 153 // Do not use. | |
| 154 | 132 |
| 133 void ExtensionEventRouter::OnListenerRemoved(const EventListener* listener) { |
| 134 // We don't care about lazy events being removed. |
| 135 if (!listener->process) |
| 136 return; |
| 137 |
| 138 const std::string& event_name = listener->event_name; |
| 155 if (extension_devtools_manager_.get()) | 139 if (extension_devtools_manager_.get()) |
| 156 extension_devtools_manager_->RemoveEventListener(event_name, | 140 extension_devtools_manager_->RemoveEventListener( |
| 157 process->GetID()); | 141 event_name, listener->process->GetID()); |
| 158 | 142 |
| 159 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener | 143 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener |
| 160 // is removed (or a process with one exits), then we let the extension API | 144 // is removed (or a process with one exits), then we let the extension API |
| 161 // know that it has one fewer listener. | 145 // know that it has one fewer listener. |
| 162 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || | 146 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || |
| 163 event_name.compare( | 147 event_name.compare( |
| 164 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) | 148 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) |
| 165 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); | 149 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); |
| 166 | 150 |
| 167 BrowserThread::PostTask( | 151 BrowserThread::PostTask( |
| 168 BrowserThread::IO, FROM_HERE, | 152 BrowserThread::IO, FROM_HERE, |
| 169 base::Bind( | 153 base::Bind( |
| 170 &NotifyEventListenerRemovedOnIOThread, | 154 &NotifyEventListenerRemovedOnIOThread, |
| 171 profile_, listener.extension_id, event_name)); | 155 profile_, listener->extension_id, listener->event_name)); |
| 172 } | 156 } |
| 173 | 157 |
| 174 void ExtensionEventRouter::AddLazyEventListener( | 158 void ExtensionEventRouter::AddLazyEventListener( |
| 175 const std::string& event_name, | 159 const std::string& event_name, |
| 176 const std::string& extension_id) { | 160 const std::string& extension_id) { |
| 177 ListenerProcess lazy_listener(NULL, extension_id); | 161 scoped_ptr<EventListener> listener(new EventListener( |
| 178 bool is_new = lazy_listeners_[event_name].insert(lazy_listener).second; | 162 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>())); |
| 163 bool is_new = listeners_.AddListener(listener.Pass()); |
| 164 |
| 179 if (is_new) { | 165 if (is_new) { |
| 180 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 166 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
| 181 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); | 167 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); |
| 182 bool prefs_is_new = events.insert(event_name).second; | 168 bool prefs_is_new = events.insert(event_name).second; |
| 183 if (prefs_is_new) | 169 if (prefs_is_new) |
| 184 prefs->SetRegisteredEvents(extension_id, events); | 170 prefs->SetRegisteredEvents(extension_id, events); |
| 185 } | 171 } |
| 186 } | 172 } |
| 187 | 173 |
| 188 void ExtensionEventRouter::RemoveLazyEventListener( | 174 void ExtensionEventRouter::RemoveLazyEventListener( |
| 189 const std::string& event_name, | 175 const std::string& event_name, |
| 190 const std::string& extension_id) { | 176 const std::string& extension_id) { |
| 191 ListenerProcess lazy_listener(NULL, extension_id); | 177 scoped_ptr<EventListener> listener(new EventListener( |
| 192 bool did_exist = lazy_listeners_[event_name].erase(lazy_listener) > 0; | 178 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>())); |
| 179 bool did_exist = listeners_.RemoveListener(*listener); |
| 180 |
| 193 if (did_exist) { | 181 if (did_exist) { |
| 194 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 182 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
| 195 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); | 183 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); |
| 196 bool prefs_did_exist = events.erase(event_name) > 0; | 184 bool prefs_did_exist = events.erase(event_name) > 0; |
| 197 DCHECK(prefs_did_exist); | 185 DCHECK(prefs_did_exist); |
| 198 prefs->SetRegisteredEvents(extension_id, events); | 186 prefs->SetRegisteredEvents(extension_id, events); |
| 199 } | 187 } |
| 200 } | 188 } |
| 201 | 189 |
| 190 void ExtensionEventRouter::AddFilteredEventListener( |
| 191 const std::string& event_name, |
| 192 content::RenderProcessHost* process, |
| 193 const std::string& extension_id, |
| 194 const base::DictionaryValue& filter, |
| 195 bool add_lazy_listener) { |
| 196 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( |
| 197 event_name, extension_id, process, |
| 198 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); |
| 199 |
| 200 if (add_lazy_listener) { |
| 201 bool added = listeners_.AddListener(scoped_ptr<EventListener>( |
| 202 new EventListener(event_name, extension_id, NULL, |
| 203 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); |
| 204 |
| 205 if (added) { |
| 206 ExtensionPrefs* prefs = |
| 207 profile_->GetExtensionService()->extension_prefs(); |
| 208 prefs->AddFilterToEvent(event_name, extension_id, &filter); |
| 209 } |
| 210 } |
| 211 } |
| 212 |
| 213 void ExtensionEventRouter::RemoveFilteredEventListener( |
| 214 const std::string& event_name, |
| 215 content::RenderProcessHost* process, |
| 216 const std::string& extension_id, |
| 217 const base::DictionaryValue& filter, |
| 218 bool remove_lazy_listener) { |
| 219 scoped_ptr<EventListener> listener(new EventListener( |
| 220 event_name, extension_id, process, |
| 221 scoped_ptr<DictionaryValue>(filter.DeepCopy()))); |
| 222 |
| 223 listeners_.RemoveListener(*listener); |
| 224 |
| 225 if (remove_lazy_listener) { |
| 226 listener->process = NULL; |
| 227 bool removed = listeners_.RemoveListener(*listener); |
| 228 |
| 229 if (removed) { |
| 230 ExtensionPrefs* prefs = |
| 231 profile_->GetExtensionService()->extension_prefs(); |
| 232 prefs->RemoveFilterFromEvent(event_name, extension_id, &filter); |
| 233 } |
| 234 } |
| 235 } |
| 236 |
| 202 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { | 237 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { |
| 203 return (HasEventListenerImpl(listeners_, "", event_name) || | 238 return listeners_.HasListenerForEvent(event_name); |
| 204 HasEventListenerImpl(lazy_listeners_, "", event_name)); | |
| 205 } | 239 } |
| 206 | 240 |
| 207 bool ExtensionEventRouter::ExtensionHasEventListener( | 241 bool ExtensionEventRouter::ExtensionHasEventListener( |
| 208 const std::string& extension_id, const std::string& event_name) { | 242 const std::string& extension_id, const std::string& event_name) { |
| 209 return (HasEventListenerImpl(listeners_, extension_id, event_name) || | 243 return listeners_.HasListenerForExtension(extension_id, event_name); |
| 210 HasEventListenerImpl(lazy_listeners_, extension_id, event_name)); | |
| 211 } | 244 } |
| 212 | 245 |
| 213 bool ExtensionEventRouter::HasEventListenerImpl( | 246 bool ExtensionEventRouter::HasEventListenerImpl( |
| 214 const ListenerMap& listener_map, | 247 const ListenerMap& listener_map, |
| 215 const std::string& extension_id, | 248 const std::string& extension_id, |
| 216 const std::string& event_name) { | 249 const std::string& event_name) { |
| 217 ListenerMap::const_iterator it = listener_map.find(event_name); | 250 ListenerMap::const_iterator it = listener_map.find(event_name); |
| 218 if (it == listener_map.end()) | 251 if (it == listener_map.end()) |
| 219 return false; | 252 return false; |
| 220 | 253 |
| 221 const std::set<ListenerProcess>& listeners = it->second; | 254 const std::set<ListenerProcess>& listeners = it->second; |
| 222 if (extension_id.empty()) | 255 if (extension_id.empty()) |
| 223 return !listeners.empty(); | 256 return !listeners.empty(); |
| 224 | 257 |
| 225 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); | 258 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); |
| 226 listener != listeners.end(); ++listener) { | 259 listener != listeners.end(); ++listener) { |
| 227 if (listener->extension_id == extension_id) | 260 if (listener->extension_id == extension_id) |
| 228 return true; | 261 return true; |
| 229 } | 262 } |
| 230 return false; | 263 return false; |
| 231 } | 264 } |
| 232 | 265 |
| 233 void ExtensionEventRouter::DispatchEventToRenderers( | 266 void ExtensionEventRouter::DispatchEventToRenderers( |
| 234 const std::string& event_name, | 267 const std::string& event_name, |
| 235 const std::string& event_args, | 268 const std::string& event_args, |
| 236 Profile* restrict_to_profile, | 269 Profile* restrict_to_profile, |
| 237 const GURL& event_url) { | 270 const GURL& event_url, |
| 271 extensions::EventFilteringInfo info) { |
| 238 linked_ptr<ExtensionEvent> event( | 272 linked_ptr<ExtensionEvent> event( |
| 239 new ExtensionEvent(event_name, event_args, event_url, | 273 new ExtensionEvent(event_name, event_args, event_url, |
| 240 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); | 274 restrict_to_profile, "", USER_GESTURE_UNKNOWN, info)); |
| 241 DispatchEventImpl("", event); | 275 DispatchEventImpl("", event); |
| 242 } | 276 } |
| 243 | 277 |
| 244 void ExtensionEventRouter::DispatchEventToExtension( | 278 void ExtensionEventRouter::DispatchEventToExtension( |
| 245 const std::string& extension_id, | 279 const std::string& extension_id, |
| 246 const std::string& event_name, | 280 const std::string& event_name, |
| 247 const std::string& event_args, | 281 const std::string& event_args, |
| 248 Profile* restrict_to_profile, | 282 Profile* restrict_to_profile, |
| 249 const GURL& event_url) { | 283 const GURL& event_url) { |
| 250 DCHECK(!extension_id.empty()); | 284 DCHECK(!extension_id.empty()); |
| 251 linked_ptr<ExtensionEvent> event( | 285 linked_ptr<ExtensionEvent> event( |
| 252 new ExtensionEvent(event_name, event_args, event_url, | 286 new ExtensionEvent(event_name, event_args, event_url, |
| 253 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); | 287 restrict_to_profile, "", USER_GESTURE_UNKNOWN, |
| 288 EventFilteringInfo())); |
| 254 DispatchEventImpl(extension_id, event); | 289 DispatchEventImpl(extension_id, event); |
| 255 } | 290 } |
| 256 | 291 |
| 257 void ExtensionEventRouter::DispatchEventToExtension( | 292 void ExtensionEventRouter::DispatchEventToExtension( |
| 258 const std::string& extension_id, | 293 const std::string& extension_id, |
| 259 const std::string& event_name, | 294 const std::string& event_name, |
| 260 const std::string& event_args, | 295 const std::string& event_args, |
| 261 Profile* restrict_to_profile, | 296 Profile* restrict_to_profile, |
| 262 const GURL& event_url, | 297 const GURL& event_url, |
| 263 UserGestureState user_gesture) { | 298 UserGestureState user_gesture) { |
| 264 DCHECK(!extension_id.empty()); | 299 DCHECK(!extension_id.empty()); |
| 265 linked_ptr<ExtensionEvent> event( | 300 linked_ptr<ExtensionEvent> event( |
| 266 new ExtensionEvent(event_name, event_args, event_url, | 301 new ExtensionEvent(event_name, event_args, event_url, |
| 267 restrict_to_profile, "", user_gesture)); | 302 restrict_to_profile, "", user_gesture, |
| 303 EventFilteringInfo())); |
| 268 DispatchEventImpl(extension_id, event); | 304 DispatchEventImpl(extension_id, event); |
| 269 } | 305 } |
| 270 | 306 |
| 271 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( | 307 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( |
| 272 const std::string& event_name, | 308 const std::string& event_name, |
| 273 const std::string& event_args, | 309 const std::string& event_args, |
| 274 Profile* restrict_to_profile, | 310 Profile* restrict_to_profile, |
| 275 const std::string& cross_incognito_args, | 311 const std::string& cross_incognito_args, |
| 276 const GURL& event_url) { | 312 const GURL& event_url) { |
| 277 linked_ptr<ExtensionEvent> event( | 313 linked_ptr<ExtensionEvent> event( |
| 278 new ExtensionEvent(event_name, event_args, event_url, | 314 new ExtensionEvent(event_name, event_args, event_url, |
| 279 restrict_to_profile, cross_incognito_args, | 315 restrict_to_profile, cross_incognito_args, |
| 280 USER_GESTURE_UNKNOWN)); | 316 USER_GESTURE_UNKNOWN, EventFilteringInfo())); |
| 281 DispatchEventImpl("", event); | 317 DispatchEventImpl("", event); |
| 282 } | 318 } |
| 283 | 319 |
| 284 void ExtensionEventRouter::DispatchEventImpl( | 320 void ExtensionEventRouter::DispatchEventImpl( |
| 285 const std::string& extension_id, | 321 const std::string& restrict_to_extension_id, |
| 286 const linked_ptr<ExtensionEvent>& event) { | 322 const linked_ptr<ExtensionEvent>& event) { |
| 287 // We don't expect to get events from a completely different profile. | 323 // We don't expect to get events from a completely different profile. |
| 288 DCHECK(!event->restrict_to_profile || | 324 DCHECK(!event->restrict_to_profile || |
| 289 profile_->IsSameProfile(event->restrict_to_profile)); | 325 profile_->IsSameProfile(event->restrict_to_profile)); |
| 290 | 326 |
| 291 LoadLazyBackgroundPagesForEvent(extension_id, event); | 327 std::set<const EventListener*> listeners(listeners_.GetEventTargets(*event)); |
| 292 | 328 for (std::set<const EventListener*>::iterator it = listeners.begin(); |
| 293 ListenerMap::iterator it = listeners_.find(event->event_name); | 329 it != listeners.end(); it++) { |
| 294 if (it == listeners_.end()) | 330 const EventListener* listener = *it; |
| 295 return; | 331 if (listener->process) { |
| 296 | 332 if (restrict_to_extension_id.empty() || |
| 297 std::set<ListenerProcess>& listeners = it->second; | 333 restrict_to_extension_id == listener->extension_id) |
| 298 for (std::set<ListenerProcess>::iterator listener = listeners.begin(); | 334 DispatchEventToProcess(listener->extension_id, listener->process, |
| 299 listener != listeners.end(); ++listener) { | 335 event); |
| 300 if (!extension_id.empty() && extension_id != listener->extension_id) | 336 } else { |
| 301 continue; | 337 DispatchLazyEvent(listener->extension_id, event); |
| 302 | 338 } |
| 303 DispatchEventToListener(*listener, event); | |
| 304 } | 339 } |
| 305 } | 340 } |
| 306 | 341 |
| 307 void ExtensionEventRouter::DispatchEventToListener( | 342 void ExtensionEventRouter::DispatchLazyEvent( |
| 308 const ListenerProcess& listener, | 343 const std::string& extension_id, |
| 344 const linked_ptr<ExtensionEvent>& event) { |
| 345 ExtensionService* service = profile_->GetExtensionService(); |
| 346 // Check both the original and the incognito profile to see if we |
| 347 // should load a lazy bg page to handle the event. The latter case |
| 348 // occurs in the case of split-mode extensions. |
| 349 const Extension* extension = service->extensions()->GetByID(extension_id); |
| 350 if (extension) { |
| 351 MaybeLoadLazyBackgroundPage(profile_, extension, event, extension_id); |
| 352 if (profile_->HasOffTheRecordProfile() && |
| 353 extension->incognito_split_mode()) { |
| 354 MaybeLoadLazyBackgroundPage( |
| 355 profile_->GetOffTheRecordProfile(), extension, event, extension_id); |
| 356 } |
| 357 } |
| 358 } |
| 359 |
| 360 void ExtensionEventRouter::DispatchEventToProcess( |
| 361 const std::string& extension_id, |
| 362 content::RenderProcessHost* process, |
| 309 const linked_ptr<ExtensionEvent>& event) { | 363 const linked_ptr<ExtensionEvent>& event) { |
| 310 ExtensionService* service = profile_->GetExtensionService(); | 364 ExtensionService* service = profile_->GetExtensionService(); |
| 311 const Extension* extension = service->extensions()->GetByID( | 365 const Extension* extension = service->extensions()->GetByID( |
| 312 listener.extension_id); | 366 extension_id); |
| 313 | 367 |
| 314 // The extension could have been removed, but we do not unregister it until | 368 // The extension could have been removed, but we do not unregister it until |
| 315 // the extension process is unloaded. | 369 // the extension process is unloaded. |
| 316 if (!extension) | 370 if (!extension) |
| 317 return; | 371 return; |
| 318 | 372 |
| 319 Profile* listener_profile = Profile::FromBrowserContext( | 373 Profile* listener_profile = Profile::FromBrowserContext( |
| 320 listener.process->GetBrowserContext()); | 374 process->GetBrowserContext()); |
| 321 extensions::ProcessMap* process_map = | 375 extensions::ProcessMap* process_map = |
| 322 listener_profile->GetExtensionService()->process_map(); | 376 listener_profile->GetExtensionService()->process_map(); |
| 323 // If the event is privileged, only send to extension processes. Otherwise, | 377 // If the event is privileged, only send to extension processes. Otherwise, |
| 324 // it's OK to send to normal renderers (e.g., for content scripts). | 378 // it's OK to send to normal renderers (e.g., for content scripts). |
| 325 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | 379 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && |
| 326 !process_map->Contains(extension->id(), listener.process->GetID())) { | 380 !process_map->Contains(extension->id(), process->GetID())) { |
| 327 return; | 381 return; |
| 328 } | 382 } |
| 329 | 383 |
| 330 const std::string* event_args; | 384 const std::string* event_args; |
| 331 if (!CanDispatchEventToProfile(listener_profile, extension, | 385 if (!CanDispatchEventToProfile(listener_profile, extension, |
| 332 event, &event_args)) | 386 event, &event_args)) |
| 333 return; | 387 return; |
| 334 | 388 |
| 335 DispatchEvent(listener.process, listener.extension_id, | 389 DispatchEvent(process, extension_id, |
| 336 event->event_name, *event_args, | 390 event->event_name, *event_args, |
| 337 event->event_url, event->user_gesture); | 391 event->event_url, event->user_gesture, |
| 392 event->info); |
| 338 IncrementInFlightEvents(listener_profile, extension); | 393 IncrementInFlightEvents(listener_profile, extension); |
| 339 } | 394 } |
| 340 | 395 |
| 341 bool ExtensionEventRouter::CanDispatchEventToProfile( | 396 bool ExtensionEventRouter::CanDispatchEventToProfile( |
| 342 Profile* profile, | 397 Profile* profile, |
| 343 const Extension* extension, | 398 const Extension* extension, |
| 344 const linked_ptr<ExtensionEvent>& event, | 399 const linked_ptr<ExtensionEvent>& event, |
| 345 const std::string** event_args) { | 400 const std::string** event_args) { |
| 346 *event_args = &event->event_args; | 401 *event_args = &event->event_args; |
| 347 | 402 |
| 348 // Is this event from a different profile than the renderer (ie, an | 403 // Is this event from a different profile than the renderer (ie, an |
| 349 // incognito tab event sent to a normal process, or vice versa). | 404 // incognito tab event sent to a normal process, or vice versa). |
| 350 bool cross_incognito = event->restrict_to_profile && | 405 bool cross_incognito = event->restrict_to_profile && |
| 351 profile != event->restrict_to_profile; | 406 profile != event->restrict_to_profile; |
| 352 if (cross_incognito && | 407 if (cross_incognito && |
| 353 !profile->GetExtensionService()->CanCrossIncognito(extension)) { | 408 !profile->GetExtensionService()->CanCrossIncognito(extension)) { |
| 354 if (event->cross_incognito_args.empty()) | 409 if (event->cross_incognito_args.empty()) |
| 355 return false; | 410 return false; |
| 356 // Send the event with different arguments to extensions that can't | 411 // Send the event with different arguments to extensions that can't |
| 357 // cross incognito. | 412 // cross incognito. |
| 358 *event_args = &event->cross_incognito_args; | 413 *event_args = &event->cross_incognito_args; |
| 359 } | 414 } |
| 360 | 415 |
| 361 return true; | 416 return true; |
| 362 } | 417 } |
| 363 | 418 |
| 364 void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent( | |
| 365 const std::string& extension_id, | |
| 366 const linked_ptr<ExtensionEvent>& event) { | |
| 367 ExtensionService* service = profile_->GetExtensionService(); | |
| 368 | |
| 369 ListenerMap::iterator it = lazy_listeners_.find(event->event_name); | |
| 370 if (it == lazy_listeners_.end()) | |
| 371 return; | |
| 372 | |
| 373 std::set<ListenerProcess>& listeners = it->second; | |
| 374 for (std::set<ListenerProcess>::iterator listener = listeners.begin(); | |
| 375 listener != listeners.end(); ++listener) { | |
| 376 if (!extension_id.empty() && extension_id != listener->extension_id) | |
| 377 continue; | |
| 378 | |
| 379 // Check both the original and the incognito profile to see if we | |
| 380 // should load a lazy bg page to handle the event. The latter case | |
| 381 // occurs in the case of split-mode extensions. | |
| 382 const Extension* extension = service->extensions()->GetByID( | |
| 383 listener->extension_id); | |
| 384 if (extension) { | |
| 385 MaybeLoadLazyBackgroundPage(profile_, extension, event); | |
| 386 if (profile_->HasOffTheRecordProfile() && | |
| 387 extension->incognito_split_mode()) { | |
| 388 MaybeLoadLazyBackgroundPage( | |
| 389 profile_->GetOffTheRecordProfile(), extension, event); | |
| 390 } | |
| 391 } | |
| 392 } | |
| 393 } | |
| 394 | |
| 395 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage( | 419 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage( |
| 396 Profile* profile, | 420 Profile* profile, |
| 397 const Extension* extension, | 421 const Extension* extension, |
| 398 const linked_ptr<ExtensionEvent>& event) { | 422 const linked_ptr<ExtensionEvent>& event, |
| 423 const std::string& extension_id) { |
| 399 const std::string* event_args; | 424 const std::string* event_args; |
| 400 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) | 425 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) |
| 401 return; | 426 return; |
| 402 | 427 |
| 403 extensions::LazyBackgroundTaskQueue* queue = | 428 extensions::LazyBackgroundTaskQueue* queue = |
| 404 ExtensionSystem::Get(profile)->lazy_background_task_queue(); | 429 ExtensionSystem::Get(profile)->lazy_background_task_queue(); |
| 405 if (queue->ShouldEnqueueTask(profile, extension)) { | 430 if (queue->ShouldEnqueueTask(profile, extension)) { |
| 406 queue->AddPendingTask( | 431 queue->AddPendingTask( |
| 407 profile, extension->id(), | 432 profile, extension->id(), |
| 408 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, | 433 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 429 ExtensionSystem::Get(profile)->process_manager(); | 454 ExtensionSystem::Get(profile)->process_manager(); |
| 430 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); | 455 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); |
| 431 // The event ACK is routed to the background host, so this should never be | 456 // The event ACK is routed to the background host, so this should never be |
| 432 // NULL. | 457 // NULL. |
| 433 CHECK(host); | 458 CHECK(host); |
| 434 CHECK(host->extension()->has_lazy_background_page()); | 459 CHECK(host->extension()->has_lazy_background_page()); |
| 435 pm->DecrementLazyKeepaliveCount(host->extension()); | 460 pm->DecrementLazyKeepaliveCount(host->extension()); |
| 436 } | 461 } |
| 437 | 462 |
| 438 void ExtensionEventRouter::DispatchPendingEvent( | 463 void ExtensionEventRouter::DispatchPendingEvent( |
| 439 const linked_ptr<ExtensionEvent>& event, ExtensionHost* host) { | 464 const linked_ptr<ExtensionEvent>& event, |
| 465 ExtensionHost* host) { |
| 440 if (!host) | 466 if (!host) |
| 441 return; | 467 return; |
| 442 | 468 |
| 443 ListenerProcess listener(host->render_process_host(), | 469 if (listeners_.HasProcessListener(host->render_process_host(), |
| 444 host->extension()->id()); | 470 host->extension()->id())) |
| 445 if (listeners_[event->event_name].count(listener) > 0u) | 471 DispatchEventToProcess(host->extension()->id(), |
| 446 DispatchEventToListener(listener, event); | 472 host->render_process_host(), event); |
| 447 } | 473 } |
| 448 | 474 |
| 449 void ExtensionEventRouter::Observe( | 475 void ExtensionEventRouter::Observe( |
| 450 int type, | 476 int type, |
| 451 const content::NotificationSource& source, | 477 const content::NotificationSource& source, |
| 452 const content::NotificationDetails& details) { | 478 const content::NotificationDetails& details) { |
| 453 switch (type) { | 479 switch (type) { |
| 454 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 480 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
| 455 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 481 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
| 456 content::RenderProcessHost* renderer = | 482 content::RenderProcessHost* renderer = |
| 457 content::Source<content::RenderProcessHost>(source).ptr(); | 483 content::Source<content::RenderProcessHost>(source).ptr(); |
| 458 // Remove all event listeners associated with this renderer. | 484 // Remove all event listeners associated with this renderer. |
| 459 for (ListenerMap::iterator it = listeners_.begin(); | 485 listeners_.RemoveListenersForProcess(renderer); |
| 460 it != listeners_.end(); ) { | |
| 461 ListenerMap::iterator current_it = it++; | |
| 462 for (std::set<ListenerProcess>::iterator jt = | |
| 463 current_it->second.begin(); | |
| 464 jt != current_it->second.end(); ) { | |
| 465 std::set<ListenerProcess>::iterator current_jt = jt++; | |
| 466 if (current_jt->process == renderer) { | |
| 467 RemoveEventListener(current_it->first, | |
| 468 current_jt->process, | |
| 469 current_jt->extension_id); | |
| 470 } | |
| 471 } | |
| 472 } | |
| 473 break; | 486 break; |
| 474 } | 487 } |
| 475 case chrome::NOTIFICATION_EXTENSION_LOADED: { | 488 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 476 // Add all registered lazy listeners to our cache. | 489 // Add all registered lazy listeners to our cache. |
| 477 const Extension* extension = | 490 const Extension* extension = |
| 478 content::Details<const Extension>(details).ptr(); | 491 content::Details<const Extension>(details).ptr(); |
| 492 ExtensionPrefs* prefs = |
| 493 profile_->GetExtensionService()->extension_prefs(); |
| 479 std::set<std::string> registered_events = | 494 std::set<std::string> registered_events = |
| 480 profile_->GetExtensionService()->extension_prefs()-> | 495 prefs->GetRegisteredEvents(extension->id()); |
| 481 GetRegisteredEvents(extension->id()); | 496 const DictionaryValue* filtered_events = |
| 482 ListenerProcess lazy_listener(NULL, extension->id()); | 497 prefs->GetFilteredEvents(extension->id()); |
| 483 for (std::set<std::string>::iterator it = registered_events.begin(); | 498 if (filtered_events) |
| 484 it != registered_events.end(); ++it) { | 499 listeners_.AddLazyListenersFromPreferences(extension->id(), |
| 485 lazy_listeners_[*it].insert(lazy_listener); | 500 registered_events, |
| 486 } | 501 *filtered_events); |
| 487 break; | 502 break; |
| 488 } | 503 } |
| 489 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 504 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 490 // Remove all registered lazy listeners from our cache. | 505 // Remove all registered lazy listeners from our cache. |
| 491 extensions::UnloadedExtensionInfo* unloaded = | 506 extensions::UnloadedExtensionInfo* unloaded = |
| 492 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); | 507 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); |
| 493 ListenerProcess lazy_listener(NULL, unloaded->extension->id()); | 508 listeners_.RemoveLazyListenersFor(unloaded->extension->id()); |
| 494 for (ListenerMap::iterator it = lazy_listeners_.begin(); | |
| 495 it != lazy_listeners_.end(); ++it) { | |
| 496 it->second.erase(lazy_listener); | |
| 497 } | |
| 498 break; | 509 break; |
| 499 } | 510 } |
| 500 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | 511 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
| 501 // Dispatch the onInstalled event. | 512 // Dispatch the onInstalled event. |
| 502 const Extension* extension = | 513 const Extension* extension = |
| 503 content::Details<const Extension>(details).ptr(); | 514 content::Details<const Extension>(details).ptr(); |
| 504 MessageLoop::current()->PostTask(FROM_HERE, | 515 MessageLoop::current()->PostTask(FROM_HERE, |
| 505 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, | 516 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, |
| 506 profile_, extension->id())); | 517 profile_, extension->id())); |
| 507 break; | 518 break; |
| 508 } | 519 } |
| 509 default: | 520 default: |
| 510 NOTREACHED(); | 521 NOTREACHED(); |
| 511 return; | 522 return; |
| 512 } | 523 } |
| 513 } | 524 } |
| 525 |
| 526 ExtensionEvent::ExtensionEvent( |
| 527 const std::string& event_name, |
| 528 const std::string& event_args, |
| 529 const GURL& event_url, |
| 530 Profile* restrict_to_profile, |
| 531 const std::string& cross_incognito_args, |
| 532 ExtensionEventRouter::UserGestureState user_gesture, |
| 533 const extensions::EventFilteringInfo& info) |
| 534 : event_name(event_name), |
| 535 event_args(event_args), |
| 536 event_url(event_url), |
| 537 restrict_to_profile(restrict_to_profile), |
| 538 cross_incognito_args(cross_incognito_args), |
| 539 user_gesture(user_gesture), |
| 540 info(info) { |
| 541 } |
| 542 |
| 543 ExtensionEvent::~ExtensionEvent() { |
| 544 } |
| OLD | NEW |