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(IPC::Message::Sender* ipc_sender, |
92 const std::string& extension_id, | 70 const std::string& extension_id, |
93 const std::string& event_name, | 71 const std::string& event_name, |
94 const std::string& event_args, | 72 const std::string& event_args, |
95 const GURL& event_url, | 73 const GURL& event_url, |
96 UserGestureState user_gesture) { | 74 UserGestureState user_gesture, |
75 extensions::EventFilteringInfo info) { | |
97 ListValue args; | 76 ListValue args; |
98 args.Set(0, Value::CreateStringValue(event_name)); | 77 args.Set(0, Value::CreateStringValue(event_name)); |
99 args.Set(1, Value::CreateStringValue(event_args)); | 78 args.Set(1, Value::CreateStringValue(event_args)); |
79 args.Set(2, Value::CreateStringValue(info.AsJSONString())); | |
100 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | 80 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, |
101 extension_id, kDispatchEvent, args, event_url, | 81 extension_id, kDispatchEvent, args, event_url, |
102 user_gesture == USER_GESTURE_ENABLED)); | 82 user_gesture == USER_GESTURE_ENABLED)); |
103 } | 83 } |
104 | 84 |
105 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) | 85 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) |
106 : profile_(profile), | 86 : profile_(profile), |
107 extension_devtools_manager_( | 87 extension_devtools_manager_( |
108 ExtensionSystem::Get(profile)->devtools_manager()) { | 88 ExtensionSystem::Get(profile)->devtools_manager()) { |
109 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 89 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
110 content::NotificationService::AllSources()); | 90 content::NotificationService::AllSources()); |
111 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 91 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
112 content::NotificationService::AllSources()); | 92 content::NotificationService::AllSources()); |
113 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 93 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
114 content::Source<Profile>(profile_)); | 94 content::Source<Profile>(profile_)); |
115 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 95 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
116 content::Source<Profile>(profile_)); | 96 content::Source<Profile>(profile_)); |
117 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | 97 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
118 content::Source<Profile>(profile_)); | 98 content::Source<Profile>(profile_)); |
119 } | 99 } |
120 | 100 |
121 ExtensionEventRouter::~ExtensionEventRouter() {} | 101 ExtensionEventRouter::~ExtensionEventRouter() {} |
122 | 102 |
123 void ExtensionEventRouter::AddEventListener( | 103 void ExtensionEventRouter::AddEventListener( |
124 const std::string& event_name, | 104 const std::string& event_name, |
125 content::RenderProcessHost* process, | 105 content::RenderProcessHost* process, |
126 const std::string& extension_id) { | 106 const std::string& extension_id) { |
127 ListenerProcess listener(process, extension_id); | 107 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( |
128 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; | 108 event_name, extension_id, process, scoped_ptr<DictionaryValue>()))); |
129 listeners_[event_name].insert(listener); | |
130 | 109 |
131 if (extension_devtools_manager_.get()) | 110 if (extension_devtools_manager_.get()) |
132 extension_devtools_manager_->AddEventListener(event_name, | 111 extension_devtools_manager_->AddEventListener(event_name, |
133 process->GetID()); | 112 process->GetID()); |
134 | 113 |
135 // We lazily tell the TaskManager to start updating when listeners to the | 114 // We lazily tell the TaskManager to start updating when listeners to the |
136 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. | 115 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. |
137 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || | 116 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || |
138 event_name.compare( | 117 event_name.compare( |
139 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) | 118 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) |
140 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); | 119 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); |
141 } | 120 } |
142 | 121 |
143 void ExtensionEventRouter::RemoveEventListener( | 122 void ExtensionEventRouter::RemoveEventListener( |
144 const std::string& event_name, | 123 const std::string& event_name, |
145 content::RenderProcessHost* process, | 124 content::RenderProcessHost* process, |
146 const std::string& extension_id) { | 125 const std::string& extension_id) { |
147 ListenerProcess listener(process, extension_id); | 126 scoped_ptr<EventListener> listener(new EventListener( |
148 DCHECK_EQ(listeners_[event_name].count(listener), 1u) << | 127 event_name, extension_id, process, scoped_ptr<DictionaryValue>())); |
149 " PID=" << process->GetID() << " extension=" << extension_id << | 128 std::string id = extension_id; |
Matt Perry
2012/06/13 01:24:27
unused
koz (OOO until 15th September)
2012/06/14 02:15:55
Done.
| |
150 " event=" << event_name; | 129 OnListenerRemoved(listener.get()); |
151 listeners_[event_name].erase(listener); | 130 listeners_.RemoveListener(listener.Pass()); |
152 // Note: extension_id may point to data in the now-deleted listeners_ object. | 131 } |
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.Pass()); | |
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 lazy) { | |
196 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( | |
197 event_name, extension_id, process, | |
198 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | |
199 | |
200 if (lazy) { | |
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 lazy) { | |
219 listeners_.RemoveListener(scoped_ptr<EventListener>(new EventListener( | |
220 event_name, extension_id, process, | |
221 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | |
222 | |
223 if (lazy) { | |
224 bool removed = listeners_.RemoveListener(scoped_ptr<EventListener>( | |
225 new EventListener(event_name, extension_id, NULL, | |
226 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | |
227 | |
228 if (removed) { | |
229 ExtensionPrefs* prefs = | |
230 profile_->GetExtensionService()->extension_prefs(); | |
231 prefs->RemoveFilterFromEvent(event_name, extension_id, &filter); | |
232 } | |
233 } | |
234 } | |
235 | |
202 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { | 236 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { |
203 return (HasEventListenerImpl(listeners_, "", event_name) || | 237 return listeners_.AnyListenersForEvent(event_name); |
204 HasEventListenerImpl(lazy_listeners_, "", event_name)); | |
205 } | 238 } |
206 | 239 |
207 bool ExtensionEventRouter::ExtensionHasEventListener( | 240 bool ExtensionEventRouter::ExtensionHasEventListener( |
208 const std::string& extension_id, const std::string& event_name) { | 241 const std::string& extension_id, const std::string& event_name) { |
209 return (HasEventListenerImpl(listeners_, extension_id, event_name) || | 242 return listeners_.AnyListenersForExtension(extension_id, event_name); |
210 HasEventListenerImpl(lazy_listeners_, extension_id, event_name)); | |
211 } | 243 } |
212 | 244 |
213 bool ExtensionEventRouter::HasEventListenerImpl( | 245 bool ExtensionEventRouter::HasEventListenerImpl( |
214 const ListenerMap& listener_map, | 246 const ListenerMap& listener_map, |
215 const std::string& extension_id, | 247 const std::string& extension_id, |
216 const std::string& event_name) { | 248 const std::string& event_name) { |
217 ListenerMap::const_iterator it = listener_map.find(event_name); | 249 ListenerMap::const_iterator it = listener_map.find(event_name); |
218 if (it == listener_map.end()) | 250 if (it == listener_map.end()) |
219 return false; | 251 return false; |
220 | 252 |
221 const std::set<ListenerProcess>& listeners = it->second; | 253 const std::set<ListenerProcess>& listeners = it->second; |
222 if (extension_id.empty()) | 254 if (extension_id.empty()) |
223 return !listeners.empty(); | 255 return !listeners.empty(); |
224 | 256 |
225 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); | 257 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); |
226 listener != listeners.end(); ++listener) { | 258 listener != listeners.end(); ++listener) { |
227 if (listener->extension_id == extension_id) | 259 if (listener->extension_id == extension_id) |
228 return true; | 260 return true; |
229 } | 261 } |
230 return false; | 262 return false; |
231 } | 263 } |
232 | 264 |
233 void ExtensionEventRouter::DispatchEventToRenderers( | 265 void ExtensionEventRouter::DispatchEventToRenderers( |
234 const std::string& event_name, | 266 const std::string& event_name, |
235 const std::string& event_args, | 267 const std::string& event_args, |
236 Profile* restrict_to_profile, | 268 Profile* restrict_to_profile, |
237 const GURL& event_url) { | 269 const GURL& event_url, |
270 extensions::EventFilteringInfo info) { | |
238 linked_ptr<ExtensionEvent> event( | 271 linked_ptr<ExtensionEvent> event( |
239 new ExtensionEvent(event_name, event_args, event_url, | 272 new ExtensionEvent(event_name, event_args, event_url, |
240 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); | 273 restrict_to_profile, "", USER_GESTURE_UNKNOWN, info)); |
241 DispatchEventImpl("", event); | 274 DispatchEventImpl("", event); |
242 } | 275 } |
243 | 276 |
244 void ExtensionEventRouter::DispatchEventToExtension( | 277 void ExtensionEventRouter::DispatchEventToExtension( |
245 const std::string& extension_id, | 278 const std::string& extension_id, |
246 const std::string& event_name, | 279 const std::string& event_name, |
247 const std::string& event_args, | 280 const std::string& event_args, |
248 Profile* restrict_to_profile, | 281 Profile* restrict_to_profile, |
249 const GURL& event_url) { | 282 const GURL& event_url) { |
250 DCHECK(!extension_id.empty()); | 283 DCHECK(!extension_id.empty()); |
251 linked_ptr<ExtensionEvent> event( | 284 linked_ptr<ExtensionEvent> event( |
252 new ExtensionEvent(event_name, event_args, event_url, | 285 new ExtensionEvent(event_name, event_args, event_url, |
253 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); | 286 restrict_to_profile, "", USER_GESTURE_UNKNOWN, |
287 EventFilteringInfo())); | |
254 DispatchEventImpl(extension_id, event); | 288 DispatchEventImpl(extension_id, event); |
255 } | 289 } |
256 | 290 |
257 void ExtensionEventRouter::DispatchEventToExtension( | 291 void ExtensionEventRouter::DispatchEventToExtension( |
258 const std::string& extension_id, | 292 const std::string& extension_id, |
259 const std::string& event_name, | 293 const std::string& event_name, |
260 const std::string& event_args, | 294 const std::string& event_args, |
261 Profile* restrict_to_profile, | 295 Profile* restrict_to_profile, |
262 const GURL& event_url, | 296 const GURL& event_url, |
263 UserGestureState user_gesture) { | 297 UserGestureState user_gesture) { |
264 DCHECK(!extension_id.empty()); | 298 DCHECK(!extension_id.empty()); |
265 linked_ptr<ExtensionEvent> event( | 299 linked_ptr<ExtensionEvent> event( |
266 new ExtensionEvent(event_name, event_args, event_url, | 300 new ExtensionEvent(event_name, event_args, event_url, |
267 restrict_to_profile, "", user_gesture)); | 301 restrict_to_profile, "", user_gesture, |
302 EventFilteringInfo())); | |
268 DispatchEventImpl(extension_id, event); | 303 DispatchEventImpl(extension_id, event); |
269 } | 304 } |
270 | 305 |
271 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( | 306 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( |
272 const std::string& event_name, | 307 const std::string& event_name, |
273 const std::string& event_args, | 308 const std::string& event_args, |
274 Profile* restrict_to_profile, | 309 Profile* restrict_to_profile, |
275 const std::string& cross_incognito_args, | 310 const std::string& cross_incognito_args, |
276 const GURL& event_url) { | 311 const GURL& event_url) { |
277 linked_ptr<ExtensionEvent> event( | 312 linked_ptr<ExtensionEvent> event( |
278 new ExtensionEvent(event_name, event_args, event_url, | 313 new ExtensionEvent(event_name, event_args, event_url, |
279 restrict_to_profile, cross_incognito_args, | 314 restrict_to_profile, cross_incognito_args, |
280 USER_GESTURE_UNKNOWN)); | 315 USER_GESTURE_UNKNOWN, EventFilteringInfo())); |
281 DispatchEventImpl("", event); | 316 DispatchEventImpl("", event); |
282 } | 317 } |
283 | 318 |
284 void ExtensionEventRouter::DispatchEventImpl( | 319 void ExtensionEventRouter::DispatchEventImpl( |
285 const std::string& extension_id, | 320 const std::string& extension_id, |
286 const linked_ptr<ExtensionEvent>& event) { | 321 const linked_ptr<ExtensionEvent>& event) { |
287 // We don't expect to get events from a completely different profile. | 322 // We don't expect to get events from a completely different profile. |
288 DCHECK(!event->restrict_to_profile || | 323 DCHECK(!event->restrict_to_profile || |
289 profile_->IsSameProfile(event->restrict_to_profile)); | 324 profile_->IsSameProfile(event->restrict_to_profile)); |
290 | 325 |
291 LoadLazyBackgroundPagesForEvent(extension_id, event); | 326 scoped_ptr<std::set<const EventListener*> > listeners( |
292 | 327 listeners_.GetEventTargets(*event)); |
293 ListenerMap::iterator it = listeners_.find(event->event_name); | 328 for (std::set<const EventListener*>::iterator it = listeners->begin(); |
294 if (it == listeners_.end()) | 329 it != listeners->end(); it++) { |
295 return; | 330 const EventListener* listener = *it; |
296 | 331 if (listener->process) { |
297 std::set<ListenerProcess>& listeners = it->second; | 332 if (extension_id.empty() || extension_id == listener->extension_id) |
298 for (std::set<ListenerProcess>::iterator listener = listeners.begin(); | 333 DispatchEventToExtension(listener->extension_id, listener->process, |
299 listener != listeners.end(); ++listener) { | 334 event); |
300 if (!extension_id.empty() && extension_id != listener->extension_id) | 335 } else { |
301 continue; | 336 DispatchLazyEvent(linked_ptr<EventListener>(listener->Copy().release()), |
302 | 337 event); |
303 DispatchEventToListener(*listener, event); | 338 } |
304 } | 339 } |
305 } | 340 } |
306 | 341 |
307 void ExtensionEventRouter::DispatchEventToListener( | 342 void ExtensionEventRouter::DispatchLazyEvent( |
308 const ListenerProcess& listener, | 343 const linked_ptr<EventListener>& listener, |
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( | |
350 listener->extension_id); | |
351 if (extension) { | |
352 MaybeLoadLazyBackgroundPage(profile_, extension, event, listener); | |
353 if (profile_->HasOffTheRecordProfile() && | |
354 extension->incognito_split_mode()) { | |
355 MaybeLoadLazyBackgroundPage( | |
356 profile_->GetOffTheRecordProfile(), extension, event, listener); | |
357 } | |
358 } | |
359 } | |
360 | |
361 void ExtensionEventRouter::DispatchEventToExtension( | |
362 const std::string& extension_id, | |
363 content::RenderProcessHost* process, | |
309 const linked_ptr<ExtensionEvent>& event) { | 364 const linked_ptr<ExtensionEvent>& event) { |
310 ExtensionService* service = profile_->GetExtensionService(); | 365 ExtensionService* service = profile_->GetExtensionService(); |
311 const Extension* extension = service->extensions()->GetByID( | 366 const Extension* extension = service->extensions()->GetByID( |
312 listener.extension_id); | 367 extension_id); |
313 | 368 |
314 // The extension could have been removed, but we do not unregister it until | 369 // The extension could have been removed, but we do not unregister it until |
315 // the extension process is unloaded. | 370 // the extension process is unloaded. |
316 if (!extension) | 371 if (!extension) |
317 return; | 372 return; |
318 | 373 |
319 Profile* listener_profile = Profile::FromBrowserContext( | 374 Profile* listener_profile = Profile::FromBrowserContext( |
320 listener.process->GetBrowserContext()); | 375 process->GetBrowserContext()); |
321 extensions::ProcessMap* process_map = | 376 extensions::ProcessMap* process_map = |
322 listener_profile->GetExtensionService()->process_map(); | 377 listener_profile->GetExtensionService()->process_map(); |
323 // If the event is privileged, only send to extension processes. Otherwise, | 378 // 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). | 379 // it's OK to send to normal renderers (e.g., for content scripts). |
325 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | 380 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && |
326 !process_map->Contains(extension->id(), listener.process->GetID())) { | 381 !process_map->Contains(extension->id(), process->GetID())) { |
327 return; | 382 return; |
328 } | 383 } |
329 | 384 |
330 const std::string* event_args; | 385 const std::string* event_args; |
331 if (!CanDispatchEventToProfile(listener_profile, extension, | 386 if (!CanDispatchEventToProfile(listener_profile, extension, |
332 event, &event_args)) | 387 event, &event_args)) |
333 return; | 388 return; |
334 | 389 |
335 DispatchEvent(listener.process, listener.extension_id, | 390 DispatchEvent(process, extension_id, |
336 event->event_name, *event_args, | 391 event->event_name, *event_args, |
337 event->event_url, event->user_gesture); | 392 event->event_url, event->user_gesture, |
393 event->info); | |
338 IncrementInFlightEvents(listener_profile, extension); | 394 IncrementInFlightEvents(listener_profile, extension); |
339 } | 395 } |
340 | 396 |
341 bool ExtensionEventRouter::CanDispatchEventToProfile( | 397 bool ExtensionEventRouter::CanDispatchEventToProfile( |
342 Profile* profile, | 398 Profile* profile, |
343 const Extension* extension, | 399 const Extension* extension, |
344 const linked_ptr<ExtensionEvent>& event, | 400 const linked_ptr<ExtensionEvent>& event, |
345 const std::string** event_args) { | 401 const std::string** event_args) { |
346 *event_args = &event->event_args; | 402 *event_args = &event->event_args; |
347 | 403 |
348 // Is this event from a different profile than the renderer (ie, an | 404 // Is this event from a different profile than the renderer (ie, an |
349 // incognito tab event sent to a normal process, or vice versa). | 405 // incognito tab event sent to a normal process, or vice versa). |
350 bool cross_incognito = event->restrict_to_profile && | 406 bool cross_incognito = event->restrict_to_profile && |
351 profile != event->restrict_to_profile; | 407 profile != event->restrict_to_profile; |
352 if (cross_incognito && | 408 if (cross_incognito && |
353 !profile->GetExtensionService()->CanCrossIncognito(extension)) { | 409 !profile->GetExtensionService()->CanCrossIncognito(extension)) { |
354 if (event->cross_incognito_args.empty()) | 410 if (event->cross_incognito_args.empty()) |
355 return false; | 411 return false; |
356 // Send the event with different arguments to extensions that can't | 412 // Send the event with different arguments to extensions that can't |
357 // cross incognito. | 413 // cross incognito. |
358 *event_args = &event->cross_incognito_args; | 414 *event_args = &event->cross_incognito_args; |
359 } | 415 } |
360 | 416 |
361 return true; | 417 return true; |
362 } | 418 } |
363 | 419 |
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( | 420 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage( |
396 Profile* profile, | 421 Profile* profile, |
397 const Extension* extension, | 422 const Extension* extension, |
398 const linked_ptr<ExtensionEvent>& event) { | 423 const linked_ptr<ExtensionEvent>& event, |
424 const linked_ptr<EventListener>& listener) { | |
399 const std::string* event_args; | 425 const std::string* event_args; |
400 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) | 426 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) |
401 return; | 427 return; |
402 | 428 |
403 extensions::LazyBackgroundTaskQueue* queue = | 429 extensions::LazyBackgroundTaskQueue* queue = |
404 ExtensionSystem::Get(profile)->lazy_background_task_queue(); | 430 ExtensionSystem::Get(profile)->lazy_background_task_queue(); |
405 if (queue->ShouldEnqueueTask(profile, extension)) { | 431 if (queue->ShouldEnqueueTask(profile, extension)) { |
406 queue->AddPendingTask( | 432 queue->AddPendingTask( |
407 profile, extension->id(), | 433 profile, extension->id(), |
408 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, | 434 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, |
409 base::Unretained(this), event)); | 435 base::Unretained(this), event, listener)); |
410 } | 436 } |
411 } | 437 } |
412 | 438 |
413 void ExtensionEventRouter::IncrementInFlightEvents( | 439 void ExtensionEventRouter::IncrementInFlightEvents( |
414 Profile* profile, const Extension* extension) { | 440 Profile* profile, const Extension* extension) { |
415 // Only increment in-flight events if the lazy background page is active, | 441 // Only increment in-flight events if the lazy background page is active, |
416 // because that's the only time we'll get an ACK. | 442 // because that's the only time we'll get an ACK. |
417 if (extension->has_lazy_background_page()) { | 443 if (extension->has_lazy_background_page()) { |
418 ExtensionProcessManager* pm = | 444 ExtensionProcessManager* pm = |
419 ExtensionSystem::Get(profile)->process_manager(); | 445 ExtensionSystem::Get(profile)->process_manager(); |
420 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id()); | 446 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id()); |
421 if (host) | 447 if (host) |
422 pm->IncrementLazyKeepaliveCount(extension); | 448 pm->IncrementLazyKeepaliveCount(extension); |
423 } | 449 } |
424 } | 450 } |
425 | 451 |
426 void ExtensionEventRouter::OnEventAck( | 452 void ExtensionEventRouter::OnEventAck( |
427 Profile* profile, const std::string& extension_id) { | 453 Profile* profile, const std::string& extension_id) { |
428 ExtensionProcessManager* pm = | 454 ExtensionProcessManager* pm = |
429 ExtensionSystem::Get(profile)->process_manager(); | 455 ExtensionSystem::Get(profile)->process_manager(); |
430 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); | 456 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); |
431 // The event ACK is routed to the background host, so this should never be | 457 // The event ACK is routed to the background host, so this should never be |
432 // NULL. | 458 // NULL. |
433 CHECK(host); | 459 CHECK(host); |
434 CHECK(host->extension()->has_lazy_background_page()); | 460 CHECK(host->extension()->has_lazy_background_page()); |
435 pm->DecrementLazyKeepaliveCount(host->extension()); | 461 pm->DecrementLazyKeepaliveCount(host->extension()); |
436 } | 462 } |
437 | 463 |
438 void ExtensionEventRouter::DispatchPendingEvent( | 464 void ExtensionEventRouter::DispatchPendingEvent( |
439 const linked_ptr<ExtensionEvent>& event, ExtensionHost* host) { | 465 const linked_ptr<ExtensionEvent>& event, |
466 const linked_ptr<EventListener>& listener, | |
467 ExtensionHost* host) { | |
440 if (!host) | 468 if (!host) |
441 return; | 469 return; |
442 | 470 |
443 ListenerProcess listener(host->render_process_host(), | 471 if (listeners_.HasListener(listener.get())) |
Matt Perry
2012/06/13 01:24:27
This is not quite right. IIUC, here |listener| is
koz (OOO until 15th September)
2012/06/14 02:15:55
Done.
| |
444 host->extension()->id()); | 472 DispatchEventToExtension(host->extension()->id(), |
445 if (listeners_[event->event_name].count(listener) > 0u) | 473 host->render_process_host(), event); |
446 DispatchEventToListener(listener, event); | |
447 } | 474 } |
448 | 475 |
449 void ExtensionEventRouter::Observe( | 476 void ExtensionEventRouter::Observe( |
450 int type, | 477 int type, |
451 const content::NotificationSource& source, | 478 const content::NotificationSource& source, |
452 const content::NotificationDetails& details) { | 479 const content::NotificationDetails& details) { |
453 switch (type) { | 480 switch (type) { |
454 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 481 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
455 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 482 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
456 content::RenderProcessHost* renderer = | 483 content::RenderProcessHost* renderer = |
457 content::Source<content::RenderProcessHost>(source).ptr(); | 484 content::Source<content::RenderProcessHost>(source).ptr(); |
458 // Remove all event listeners associated with this renderer. | 485 // Remove all event listeners associated with this renderer. |
459 for (ListenerMap::iterator it = listeners_.begin(); | 486 EventListenerMap::ListenerList removed = |
460 it != listeners_.end(); ) { | 487 listeners_.RemoveListenersForProcess(renderer); |
461 ListenerMap::iterator current_it = it++; | 488 for (EventListenerMap::ListenerList::iterator it = removed.begin(); |
462 for (std::set<ListenerProcess>::iterator jt = | 489 it != removed.end(); it++) { |
463 current_it->second.begin(); | 490 OnListenerRemoved(it->get()); |
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 } | 491 } |
473 break; | 492 break; |
474 } | 493 } |
475 case chrome::NOTIFICATION_EXTENSION_LOADED: { | 494 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
476 // Add all registered lazy listeners to our cache. | 495 // Add all registered lazy listeners to our cache. |
477 const Extension* extension = | 496 const Extension* extension = |
478 content::Details<const Extension>(details).ptr(); | 497 content::Details<const Extension>(details).ptr(); |
498 ExtensionPrefs* prefs = | |
499 profile_->GetExtensionService()->extension_prefs(); | |
479 std::set<std::string> registered_events = | 500 std::set<std::string> registered_events = |
480 profile_->GetExtensionService()->extension_prefs()-> | 501 prefs->GetRegisteredEvents(extension->id()); |
481 GetRegisteredEvents(extension->id()); | 502 const DictionaryValue* filtered_events = |
482 ListenerProcess lazy_listener(NULL, extension->id()); | 503 prefs->GetFilteredEvents(extension->id()); |
483 for (std::set<std::string>::iterator it = registered_events.begin(); | 504 if (filtered_events) |
484 it != registered_events.end(); ++it) { | 505 listeners_.AddLazyListenersFromPreferences(extension->id(), |
485 lazy_listeners_[*it].insert(lazy_listener); | 506 registered_events, |
Matt Perry
2012/06/13 01:24:27
indent
koz (OOO until 15th September)
2012/06/14 02:15:55
Done.
| |
486 } | 507 *filtered_events); |
487 break; | 508 break; |
488 } | 509 } |
489 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 510 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
Matt Perry
2012/06/13 01:24:27
These top 4 notifications should be handled direct
koz (OOO until 15th September)
2012/06/14 02:15:55
I've added the callback for OnListenerRemoved(), b
| |
490 // Remove all registered lazy listeners from our cache. | 511 // Remove all registered lazy listeners from our cache. |
491 extensions::UnloadedExtensionInfo* unloaded = | 512 extensions::UnloadedExtensionInfo* unloaded = |
492 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); | 513 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); |
493 ListenerProcess lazy_listener(NULL, unloaded->extension->id()); | 514 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; | 515 break; |
499 } | 516 } |
500 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | 517 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
501 // Dispatch the onInstalled event. | 518 // Dispatch the onInstalled event. |
502 const Extension* extension = | 519 const Extension* extension = |
503 content::Details<const Extension>(details).ptr(); | 520 content::Details<const Extension>(details).ptr(); |
504 MessageLoop::current()->PostTask(FROM_HERE, | 521 MessageLoop::current()->PostTask(FROM_HERE, |
505 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, | 522 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, |
506 profile_, extension->id())); | 523 profile_, extension->id())); |
507 break; | 524 break; |
508 } | 525 } |
509 default: | 526 default: |
510 NOTREACHED(); | 527 NOTREACHED(); |
511 return; | 528 return; |
512 } | 529 } |
513 } | 530 } |
531 | |
532 ExtensionEvent::ExtensionEvent( | |
533 const std::string& event_name, | |
534 const std::string& event_args, | |
535 const GURL& event_url, | |
536 Profile* restrict_to_profile, | |
537 const std::string& cross_incognito_args, | |
538 ExtensionEventRouter::UserGestureState user_gesture, | |
539 const extensions::EventFilteringInfo& info) | |
540 : event_name(event_name), | |
541 event_args(event_args), | |
542 event_url(event_url), | |
543 restrict_to_profile(restrict_to_profile), | |
544 cross_incognito_args(cross_incognito_args), | |
545 user_gesture(user_gesture), | |
546 info(info) { | |
547 } | |
548 | |
549 ExtensionEvent::~ExtensionEvent() { | |
550 } | |
OLD | NEW |