Revert 264226 "Reduce dependency of TiclInvalidationService on P..."
[chromium-blink-merge.git] / extensions / browser / event_router.cc
blob4a165e3b993a3aa8e3c6df360736f0bc957409d2
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.
5 #include "extensions/browser/event_router.h"
7 #include <utility>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/stl_util.h"
13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "extensions/browser/api_activity_monitor.h"
18 #include "extensions/browser/extension_host.h"
19 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/browser/extensions_browser_client.h"
23 #include "extensions/browser/lazy_background_task_queue.h"
24 #include "extensions/browser/process_manager.h"
25 #include "extensions/browser/process_map.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/extension_api.h"
28 #include "extensions/common/extension_messages.h"
29 #include "extensions/common/extension_urls.h"
30 #include "extensions/common/manifest_handlers/background_info.h"
31 #include "extensions/common/manifest_handlers/incognito_info.h"
33 using base::DictionaryValue;
34 using base::ListValue;
35 using content::BrowserContext;
36 using content::BrowserThread;
38 namespace extensions {
40 namespace {
42 void DoNothing(ExtensionHost* host) {}
44 // A dictionary of event names to lists of filters that this extension has
45 // registered from its lazy background page.
46 const char kFilteredEvents[] = "filtered_events";
48 // Sends a notification about an event to the API activity monitor on the
49 // UI thread. Can be called from any thread.
50 void NotifyApiEventDispatched(void* browser_context_id,
51 const std::string& extension_id,
52 const std::string& event_name,
53 scoped_ptr<ListValue> args) {
54 // The ApiActivityMonitor can only be accessed from the UI thread.
55 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
56 BrowserThread::PostTask(
57 BrowserThread::UI,
58 FROM_HERE,
59 base::Bind(&NotifyApiEventDispatched,
60 browser_context_id,
61 extension_id,
62 event_name,
63 base::Passed(&args)));
64 return;
67 // Notify the ApiActivityMonitor about the event dispatch.
68 BrowserContext* context = static_cast<BrowserContext*>(browser_context_id);
69 if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
70 return;
71 ApiActivityMonitor* monitor =
72 ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context);
73 if (monitor)
74 monitor->OnApiEventDispatched(extension_id, event_name, args.Pass());
77 } // namespace
79 const char EventRouter::kRegisteredEvents[] = "events";
81 struct EventRouter::ListenerProcess {
82 content::RenderProcessHost* process;
83 std::string extension_id;
85 ListenerProcess(content::RenderProcessHost* process,
86 const std::string& extension_id)
87 : process(process), extension_id(extension_id) {}
89 bool operator<(const ListenerProcess& that) const {
90 if (process < that.process)
91 return true;
92 if (process == that.process && extension_id < that.extension_id)
93 return true;
94 return false;
98 // static
99 void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
100 void* browser_context_id,
101 const std::string& extension_id,
102 const std::string& event_name,
103 ListValue* event_args,
104 UserGestureState user_gesture,
105 const EventFilteringInfo& info) {
106 NotifyApiEventDispatched(browser_context_id,
107 extension_id,
108 event_name,
109 make_scoped_ptr(event_args->DeepCopy()));
111 ListValue args;
112 args.Set(0, new base::StringValue(event_name));
113 args.Set(1, event_args);
114 args.Set(2, info.AsValue().release());
115 ipc_sender->Send(new ExtensionMsg_MessageInvoke(
116 MSG_ROUTING_CONTROL,
117 extension_id,
118 kEventBindings,
119 "dispatchEvent",
120 args,
121 user_gesture == USER_GESTURE_ENABLED));
123 // DispatchExtensionMessage does _not_ take ownership of event_args, so we
124 // must ensure that the destruction of args does not attempt to free it.
125 scoped_ptr<base::Value> removed_event_args;
126 args.Remove(1, &removed_event_args);
127 ignore_result(removed_event_args.release());
130 // static
131 EventRouter* EventRouter::Get(content::BrowserContext* browser_context) {
132 return ExtensionSystem::Get(browser_context)->event_router();
135 // static
136 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
137 size_t slash_sep = full_event_name.find('/');
138 return full_event_name.substr(0, slash_sep);
141 // static
142 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
143 void* browser_context_id,
144 const std::string& extension_id,
145 const std::string& event_name,
146 scoped_ptr<ListValue> event_args,
147 UserGestureState user_gesture,
148 const EventFilteringInfo& info) {
149 DispatchExtensionMessage(ipc_sender,
150 browser_context_id,
151 extension_id,
152 event_name,
153 event_args.get(),
154 user_gesture,
155 info);
157 BrowserThread::PostTask(
158 BrowserThread::UI,
159 FROM_HERE,
160 base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
161 browser_context_id,
162 extension_id));
165 EventRouter::EventRouter(BrowserContext* browser_context,
166 ExtensionPrefs* extension_prefs)
167 : browser_context_(browser_context),
168 extension_prefs_(extension_prefs),
169 listeners_(this) {
170 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
171 content::NotificationService::AllSources());
172 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
173 content::NotificationService::AllSources());
174 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
175 content::Source<BrowserContext>(browser_context_));
176 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
177 content::Source<BrowserContext>(browser_context_));
178 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
179 content::Source<BrowserContext>(browser_context_));
182 EventRouter::~EventRouter() {}
184 void EventRouter::AddEventListener(const std::string& event_name,
185 content::RenderProcessHost* process,
186 const std::string& extension_id) {
187 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
188 event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
191 void EventRouter::RemoveEventListener(const std::string& event_name,
192 content::RenderProcessHost* process,
193 const std::string& extension_id) {
194 EventListener listener(event_name, extension_id, process,
195 scoped_ptr<DictionaryValue>());
196 listeners_.RemoveListener(&listener);
199 void EventRouter::RegisterObserver(Observer* observer,
200 const std::string& event_name) {
201 // Observing sub-event names like "foo.onBar/123" is not allowed.
202 DCHECK(event_name.find('/') == std::string::npos);
203 observers_[event_name] = observer;
206 void EventRouter::UnregisterObserver(Observer* observer) {
207 std::vector<ObserverMap::iterator> iters_to_remove;
208 for (ObserverMap::iterator iter = observers_.begin();
209 iter != observers_.end(); ++iter) {
210 if (iter->second == observer)
211 iters_to_remove.push_back(iter);
213 for (size_t i = 0; i < iters_to_remove.size(); ++i)
214 observers_.erase(iters_to_remove[i]);
217 void EventRouter::OnListenerAdded(const EventListener* listener) {
218 const EventListenerInfo details(
219 listener->event_name,
220 listener->extension_id,
221 listener->process ? listener->process->GetBrowserContext() : NULL);
222 std::string base_event_name = GetBaseEventName(listener->event_name);
223 ObserverMap::iterator observer = observers_.find(base_event_name);
224 if (observer != observers_.end())
225 observer->second->OnListenerAdded(details);
228 void EventRouter::OnListenerRemoved(const EventListener* listener) {
229 const EventListenerInfo details(
230 listener->event_name,
231 listener->extension_id,
232 listener->process ? listener->process->GetBrowserContext() : NULL);
233 std::string base_event_name = GetBaseEventName(listener->event_name);
234 ObserverMap::iterator observer = observers_.find(base_event_name);
235 if (observer != observers_.end())
236 observer->second->OnListenerRemoved(details);
239 void EventRouter::AddLazyEventListener(const std::string& event_name,
240 const std::string& extension_id) {
241 scoped_ptr<EventListener> listener(new EventListener(
242 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
243 bool is_new = listeners_.AddListener(listener.Pass());
245 if (is_new) {
246 std::set<std::string> events = GetRegisteredEvents(extension_id);
247 bool prefs_is_new = events.insert(event_name).second;
248 if (prefs_is_new)
249 SetRegisteredEvents(extension_id, events);
253 void EventRouter::RemoveLazyEventListener(const std::string& event_name,
254 const std::string& extension_id) {
255 EventListener listener(event_name, extension_id, NULL,
256 scoped_ptr<DictionaryValue>());
257 bool did_exist = listeners_.RemoveListener(&listener);
259 if (did_exist) {
260 std::set<std::string> events = GetRegisteredEvents(extension_id);
261 bool prefs_did_exist = events.erase(event_name) > 0;
262 DCHECK(prefs_did_exist);
263 SetRegisteredEvents(extension_id, events);
267 void EventRouter::AddFilteredEventListener(const std::string& event_name,
268 content::RenderProcessHost* process,
269 const std::string& extension_id,
270 const base::DictionaryValue& filter,
271 bool add_lazy_listener) {
272 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
273 event_name, extension_id, process,
274 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
276 if (add_lazy_listener) {
277 bool added = listeners_.AddListener(scoped_ptr<EventListener>(
278 new EventListener(event_name, extension_id, NULL,
279 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
281 if (added)
282 AddFilterToEvent(event_name, extension_id, &filter);
286 void EventRouter::RemoveFilteredEventListener(
287 const std::string& event_name,
288 content::RenderProcessHost* process,
289 const std::string& extension_id,
290 const base::DictionaryValue& filter,
291 bool remove_lazy_listener) {
292 EventListener listener(event_name, extension_id, process,
293 scoped_ptr<DictionaryValue>(filter.DeepCopy()));
295 listeners_.RemoveListener(&listener);
297 if (remove_lazy_listener) {
298 listener.process = NULL;
299 bool removed = listeners_.RemoveListener(&listener);
301 if (removed)
302 RemoveFilterFromEvent(event_name, extension_id, &filter);
306 bool EventRouter::HasEventListener(const std::string& event_name) {
307 return listeners_.HasListenerForEvent(event_name);
310 bool EventRouter::ExtensionHasEventListener(const std::string& extension_id,
311 const std::string& event_name) {
312 return listeners_.HasListenerForExtension(extension_id, event_name);
315 bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map,
316 const std::string& extension_id,
317 const std::string& event_name) {
318 ListenerMap::const_iterator it = listener_map.find(event_name);
319 if (it == listener_map.end())
320 return false;
322 const std::set<ListenerProcess>& listeners = it->second;
323 if (extension_id.empty())
324 return !listeners.empty();
326 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
327 listener != listeners.end(); ++listener) {
328 if (listener->extension_id == extension_id)
329 return true;
331 return false;
334 std::set<std::string> EventRouter::GetRegisteredEvents(
335 const std::string& extension_id) {
336 std::set<std::string> events;
337 const ListValue* events_value = NULL;
339 if (!extension_prefs_ ||
340 !extension_prefs_->ReadPrefAsList(
341 extension_id, kRegisteredEvents, &events_value)) {
342 return events;
345 for (size_t i = 0; i < events_value->GetSize(); ++i) {
346 std::string event;
347 if (events_value->GetString(i, &event))
348 events.insert(event);
350 return events;
353 void EventRouter::SetRegisteredEvents(const std::string& extension_id,
354 const std::set<std::string>& events) {
355 ListValue* events_value = new ListValue;
356 for (std::set<std::string>::const_iterator iter = events.begin();
357 iter != events.end(); ++iter) {
358 events_value->Append(new base::StringValue(*iter));
360 extension_prefs_->UpdateExtensionPref(
361 extension_id, kRegisteredEvents, events_value);
364 void EventRouter::AddFilterToEvent(const std::string& event_name,
365 const std::string& extension_id,
366 const DictionaryValue* filter) {
367 ExtensionPrefs::ScopedDictionaryUpdate update(
368 extension_prefs_, extension_id, kFilteredEvents);
369 DictionaryValue* filtered_events = update.Get();
370 if (!filtered_events)
371 filtered_events = update.Create();
373 ListValue* filter_list = NULL;
374 if (!filtered_events->GetList(event_name, &filter_list)) {
375 filter_list = new ListValue;
376 filtered_events->SetWithoutPathExpansion(event_name, filter_list);
379 filter_list->Append(filter->DeepCopy());
382 void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
383 const std::string& extension_id,
384 const DictionaryValue* filter) {
385 ExtensionPrefs::ScopedDictionaryUpdate update(
386 extension_prefs_, extension_id, kFilteredEvents);
387 DictionaryValue* filtered_events = update.Get();
388 ListValue* filter_list = NULL;
389 if (!filtered_events ||
390 !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
391 return;
394 for (size_t i = 0; i < filter_list->GetSize(); i++) {
395 DictionaryValue* filter = NULL;
396 CHECK(filter_list->GetDictionary(i, &filter));
397 if (filter->Equals(filter)) {
398 filter_list->Remove(i, NULL);
399 break;
404 const DictionaryValue* EventRouter::GetFilteredEvents(
405 const std::string& extension_id) {
406 const DictionaryValue* events = NULL;
407 extension_prefs_->ReadPrefAsDictionary(
408 extension_id, kFilteredEvents, &events);
409 return events;
412 void EventRouter::BroadcastEvent(scoped_ptr<Event> event) {
413 DispatchEventImpl(std::string(), linked_ptr<Event>(event.release()));
416 void EventRouter::DispatchEventToExtension(const std::string& extension_id,
417 scoped_ptr<Event> event) {
418 DCHECK(!extension_id.empty());
419 DispatchEventImpl(extension_id, linked_ptr<Event>(event.release()));
422 void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
423 scoped_ptr<Event> event) {
424 DCHECK(!extension_id.empty());
425 std::string event_name = event->event_name;
426 bool has_listener = ExtensionHasEventListener(extension_id, event_name);
427 if (!has_listener)
428 AddLazyEventListener(event_name, extension_id);
429 DispatchEventToExtension(extension_id, event.Pass());
430 if (!has_listener)
431 RemoveLazyEventListener(event_name, extension_id);
434 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
435 const linked_ptr<Event>& event) {
436 // We don't expect to get events from a completely different browser context.
437 DCHECK(!event->restrict_to_browser_context ||
438 ExtensionsBrowserClient::Get()->IsSameContext(
439 browser_context_, event->restrict_to_browser_context));
441 std::set<const EventListener*> listeners(
442 listeners_.GetEventListeners(*event));
444 std::set<EventDispatchIdentifier> already_dispatched;
446 // We dispatch events for lazy background pages first because attempting to do
447 // so will cause those that are being suspended to cancel that suspension.
448 // As canceling a suspension entails sending an event to the affected
449 // background page, and as that event needs to be delivered before we dispatch
450 // the event we are dispatching here, we dispatch to the lazy listeners here
451 // first.
452 for (std::set<const EventListener*>::iterator it = listeners.begin();
453 it != listeners.end(); it++) {
454 const EventListener* listener = *it;
455 if (restrict_to_extension_id.empty() ||
456 restrict_to_extension_id == listener->extension_id) {
457 if (!listener->process) {
458 DispatchLazyEvent(listener->extension_id, event, &already_dispatched);
463 for (std::set<const EventListener*>::iterator it = listeners.begin();
464 it != listeners.end(); it++) {
465 const EventListener* listener = *it;
466 if (restrict_to_extension_id.empty() ||
467 restrict_to_extension_id == listener->extension_id) {
468 if (listener->process) {
469 EventDispatchIdentifier dispatch_id(
470 listener->process->GetBrowserContext(), listener->extension_id);
471 if (!ContainsKey(already_dispatched, dispatch_id)) {
472 DispatchEventToProcess(listener->extension_id, listener->process,
473 event);
480 void EventRouter::DispatchLazyEvent(
481 const std::string& extension_id,
482 const linked_ptr<Event>& event,
483 std::set<EventDispatchIdentifier>* already_dispatched) {
484 // Check both the original and the incognito browser context to see if we
485 // should load a lazy bg page to handle the event. The latter case
486 // occurs in the case of split-mode extensions.
487 const Extension* extension =
488 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
489 extension_id);
490 if (!extension)
491 return;
493 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
494 browser_context_, extension, event)) {
495 already_dispatched->insert(std::make_pair(browser_context_, extension_id));
498 ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
499 if (browser_client->HasOffTheRecordContext(browser_context_) &&
500 IncognitoInfo::IsSplitMode(extension)) {
501 BrowserContext* incognito_context =
502 browser_client->GetOffTheRecordContext(browser_context_);
503 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
504 incognito_context, extension, event)) {
505 already_dispatched->insert(
506 std::make_pair(incognito_context, extension_id));
511 void EventRouter::DispatchEventToProcess(const std::string& extension_id,
512 content::RenderProcessHost* process,
513 const linked_ptr<Event>& event) {
514 const Extension* extension =
515 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
516 extension_id);
518 // The extension could have been removed, but we do not unregister it until
519 // the extension process is unloaded.
520 if (!extension)
521 return;
523 BrowserContext* listener_context = process->GetBrowserContext();
524 ProcessMap* process_map = ProcessMap::Get(listener_context);
525 // If the event is privileged, only send to extension processes. Otherwise,
526 // it's OK to send to normal renderers (e.g., for content scripts).
527 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
528 !process_map->Contains(extension->id(), process->GetID())) {
529 return;
532 // If the event is restricted to a URL, only dispatch if the extension has
533 // permission for it (or if the event originated from itself).
534 if (!event->event_url.is_empty() &&
535 event->event_url.host() != extension->id() &&
536 !extension->GetActivePermissions()->HasEffectiveAccessToURL(
537 event->event_url)) {
538 return;
541 if (!CanDispatchEventToBrowserContext(listener_context, extension, event))
542 return;
544 if (!event->will_dispatch_callback.is_null()) {
545 event->will_dispatch_callback.Run(listener_context, extension,
546 event->event_args.get());
549 DispatchExtensionMessage(process, listener_context, extension->id(),
550 event->event_name, event->event_args.get(),
551 event->user_gesture, event->filter_info);
552 IncrementInFlightEvents(listener_context, extension);
555 bool EventRouter::CanDispatchEventToBrowserContext(
556 BrowserContext* context,
557 const Extension* extension,
558 const linked_ptr<Event>& event) {
559 // Is this event from a different browser context than the renderer (ie, an
560 // incognito tab event sent to a normal process, or vice versa).
561 bool cross_incognito = event->restrict_to_browser_context &&
562 context != event->restrict_to_browser_context;
563 if (!cross_incognito)
564 return true;
565 return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
566 extension, context);
569 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
570 BrowserContext* context,
571 const Extension* extension,
572 const linked_ptr<Event>& event) {
573 if (extension->is_ephemeral() && !event->can_load_ephemeral_apps) {
574 // Most events can only be dispatched to ephemeral apps that are already
575 // running.
576 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
577 if (!pm->GetBackgroundHostForExtension(extension->id()))
578 return false;
581 if (!CanDispatchEventToBrowserContext(context, extension, event))
582 return false;
584 LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
585 context)->lazy_background_task_queue();
586 if (queue->ShouldEnqueueTask(context, extension)) {
587 linked_ptr<Event> dispatched_event(event);
589 // If there's a dispatch callback, call it now (rather than dispatch time)
590 // to avoid lifetime issues. Use a separate copy of the event args, so they
591 // last until the event is dispatched.
592 if (!event->will_dispatch_callback.is_null()) {
593 dispatched_event.reset(event->DeepCopy());
594 dispatched_event->will_dispatch_callback.Run(
595 context, extension, dispatched_event->event_args.get());
596 // Ensure we don't call it again at dispatch time.
597 dispatched_event->will_dispatch_callback.Reset();
600 queue->AddPendingTask(context, extension->id(),
601 base::Bind(&EventRouter::DispatchPendingEvent,
602 base::Unretained(this), dispatched_event));
603 return true;
606 return false;
609 // static
610 void EventRouter::IncrementInFlightEventsOnUI(
611 void* browser_context_id,
612 const std::string& extension_id) {
613 DCHECK_CURRENTLY_ON(BrowserThread::UI);
614 BrowserContext* browser_context =
615 reinterpret_cast<BrowserContext*>(browser_context_id);
616 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
617 return;
618 ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context);
619 EventRouter* event_router = extension_system->event_router();
620 if (!event_router)
621 return;
622 const Extension* extension =
623 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
624 extension_id);
625 if (!extension)
626 return;
627 event_router->IncrementInFlightEvents(browser_context, extension);
630 void EventRouter::IncrementInFlightEvents(BrowserContext* context,
631 const Extension* extension) {
632 // Only increment in-flight events if the lazy background page is active,
633 // because that's the only time we'll get an ACK.
634 if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
635 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
636 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
637 if (host)
638 pm->IncrementLazyKeepaliveCount(extension);
642 void EventRouter::OnEventAck(BrowserContext* context,
643 const std::string& extension_id) {
644 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
645 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
646 // The event ACK is routed to the background host, so this should never be
647 // NULL.
648 CHECK(host);
649 // TODO(mpcomplete): We should never get this message unless
650 // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
651 if (host->extension() &&
652 BackgroundInfo::HasLazyBackgroundPage(host->extension()))
653 pm->DecrementLazyKeepaliveCount(host->extension());
656 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
657 ExtensionHost* host) {
658 if (!host)
659 return;
661 if (listeners_.HasProcessListener(host->render_process_host(),
662 host->extension()->id())) {
663 DispatchEventToProcess(host->extension()->id(),
664 host->render_process_host(), event);
668 void EventRouter::Observe(int type,
669 const content::NotificationSource& source,
670 const content::NotificationDetails& details) {
671 switch (type) {
672 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
673 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
674 content::RenderProcessHost* renderer =
675 content::Source<content::RenderProcessHost>(source).ptr();
676 // Remove all event listeners associated with this renderer.
677 listeners_.RemoveListenersForProcess(renderer);
678 break;
680 case chrome::NOTIFICATION_EXTENSION_ENABLED: {
681 // If the extension has a lazy background page, make sure it gets loaded
682 // to register the events the extension is interested in.
683 const Extension* extension =
684 content::Details<const Extension>(details).ptr();
685 if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
686 LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
687 browser_context_)->lazy_background_task_queue();
688 queue->AddPendingTask(browser_context_, extension->id(),
689 base::Bind(&DoNothing));
691 break;
693 case chrome::NOTIFICATION_EXTENSION_LOADED: {
694 // Add all registered lazy listeners to our cache.
695 const Extension* extension =
696 content::Details<const Extension>(details).ptr();
697 std::set<std::string> registered_events =
698 GetRegisteredEvents(extension->id());
699 listeners_.LoadUnfilteredLazyListeners(extension->id(),
700 registered_events);
701 const DictionaryValue* filtered_events =
702 GetFilteredEvents(extension->id());
703 if (filtered_events)
704 listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
705 break;
707 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
708 // Remove all registered lazy listeners from our cache.
709 UnloadedExtensionInfo* unloaded =
710 content::Details<UnloadedExtensionInfo>(details).ptr();
711 listeners_.RemoveLazyListenersForExtension(unloaded->extension->id());
712 break;
714 default:
715 NOTREACHED();
716 return;
720 Event::Event(const std::string& event_name,
721 scoped_ptr<base::ListValue> event_args)
722 : event_name(event_name),
723 event_args(event_args.Pass()),
724 restrict_to_browser_context(NULL),
725 user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
726 can_load_ephemeral_apps(false) {
727 DCHECK(this->event_args.get());
730 Event::Event(const std::string& event_name,
731 scoped_ptr<base::ListValue> event_args,
732 BrowserContext* restrict_to_browser_context)
733 : event_name(event_name),
734 event_args(event_args.Pass()),
735 restrict_to_browser_context(restrict_to_browser_context),
736 user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
737 can_load_ephemeral_apps(false) {
738 DCHECK(this->event_args.get());
741 Event::Event(const std::string& event_name,
742 scoped_ptr<ListValue> event_args,
743 BrowserContext* restrict_to_browser_context,
744 const GURL& event_url,
745 EventRouter::UserGestureState user_gesture,
746 const EventFilteringInfo& filter_info)
747 : event_name(event_name),
748 event_args(event_args.Pass()),
749 restrict_to_browser_context(restrict_to_browser_context),
750 event_url(event_url),
751 user_gesture(user_gesture),
752 filter_info(filter_info),
753 can_load_ephemeral_apps(false) {
754 DCHECK(this->event_args.get());
757 Event::~Event() {}
759 Event* Event::DeepCopy() {
760 Event* copy = new Event(event_name,
761 scoped_ptr<base::ListValue>(event_args->DeepCopy()),
762 restrict_to_browser_context,
763 event_url,
764 user_gesture,
765 filter_info);
766 copy->will_dispatch_callback = will_dispatch_callback;
767 return copy;
770 EventListenerInfo::EventListenerInfo(const std::string& event_name,
771 const std::string& extension_id,
772 content::BrowserContext* browser_context)
773 : event_name(event_name),
774 extension_id(extension_id),
775 browser_context(browser_context) {}
777 } // namespace extensions