OLD | NEW |
| (Empty) |
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 #include "chrome/browser/extensions/extension_event_router.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/command_line.h" | |
9 #include "base/message_loop.h" | |
10 #include "base/values.h" | |
11 #include "chrome/browser/extensions/api/runtime/runtime_api.h" | |
12 #include "chrome/browser/extensions/api/web_request/web_request_api.h" | |
13 #include "chrome/browser/extensions/extension_devtools_manager.h" | |
14 #include "chrome/browser/extensions/extension_host.h" | |
15 #include "chrome/browser/extensions/extension_process_manager.h" | |
16 #include "chrome/browser/extensions/extension_processes_api.h" | |
17 #include "chrome/browser/extensions/extension_processes_api_constants.h" | |
18 #include "chrome/browser/extensions/extension_service.h" | |
19 #include "chrome/browser/extensions/extension_system.h" | |
20 #include "chrome/browser/extensions/lazy_background_task_queue.h" | |
21 #include "chrome/browser/extensions/process_map.h" | |
22 #include "chrome/browser/profiles/profile.h" | |
23 #include "chrome/common/chrome_notification_types.h" | |
24 #include "chrome/common/chrome_switches.h" | |
25 #include "chrome/common/extensions/extension.h" | |
26 #include "chrome/common/extensions/extension_messages.h" | |
27 #include "chrome/common/extensions/api/extension_api.h" | |
28 #include "chrome/common/view_type.h" | |
29 #include "content/public/browser/notification_service.h" | |
30 #include "content/public/browser/render_process_host.h" | |
31 | |
32 using base::Value; | |
33 using content::BrowserThread; | |
34 using extensions::Extension; | |
35 using extensions::ExtensionAPI; | |
36 | |
37 namespace { | |
38 | |
39 const char kDispatchEvent[] = "Event.dispatchJSON"; | |
40 | |
41 void NotifyEventListenerRemovedOnIOThread( | |
42 void* profile, | |
43 const std::string& extension_id, | |
44 const std::string& sub_event_name) { | |
45 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | |
46 profile, extension_id, sub_event_name); | |
47 } | |
48 | |
49 } // namespace | |
50 | |
51 struct ExtensionEventRouter::ListenerProcess { | |
52 content::RenderProcessHost* process; | |
53 std::string extension_id; | |
54 | |
55 ListenerProcess(content::RenderProcessHost* process, | |
56 const std::string& extension_id) | |
57 : process(process), extension_id(extension_id) {} | |
58 | |
59 bool operator<(const ListenerProcess& that) const { | |
60 if (process < that.process) | |
61 return true; | |
62 if (process == that.process && extension_id < that.extension_id) | |
63 return true; | |
64 return false; | |
65 } | |
66 }; | |
67 | |
68 // static | |
69 void ExtensionEventRouter::DispatchEvent( | |
70 IPC::Sender* ipc_sender, | |
71 const std::string& extension_id, | |
72 const std::string& event_name, | |
73 const Value& event_args, | |
74 const GURL& event_url, | |
75 UserGestureState user_gesture, | |
76 const extensions::EventFilteringInfo& info) { | |
77 // TODO(gdk): Reduce number of DeepCopy() calls throughout the event dispatch | |
78 // chain, starting by replacing the event_args with a Value*. | |
79 ListValue args; | |
80 args.Set(0, Value::CreateStringValue(event_name)); | |
81 args.Set(1, event_args.DeepCopy()); | |
82 args.Set(2, info.AsValue().release()); | |
83 | |
84 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | |
85 extension_id, kDispatchEvent, args, event_url, | |
86 user_gesture == USER_GESTURE_ENABLED)); | |
87 } | |
88 | |
89 // static | |
90 void ExtensionEventRouter::DispatchEvent( | |
91 IPC::Sender* ipc_sender, | |
92 const std::string& extension_id, | |
93 const std::string& event_name, | |
94 const std::string& event_args, | |
95 const GURL& event_url, | |
96 UserGestureState user_gesture, | |
97 const extensions::EventFilteringInfo& info) { | |
98 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); | |
99 DispatchEvent(ipc_sender, extension_id, event_name, *event_args_value.get(), | |
100 event_url, user_gesture, info); | |
101 } | |
102 | |
103 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) | |
104 : profile_(profile), | |
105 extension_devtools_manager_( | |
106 extensions::ExtensionSystem::Get(profile)->devtools_manager()), | |
107 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
109 content::NotificationService::AllSources()); | |
110 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
111 content::NotificationService::AllSources()); | |
112 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | |
113 content::Source<Profile>(profile_)); | |
114 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | |
115 content::Source<Profile>(profile_)); | |
116 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
117 content::Source<Profile>(profile_)); | |
118 } | |
119 | |
120 ExtensionEventRouter::~ExtensionEventRouter() {} | |
121 | |
122 void ExtensionEventRouter::AddEventListener( | |
123 const std::string& event_name, | |
124 content::RenderProcessHost* process, | |
125 const std::string& extension_id) { | |
126 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( | |
127 event_name, extension_id, process, scoped_ptr<DictionaryValue>()))); | |
128 } | |
129 | |
130 void ExtensionEventRouter::RemoveEventListener( | |
131 const std::string& event_name, | |
132 content::RenderProcessHost* process, | |
133 const std::string& extension_id) { | |
134 EventListener listener(event_name, extension_id, process, | |
135 scoped_ptr<DictionaryValue>()); | |
136 listeners_.RemoveListener(&listener); | |
137 } | |
138 | |
139 void ExtensionEventRouter::OnListenerAdded(const EventListener* listener) { | |
140 // We don't care about lazy events being added. | |
141 if (!listener->process) | |
142 return; | |
143 | |
144 if (extension_devtools_manager_.get()) | |
145 extension_devtools_manager_->AddEventListener(listener->event_name, | |
146 listener->process->GetID()); | |
147 | |
148 // We lazily tell the TaskManager to start updating when listeners to the | |
149 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. | |
150 const std::string& event_name = listener->event_name; | |
151 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || | |
152 event_name.compare( | |
153 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) | |
154 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); | |
155 } | |
156 | |
157 void ExtensionEventRouter::OnListenerRemoved(const EventListener* listener) { | |
158 // We don't care about lazy events being removed. | |
159 if (!listener->process) | |
160 return; | |
161 | |
162 const std::string& event_name = listener->event_name; | |
163 if (extension_devtools_manager_.get()) | |
164 extension_devtools_manager_->RemoveEventListener( | |
165 event_name, listener->process->GetID()); | |
166 | |
167 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener | |
168 // is removed (or a process with one exits), then we let the extension API | |
169 // know that it has one fewer listener. | |
170 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || | |
171 event_name.compare( | |
172 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) | |
173 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); | |
174 | |
175 BrowserThread::PostTask( | |
176 BrowserThread::IO, FROM_HERE, | |
177 base::Bind( | |
178 &NotifyEventListenerRemovedOnIOThread, | |
179 profile_, listener->extension_id, listener->event_name)); | |
180 } | |
181 | |
182 void ExtensionEventRouter::AddLazyEventListener( | |
183 const std::string& event_name, | |
184 const std::string& extension_id) { | |
185 scoped_ptr<EventListener> listener(new EventListener( | |
186 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>())); | |
187 bool is_new = listeners_.AddListener(listener.Pass()); | |
188 | |
189 if (is_new) { | |
190 extensions::ExtensionPrefs* prefs = | |
191 profile_->GetExtensionService()->extension_prefs(); | |
192 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); | |
193 bool prefs_is_new = events.insert(event_name).second; | |
194 if (prefs_is_new) | |
195 prefs->SetRegisteredEvents(extension_id, events); | |
196 } | |
197 } | |
198 | |
199 void ExtensionEventRouter::RemoveLazyEventListener( | |
200 const std::string& event_name, | |
201 const std::string& extension_id) { | |
202 EventListener listener(event_name, extension_id, NULL, | |
203 scoped_ptr<DictionaryValue>()); | |
204 bool did_exist = listeners_.RemoveListener(&listener); | |
205 | |
206 if (did_exist) { | |
207 extensions::ExtensionPrefs* prefs = | |
208 profile_->GetExtensionService()->extension_prefs(); | |
209 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); | |
210 bool prefs_did_exist = events.erase(event_name) > 0; | |
211 DCHECK(prefs_did_exist); | |
212 prefs->SetRegisteredEvents(extension_id, events); | |
213 } | |
214 } | |
215 | |
216 void ExtensionEventRouter::AddFilteredEventListener( | |
217 const std::string& event_name, | |
218 content::RenderProcessHost* process, | |
219 const std::string& extension_id, | |
220 const base::DictionaryValue& filter, | |
221 bool add_lazy_listener) { | |
222 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( | |
223 event_name, extension_id, process, | |
224 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | |
225 | |
226 if (add_lazy_listener) { | |
227 bool added = listeners_.AddListener(scoped_ptr<EventListener>( | |
228 new EventListener(event_name, extension_id, NULL, | |
229 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | |
230 | |
231 if (added) { | |
232 extensions::ExtensionPrefs* prefs = | |
233 profile_->GetExtensionService()->extension_prefs(); | |
234 prefs->AddFilterToEvent(event_name, extension_id, &filter); | |
235 } | |
236 } | |
237 } | |
238 | |
239 void ExtensionEventRouter::RemoveFilteredEventListener( | |
240 const std::string& event_name, | |
241 content::RenderProcessHost* process, | |
242 const std::string& extension_id, | |
243 const base::DictionaryValue& filter, | |
244 bool remove_lazy_listener) { | |
245 EventListener listener(event_name, extension_id, process, | |
246 scoped_ptr<DictionaryValue>(filter.DeepCopy())); | |
247 | |
248 listeners_.RemoveListener(&listener); | |
249 | |
250 if (remove_lazy_listener) { | |
251 listener.process = NULL; | |
252 bool removed = listeners_.RemoveListener(&listener); | |
253 | |
254 if (removed) { | |
255 extensions::ExtensionPrefs* prefs = | |
256 profile_->GetExtensionService()->extension_prefs(); | |
257 prefs->RemoveFilterFromEvent(event_name, extension_id, &filter); | |
258 } | |
259 } | |
260 } | |
261 | |
262 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { | |
263 return listeners_.HasListenerForEvent(event_name); | |
264 } | |
265 | |
266 bool ExtensionEventRouter::ExtensionHasEventListener( | |
267 const std::string& extension_id, const std::string& event_name) { | |
268 return listeners_.HasListenerForExtension(extension_id, event_name); | |
269 } | |
270 | |
271 bool ExtensionEventRouter::HasEventListenerImpl( | |
272 const ListenerMap& listener_map, | |
273 const std::string& extension_id, | |
274 const std::string& event_name) { | |
275 ListenerMap::const_iterator it = listener_map.find(event_name); | |
276 if (it == listener_map.end()) | |
277 return false; | |
278 | |
279 const std::set<ListenerProcess>& listeners = it->second; | |
280 if (extension_id.empty()) | |
281 return !listeners.empty(); | |
282 | |
283 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); | |
284 listener != listeners.end(); ++listener) { | |
285 if (listener->extension_id == extension_id) | |
286 return true; | |
287 } | |
288 return false; | |
289 } | |
290 | |
291 void ExtensionEventRouter::DispatchEventToRenderers( | |
292 const std::string& event_name, | |
293 const std::string& event_args, | |
294 Profile* restrict_to_profile, | |
295 const GURL& event_url, | |
296 extensions::EventFilteringInfo info) { | |
297 DCHECK(!event_args.empty()); | |
298 StringValue event_args_value(event_args); | |
299 linked_ptr<ExtensionEvent> event( | |
300 new ExtensionEvent(event_name, event_args_value, event_url, | |
301 restrict_to_profile, USER_GESTURE_UNKNOWN, info)); | |
302 DispatchEventImpl("", event); | |
303 } | |
304 | |
305 void ExtensionEventRouter::DispatchEventToRenderers( | |
306 const std::string& event_name, | |
307 const std::string& event_args, | |
308 Profile* restrict_to_profile, | |
309 const GURL& event_url) { | |
310 DispatchEventToRenderers(event_name, event_args, restrict_to_profile, | |
311 event_url, extensions::EventFilteringInfo()); | |
312 } | |
313 | |
314 void ExtensionEventRouter::DispatchEventToExtension( | |
315 const std::string& extension_id, | |
316 const std::string& event_name, | |
317 const Value& event_args, | |
318 Profile* restrict_to_profile, | |
319 const GURL& event_url) { | |
320 DCHECK(!extension_id.empty()); | |
321 linked_ptr<ExtensionEvent> event( | |
322 new ExtensionEvent(event_name, event_args, event_url, | |
323 restrict_to_profile, USER_GESTURE_UNKNOWN, | |
324 EventFilteringInfo())); | |
325 DispatchEventImpl(extension_id, event); | |
326 } | |
327 | |
328 void ExtensionEventRouter::DispatchEventToExtension( | |
329 const std::string& extension_id, | |
330 const std::string& event_name, | |
331 const std::string& event_args, | |
332 Profile* restrict_to_profile, | |
333 const GURL& event_url) { | |
334 StringValue event_args_value(event_args); | |
335 DispatchEventToExtension(extension_id, event_name, event_args_value, | |
336 restrict_to_profile, event_url); | |
337 } | |
338 | |
339 void ExtensionEventRouter::DispatchEventToExtension( | |
340 const std::string& extension_id, | |
341 const std::string& event_name, | |
342 const std::string& event_args, | |
343 Profile* restrict_to_profile, | |
344 const GURL& event_url, | |
345 UserGestureState user_gesture) { | |
346 DCHECK(!extension_id.empty()); | |
347 StringValue event_args_value(event_args); | |
348 linked_ptr<ExtensionEvent> event( | |
349 new ExtensionEvent(event_name, event_args_value, event_url, | |
350 restrict_to_profile, user_gesture, | |
351 EventFilteringInfo())); | |
352 DispatchEventImpl(extension_id, event); | |
353 } | |
354 | |
355 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( | |
356 const std::string& event_name, | |
357 const std::string& event_args, | |
358 Profile* restrict_to_profile, | |
359 const std::string& cross_incognito_args, | |
360 const GURL& event_url) { | |
361 linked_ptr<ExtensionEvent> event( | |
362 new ExtensionEvent(event_name, event_args, event_url, | |
363 restrict_to_profile, cross_incognito_args, | |
364 USER_GESTURE_UNKNOWN, EventFilteringInfo())); | |
365 DispatchEventImpl("", event); | |
366 } | |
367 | |
368 void ExtensionEventRouter::DispatchEventImpl( | |
369 const std::string& restrict_to_extension_id, | |
370 const linked_ptr<ExtensionEvent>& event) { | |
371 // We don't expect to get events from a completely different profile. | |
372 DCHECK(!event->restrict_to_profile || | |
373 profile_->IsSameProfile(event->restrict_to_profile)); | |
374 | |
375 std::set<const EventListener*> listeners( | |
376 listeners_.GetEventListeners(*event)); | |
377 for (std::set<const EventListener*>::iterator it = listeners.begin(); | |
378 it != listeners.end(); it++) { | |
379 const EventListener* listener = *it; | |
380 if (restrict_to_extension_id.empty() || | |
381 restrict_to_extension_id == listener->extension_id) { | |
382 if (listener->process) { | |
383 DispatchEventToProcess(listener->extension_id, listener->process, | |
384 event); | |
385 } else { | |
386 DispatchLazyEvent(listener->extension_id, event); | |
387 } | |
388 } | |
389 } | |
390 } | |
391 | |
392 void ExtensionEventRouter::DispatchLazyEvent( | |
393 const std::string& extension_id, | |
394 const linked_ptr<ExtensionEvent>& event) { | |
395 ExtensionService* service = profile_->GetExtensionService(); | |
396 // Check both the original and the incognito profile to see if we | |
397 // should load a lazy bg page to handle the event. The latter case | |
398 // occurs in the case of split-mode extensions. | |
399 const Extension* extension = service->extensions()->GetByID(extension_id); | |
400 if (extension) { | |
401 MaybeLoadLazyBackgroundPageToDispatchEvent(profile_, extension, event); | |
402 if (profile_->HasOffTheRecordProfile() && | |
403 extension->incognito_split_mode()) { | |
404 MaybeLoadLazyBackgroundPageToDispatchEvent( | |
405 profile_->GetOffTheRecordProfile(), extension, event); | |
406 } | |
407 } | |
408 } | |
409 | |
410 void ExtensionEventRouter::DispatchEventToProcess( | |
411 const std::string& extension_id, | |
412 content::RenderProcessHost* process, | |
413 const linked_ptr<ExtensionEvent>& event) { | |
414 ExtensionService* service = profile_->GetExtensionService(); | |
415 const Extension* extension = service->extensions()->GetByID(extension_id); | |
416 | |
417 // The extension could have been removed, but we do not unregister it until | |
418 // the extension process is unloaded. | |
419 if (!extension) | |
420 return; | |
421 | |
422 Profile* listener_profile = Profile::FromBrowserContext( | |
423 process->GetBrowserContext()); | |
424 extensions::ProcessMap* process_map = | |
425 listener_profile->GetExtensionService()->process_map(); | |
426 // If the event is privileged, only send to extension processes. Otherwise, | |
427 // it's OK to send to normal renderers (e.g., for content scripts). | |
428 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | |
429 !process_map->Contains(extension->id(), process->GetID())) { | |
430 return; | |
431 } | |
432 | |
433 const Value* event_args = NULL; | |
434 if (!CanDispatchEventToProfile(listener_profile, extension, | |
435 event, &event_args)) { | |
436 return; | |
437 } | |
438 | |
439 DispatchEvent(process, extension_id, | |
440 event->event_name, *event_args, | |
441 event->event_url, event->user_gesture, | |
442 event->info); | |
443 IncrementInFlightEvents(listener_profile, extension); | |
444 } | |
445 | |
446 bool ExtensionEventRouter::CanDispatchEventToProfile( | |
447 Profile* profile, | |
448 const Extension* extension, | |
449 const linked_ptr<ExtensionEvent>& event, | |
450 const Value** event_args) { | |
451 *event_args = event->event_args.get(); | |
452 | |
453 // Is this event from a different profile than the renderer (ie, an | |
454 // incognito tab event sent to a normal process, or vice versa). | |
455 bool cross_incognito = event->restrict_to_profile && | |
456 profile != event->restrict_to_profile; | |
457 if (cross_incognito && | |
458 !profile->GetExtensionService()->CanCrossIncognito(extension)) { | |
459 if (!event->cross_incognito_args.get()) | |
460 return false; | |
461 // Send the event with different arguments to extensions that can't | |
462 // cross incognito. | |
463 *event_args = event->cross_incognito_args.get(); | |
464 } | |
465 | |
466 return true; | |
467 } | |
468 | |
469 void ExtensionEventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( | |
470 Profile* profile, | |
471 const Extension* extension, | |
472 const linked_ptr<ExtensionEvent>& event) { | |
473 const Value* event_args = NULL; | |
474 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) | |
475 return; | |
476 | |
477 extensions::LazyBackgroundTaskQueue* queue = | |
478 extensions::ExtensionSystem::Get(profile)->lazy_background_task_queue(); | |
479 if (queue->ShouldEnqueueTask(profile, extension)) { | |
480 queue->AddPendingTask( | |
481 profile, extension->id(), | |
482 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, | |
483 base::Unretained(this), event)); | |
484 } | |
485 } | |
486 | |
487 void ExtensionEventRouter::IncrementInFlightEvents( | |
488 Profile* profile, const Extension* extension) { | |
489 // Only increment in-flight events if the lazy background page is active, | |
490 // because that's the only time we'll get an ACK. | |
491 if (extension->has_lazy_background_page()) { | |
492 ExtensionProcessManager* pm = | |
493 extensions::ExtensionSystem::Get(profile)->process_manager(); | |
494 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id()); | |
495 if (host) | |
496 pm->IncrementLazyKeepaliveCount(extension); | |
497 } | |
498 } | |
499 | |
500 void ExtensionEventRouter::OnEventAck( | |
501 Profile* profile, const std::string& extension_id) { | |
502 ExtensionProcessManager* pm = | |
503 extensions::ExtensionSystem::Get(profile)->process_manager(); | |
504 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); | |
505 // The event ACK is routed to the background host, so this should never be | |
506 // NULL. | |
507 CHECK(host); | |
508 // TODO(mpcomplete): We should never get this message unless | |
509 // has_lazy_background_page is true. Find out why we're getting it anyway. | |
510 if (host->extension() && host->extension()->has_lazy_background_page()) | |
511 pm->DecrementLazyKeepaliveCount(host->extension()); | |
512 } | |
513 | |
514 void ExtensionEventRouter::DispatchPendingEvent( | |
515 const linked_ptr<ExtensionEvent>& event, | |
516 ExtensionHost* host) { | |
517 if (!host) | |
518 return; | |
519 | |
520 if (listeners_.HasProcessListener(host->render_process_host(), | |
521 host->extension()->id())) | |
522 DispatchEventToProcess(host->extension()->id(), | |
523 host->render_process_host(), event); | |
524 } | |
525 | |
526 void ExtensionEventRouter::Observe( | |
527 int type, | |
528 const content::NotificationSource& source, | |
529 const content::NotificationDetails& details) { | |
530 switch (type) { | |
531 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | |
532 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | |
533 content::RenderProcessHost* renderer = | |
534 content::Source<content::RenderProcessHost>(source).ptr(); | |
535 // Remove all event listeners associated with this renderer. | |
536 listeners_.RemoveListenersForProcess(renderer); | |
537 break; | |
538 } | |
539 case chrome::NOTIFICATION_EXTENSION_LOADED: { | |
540 // Add all registered lazy listeners to our cache. | |
541 const Extension* extension = | |
542 content::Details<const Extension>(details).ptr(); | |
543 extensions::ExtensionPrefs* prefs = | |
544 profile_->GetExtensionService()->extension_prefs(); | |
545 std::set<std::string> registered_events = | |
546 prefs->GetRegisteredEvents(extension->id()); | |
547 listeners_.LoadUnfilteredLazyListeners(extension->id(), | |
548 registered_events); | |
549 const DictionaryValue* filtered_events = | |
550 prefs->GetFilteredEvents(extension->id()); | |
551 if (filtered_events) | |
552 listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events); | |
553 break; | |
554 } | |
555 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | |
556 // Remove all registered lazy listeners from our cache. | |
557 extensions::UnloadedExtensionInfo* unloaded = | |
558 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); | |
559 listeners_.RemoveLazyListenersForExtension(unloaded->extension->id()); | |
560 break; | |
561 } | |
562 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | |
563 // Dispatch the onInstalled event. | |
564 const Extension* extension = | |
565 content::Details<const Extension>(details).ptr(); | |
566 MessageLoop::current()->PostTask(FROM_HERE, | |
567 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, | |
568 profile_, extension->id())); | |
569 break; | |
570 } | |
571 default: | |
572 NOTREACHED(); | |
573 return; | |
574 } | |
575 } | |
576 | |
577 ExtensionEvent::ExtensionEvent( | |
578 const std::string& event_name, | |
579 const Value& event_args, | |
580 const GURL& event_url, | |
581 Profile* restrict_to_profile, | |
582 const Value& cross_incognito_args, | |
583 ExtensionEventRouter::UserGestureState user_gesture, | |
584 const extensions::EventFilteringInfo& info) | |
585 : event_name(event_name), | |
586 event_args(event_args.DeepCopy()), | |
587 event_url(event_url), | |
588 restrict_to_profile(restrict_to_profile), | |
589 cross_incognito_args(cross_incognito_args.DeepCopy()), | |
590 user_gesture(user_gesture), | |
591 info(info) { | |
592 } | |
593 | |
594 ExtensionEvent::ExtensionEvent( | |
595 const std::string& event_name, | |
596 const std::string& event_args, | |
597 const GURL& event_url, | |
598 Profile* restrict_to_profile, | |
599 const std::string& cross_incognito_args, | |
600 ExtensionEventRouter::UserGestureState user_gesture, | |
601 const extensions::EventFilteringInfo& info) | |
602 : event_name(event_name), | |
603 event_args(Value::CreateStringValue(event_args)), | |
604 event_url(event_url), | |
605 restrict_to_profile(restrict_to_profile), | |
606 cross_incognito_args(Value::CreateStringValue(cross_incognito_args)), | |
607 user_gesture(user_gesture), | |
608 info(info) { | |
609 } | |
610 | |
611 ExtensionEvent::ExtensionEvent( | |
612 const std::string& event_name, | |
613 const Value& event_args, | |
614 const GURL& event_url, | |
615 Profile* restrict_to_profile, | |
616 ExtensionEventRouter::UserGestureState user_gesture, | |
617 const extensions::EventFilteringInfo& info) | |
618 : event_name(event_name), | |
619 event_args(event_args.DeepCopy()), | |
620 event_url(event_url), | |
621 restrict_to_profile(restrict_to_profile), | |
622 cross_incognito_args(NULL), | |
623 user_gesture(user_gesture), | |
624 info(info) { | |
625 } | |
626 | |
627 ExtensionEvent::~ExtensionEvent() { | |
628 } | |
OLD | NEW |