Fix import error in mac_platform_backend.py
[chromium-blink-merge.git] / extensions / browser / event_router.cc
blobd1450590a5b32f702833e7d4f92759fcd129a25d
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 "chrome/browser/extensions/extension_host.h"
16 #include "chrome/browser/extensions/extension_util.h"
17 #include "chrome/common/extensions/extension_messages.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "extensions/browser/api_activity_monitor.h"
21 #include "extensions/browser/extension_prefs.h"
22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/browser/extension_system.h"
24 #include "extensions/browser/extensions_browser_client.h"
25 #include "extensions/browser/lazy_background_task_queue.h"
26 #include "extensions/browser/process_manager.h"
27 #include "extensions/browser/process_map.h"
28 #include "extensions/common/extension.h"
29 #include "extensions/common/extension_api.h"
30 #include "extensions/common/extension_urls.h"
31 #include "extensions/common/manifest_handlers/background_info.h"
32 #include "extensions/common/manifest_handlers/incognito_info.h"
34 using base::DictionaryValue;
35 using base::ListValue;
36 using content::BrowserContext;
37 using content::BrowserThread;
39 namespace extensions {
41 namespace {
43 void DoNothing(ExtensionHost* host) {}
45 // A dictionary of event names to lists of filters that this extension has
46 // registered from its lazy background page.
47 const char kFilteredEvents[] = "filtered_events";
49 // Sends a notification about an event to the API activity monitor on the
50 // UI thread. Can be called from any thread.
51 void NotifyApiEventDispatched(void* browser_context_id,
52 const std::string& extension_id,
53 const std::string& event_name,
54 scoped_ptr<ListValue> args) {
55 // The ApiActivityMonitor can only be accessed from the UI thread.
56 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
57 BrowserThread::PostTask(
58 BrowserThread::UI,
59 FROM_HERE,
60 base::Bind(&NotifyApiEventDispatched,
61 browser_context_id,
62 extension_id,
63 event_name,
64 base::Passed(&args)));
65 return;
68 // Notify the ApiActivityMonitor about the event dispatch.
69 BrowserContext* context = static_cast<BrowserContext*>(browser_context_id);
70 if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
71 return;
72 ApiActivityMonitor* monitor =
73 ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context);
74 if (monitor)
75 monitor->OnApiEventDispatched(extension_id, event_name, args.Pass());
78 } // namespace
80 const char EventRouter::kRegisteredEvents[] = "events";
82 struct EventRouter::ListenerProcess {
83 content::RenderProcessHost* process;
84 std::string extension_id;
86 ListenerProcess(content::RenderProcessHost* process,
87 const std::string& extension_id)
88 : process(process), extension_id(extension_id) {}
90 bool operator<(const ListenerProcess& that) const {
91 if (process < that.process)
92 return true;
93 if (process == that.process && extension_id < that.extension_id)
94 return true;
95 return false;
99 // static
100 void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
101 void* browser_context_id,
102 const std::string& extension_id,
103 const std::string& event_name,
104 ListValue* event_args,
105 UserGestureState user_gesture,
106 const EventFilteringInfo& info) {
107 NotifyApiEventDispatched(browser_context_id,
108 extension_id,
109 event_name,
110 make_scoped_ptr(event_args->DeepCopy()));
112 ListValue args;
113 args.Set(0, new base::StringValue(event_name));
114 args.Set(1, event_args);
115 args.Set(2, info.AsValue().release());
116 ipc_sender->Send(new ExtensionMsg_MessageInvoke(
117 MSG_ROUTING_CONTROL,
118 extension_id,
119 kEventBindings,
120 "dispatchEvent",
121 args,
122 user_gesture == USER_GESTURE_ENABLED));
124 // DispatchExtensionMessage does _not_ take ownership of event_args, so we
125 // must ensure that the destruction of args does not attempt to free it.
126 scoped_ptr<base::Value> removed_event_args;
127 args.Remove(1, &removed_event_args);
128 ignore_result(removed_event_args.release());
131 // static
132 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
133 size_t slash_sep = full_event_name.find('/');
134 return full_event_name.substr(0, slash_sep);
137 // static
138 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
139 void* browser_context_id,
140 const std::string& extension_id,
141 const std::string& event_name,
142 scoped_ptr<ListValue> event_args,
143 UserGestureState user_gesture,
144 const EventFilteringInfo& info) {
145 DispatchExtensionMessage(ipc_sender,
146 browser_context_id,
147 extension_id,
148 event_name,
149 event_args.get(),
150 user_gesture,
151 info);
153 BrowserThread::PostTask(
154 BrowserThread::UI,
155 FROM_HERE,
156 base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
157 browser_context_id,
158 extension_id));
161 EventRouter::EventRouter(BrowserContext* browser_context,
162 ExtensionPrefs* extension_prefs)
163 : browser_context_(browser_context),
164 extension_prefs_(extension_prefs),
165 listeners_(this) {
166 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
167 content::NotificationService::AllSources());
168 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
169 content::NotificationService::AllSources());
170 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
171 content::Source<BrowserContext>(browser_context_));
172 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
173 content::Source<BrowserContext>(browser_context_));
174 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
175 content::Source<BrowserContext>(browser_context_));
178 EventRouter::~EventRouter() {}
180 void EventRouter::AddEventListener(const std::string& event_name,
181 content::RenderProcessHost* process,
182 const std::string& extension_id) {
183 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
184 event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
187 void EventRouter::RemoveEventListener(const std::string& event_name,
188 content::RenderProcessHost* process,
189 const std::string& extension_id) {
190 EventListener listener(event_name, extension_id, process,
191 scoped_ptr<DictionaryValue>());
192 listeners_.RemoveListener(&listener);
195 void EventRouter::RegisterObserver(Observer* observer,
196 const std::string& event_name) {
197 // Observing sub-event names like "foo.onBar/123" is not allowed.
198 DCHECK(event_name.find('/') == std::string::npos);
199 observers_[event_name] = observer;
202 void EventRouter::UnregisterObserver(Observer* observer) {
203 std::vector<ObserverMap::iterator> iters_to_remove;
204 for (ObserverMap::iterator iter = observers_.begin();
205 iter != observers_.end(); ++iter) {
206 if (iter->second == observer)
207 iters_to_remove.push_back(iter);
209 for (size_t i = 0; i < iters_to_remove.size(); ++i)
210 observers_.erase(iters_to_remove[i]);
213 void EventRouter::OnListenerAdded(const EventListener* listener) {
214 const EventListenerInfo details(
215 listener->event_name,
216 listener->extension_id,
217 listener->process ? listener->process->GetBrowserContext() : NULL);
218 std::string base_event_name = GetBaseEventName(listener->event_name);
219 ObserverMap::iterator observer = observers_.find(base_event_name);
220 if (observer != observers_.end())
221 observer->second->OnListenerAdded(details);
224 void EventRouter::OnListenerRemoved(const EventListener* listener) {
225 const EventListenerInfo details(
226 listener->event_name,
227 listener->extension_id,
228 listener->process ? listener->process->GetBrowserContext() : NULL);
229 std::string base_event_name = GetBaseEventName(listener->event_name);
230 ObserverMap::iterator observer = observers_.find(base_event_name);
231 if (observer != observers_.end())
232 observer->second->OnListenerRemoved(details);
235 void EventRouter::AddLazyEventListener(const std::string& event_name,
236 const std::string& extension_id) {
237 scoped_ptr<EventListener> listener(new EventListener(
238 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
239 bool is_new = listeners_.AddListener(listener.Pass());
241 if (is_new) {
242 std::set<std::string> events = GetRegisteredEvents(extension_id);
243 bool prefs_is_new = events.insert(event_name).second;
244 if (prefs_is_new)
245 SetRegisteredEvents(extension_id, events);
249 void EventRouter::RemoveLazyEventListener(const std::string& event_name,
250 const std::string& extension_id) {
251 EventListener listener(event_name, extension_id, NULL,
252 scoped_ptr<DictionaryValue>());
253 bool did_exist = listeners_.RemoveListener(&listener);
255 if (did_exist) {
256 std::set<std::string> events = GetRegisteredEvents(extension_id);
257 bool prefs_did_exist = events.erase(event_name) > 0;
258 DCHECK(prefs_did_exist);
259 SetRegisteredEvents(extension_id, events);
263 void EventRouter::AddFilteredEventListener(const std::string& event_name,
264 content::RenderProcessHost* process,
265 const std::string& extension_id,
266 const base::DictionaryValue& filter,
267 bool add_lazy_listener) {
268 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
269 event_name, extension_id, process,
270 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
272 if (add_lazy_listener) {
273 bool added = listeners_.AddListener(scoped_ptr<EventListener>(
274 new EventListener(event_name, extension_id, NULL,
275 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
277 if (added)
278 AddFilterToEvent(event_name, extension_id, &filter);
282 void EventRouter::RemoveFilteredEventListener(
283 const std::string& event_name,
284 content::RenderProcessHost* process,
285 const std::string& extension_id,
286 const base::DictionaryValue& filter,
287 bool remove_lazy_listener) {
288 EventListener listener(event_name, extension_id, process,
289 scoped_ptr<DictionaryValue>(filter.DeepCopy()));
291 listeners_.RemoveListener(&listener);
293 if (remove_lazy_listener) {
294 listener.process = NULL;
295 bool removed = listeners_.RemoveListener(&listener);
297 if (removed)
298 RemoveFilterFromEvent(event_name, extension_id, &filter);
302 bool EventRouter::HasEventListener(const std::string& event_name) {
303 return listeners_.HasListenerForEvent(event_name);
306 bool EventRouter::ExtensionHasEventListener(const std::string& extension_id,
307 const std::string& event_name) {
308 return listeners_.HasListenerForExtension(extension_id, event_name);
311 bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map,
312 const std::string& extension_id,
313 const std::string& event_name) {
314 ListenerMap::const_iterator it = listener_map.find(event_name);
315 if (it == listener_map.end())
316 return false;
318 const std::set<ListenerProcess>& listeners = it->second;
319 if (extension_id.empty())
320 return !listeners.empty();
322 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
323 listener != listeners.end(); ++listener) {
324 if (listener->extension_id == extension_id)
325 return true;
327 return false;
330 std::set<std::string> EventRouter::GetRegisteredEvents(
331 const std::string& extension_id) {
332 std::set<std::string> events;
333 const ListValue* events_value = NULL;
335 if (!extension_prefs_ ||
336 !extension_prefs_->ReadPrefAsList(
337 extension_id, kRegisteredEvents, &events_value)) {
338 return events;
341 for (size_t i = 0; i < events_value->GetSize(); ++i) {
342 std::string event;
343 if (events_value->GetString(i, &event))
344 events.insert(event);
346 return events;
349 void EventRouter::SetRegisteredEvents(const std::string& extension_id,
350 const std::set<std::string>& events) {
351 ListValue* events_value = new ListValue;
352 for (std::set<std::string>::const_iterator iter = events.begin();
353 iter != events.end(); ++iter) {
354 events_value->Append(new base::StringValue(*iter));
356 extension_prefs_->UpdateExtensionPref(
357 extension_id, kRegisteredEvents, events_value);
360 void EventRouter::AddFilterToEvent(const std::string& event_name,
361 const std::string& extension_id,
362 const DictionaryValue* filter) {
363 ExtensionPrefs::ScopedDictionaryUpdate update(
364 extension_prefs_, extension_id, kFilteredEvents);
365 DictionaryValue* filtered_events = update.Get();
366 if (!filtered_events)
367 filtered_events = update.Create();
369 ListValue* filter_list = NULL;
370 if (!filtered_events->GetList(event_name, &filter_list)) {
371 filter_list = new ListValue;
372 filtered_events->SetWithoutPathExpansion(event_name, filter_list);
375 filter_list->Append(filter->DeepCopy());
378 void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
379 const std::string& extension_id,
380 const DictionaryValue* filter) {
381 ExtensionPrefs::ScopedDictionaryUpdate update(
382 extension_prefs_, extension_id, kFilteredEvents);
383 DictionaryValue* filtered_events = update.Get();
384 ListValue* filter_list = NULL;
385 if (!filtered_events ||
386 !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
387 return;
390 for (size_t i = 0; i < filter_list->GetSize(); i++) {
391 DictionaryValue* filter = NULL;
392 CHECK(filter_list->GetDictionary(i, &filter));
393 if (filter->Equals(filter)) {
394 filter_list->Remove(i, NULL);
395 break;
400 const DictionaryValue* EventRouter::GetFilteredEvents(
401 const std::string& extension_id) {
402 const DictionaryValue* events = NULL;
403 extension_prefs_->ReadPrefAsDictionary(
404 extension_id, kFilteredEvents, &events);
405 return events;
408 void EventRouter::BroadcastEvent(scoped_ptr<Event> event) {
409 DispatchEventImpl(std::string(), linked_ptr<Event>(event.release()));
412 void EventRouter::DispatchEventToExtension(const std::string& extension_id,
413 scoped_ptr<Event> event) {
414 DCHECK(!extension_id.empty());
415 DispatchEventImpl(extension_id, linked_ptr<Event>(event.release()));
418 void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
419 scoped_ptr<Event> event) {
420 DCHECK(!extension_id.empty());
421 std::string event_name = event->event_name;
422 bool has_listener = ExtensionHasEventListener(extension_id, event_name);
423 if (!has_listener)
424 AddLazyEventListener(event_name, extension_id);
425 DispatchEventToExtension(extension_id, event.Pass());
426 if (!has_listener)
427 RemoveLazyEventListener(event_name, extension_id);
430 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
431 const linked_ptr<Event>& event) {
432 // We don't expect to get events from a completely different browser context.
433 DCHECK(!event->restrict_to_browser_context ||
434 ExtensionsBrowserClient::Get()->IsSameContext(
435 browser_context_, event->restrict_to_browser_context));
437 std::set<const EventListener*> listeners(
438 listeners_.GetEventListeners(*event));
440 std::set<EventDispatchIdentifier> already_dispatched;
442 // We dispatch events for lazy background pages first because attempting to do
443 // so will cause those that are being suspended to cancel that suspension.
444 // As canceling a suspension entails sending an event to the affected
445 // background page, and as that event needs to be delivered before we dispatch
446 // the event we are dispatching here, we dispatch to the lazy listeners here
447 // first.
448 for (std::set<const EventListener*>::iterator it = listeners.begin();
449 it != listeners.end(); it++) {
450 const EventListener* listener = *it;
451 if (restrict_to_extension_id.empty() ||
452 restrict_to_extension_id == listener->extension_id) {
453 if (!listener->process) {
454 DispatchLazyEvent(listener->extension_id, event, &already_dispatched);
459 for (std::set<const EventListener*>::iterator it = listeners.begin();
460 it != listeners.end(); it++) {
461 const EventListener* listener = *it;
462 if (restrict_to_extension_id.empty() ||
463 restrict_to_extension_id == listener->extension_id) {
464 if (listener->process) {
465 EventDispatchIdentifier dispatch_id(
466 listener->process->GetBrowserContext(), listener->extension_id);
467 if (!ContainsKey(already_dispatched, dispatch_id)) {
468 DispatchEventToProcess(listener->extension_id, listener->process,
469 event);
476 void EventRouter::DispatchLazyEvent(
477 const std::string& extension_id,
478 const linked_ptr<Event>& event,
479 std::set<EventDispatchIdentifier>* already_dispatched) {
480 // Check both the original and the incognito browser context to see if we
481 // should load a lazy bg page to handle the event. The latter case
482 // occurs in the case of split-mode extensions.
483 const Extension* extension =
484 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
485 extension_id);
486 if (!extension)
487 return;
489 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
490 browser_context_, extension, event)) {
491 already_dispatched->insert(std::make_pair(browser_context_, extension_id));
494 ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
495 if (browser_client->HasOffTheRecordContext(browser_context_) &&
496 IncognitoInfo::IsSplitMode(extension)) {
497 BrowserContext* incognito_context =
498 browser_client->GetOffTheRecordContext(browser_context_);
499 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
500 incognito_context, extension, event)) {
501 already_dispatched->insert(
502 std::make_pair(incognito_context, extension_id));
507 void EventRouter::DispatchEventToProcess(const std::string& extension_id,
508 content::RenderProcessHost* process,
509 const linked_ptr<Event>& event) {
510 const Extension* extension =
511 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
512 extension_id);
514 // The extension could have been removed, but we do not unregister it until
515 // the extension process is unloaded.
516 if (!extension)
517 return;
519 BrowserContext* listener_context = process->GetBrowserContext();
520 ProcessMap* process_map = ProcessMap::Get(listener_context);
521 // If the event is privileged, only send to extension processes. Otherwise,
522 // it's OK to send to normal renderers (e.g., for content scripts).
523 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
524 !process_map->Contains(extension->id(), process->GetID())) {
525 return;
528 // If the event is restricted to a URL, only dispatch if the extension has
529 // permission for it (or if the event originated from itself).
530 if (!event->event_url.is_empty() &&
531 event->event_url.host() != extension->id() &&
532 !extension->GetActivePermissions()->HasEffectiveAccessToURL(
533 event->event_url)) {
534 return;
537 if (!CanDispatchEventToBrowserContext(listener_context, extension, event))
538 return;
540 if (!event->will_dispatch_callback.is_null()) {
541 event->will_dispatch_callback.Run(listener_context, extension,
542 event->event_args.get());
545 DispatchExtensionMessage(process, listener_context, extension->id(),
546 event->event_name, event->event_args.get(),
547 event->user_gesture, event->filter_info);
548 IncrementInFlightEvents(listener_context, extension);
551 bool EventRouter::CanDispatchEventToBrowserContext(
552 BrowserContext* context,
553 const Extension* extension,
554 const linked_ptr<Event>& event) {
555 // Is this event from a different browser context than the renderer (ie, an
556 // incognito tab event sent to a normal process, or vice versa).
557 bool cross_incognito = event->restrict_to_browser_context &&
558 context != event->restrict_to_browser_context;
559 if (!cross_incognito)
560 return true;
561 return util::CanCrossIncognito(extension, context);
564 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
565 BrowserContext* context,
566 const Extension* extension,
567 const linked_ptr<Event>& event) {
568 if (extension->is_ephemeral() && !event->can_load_ephemeral_apps) {
569 // Most events can only be dispatched to ephemeral apps that are already
570 // running.
571 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
572 if (!pm->GetBackgroundHostForExtension(extension->id()))
573 return false;
576 if (!CanDispatchEventToBrowserContext(context, extension, event))
577 return false;
579 LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
580 context)->lazy_background_task_queue();
581 if (queue->ShouldEnqueueTask(context, extension)) {
582 linked_ptr<Event> dispatched_event(event);
584 // If there's a dispatch callback, call it now (rather than dispatch time)
585 // to avoid lifetime issues. Use a separate copy of the event args, so they
586 // last until the event is dispatched.
587 if (!event->will_dispatch_callback.is_null()) {
588 dispatched_event.reset(event->DeepCopy());
589 dispatched_event->will_dispatch_callback.Run(
590 context, extension, dispatched_event->event_args.get());
591 // Ensure we don't call it again at dispatch time.
592 dispatched_event->will_dispatch_callback.Reset();
595 queue->AddPendingTask(context, extension->id(),
596 base::Bind(&EventRouter::DispatchPendingEvent,
597 base::Unretained(this), dispatched_event));
598 return true;
601 return false;
604 // static
605 void EventRouter::IncrementInFlightEventsOnUI(
606 void* browser_context_id,
607 const std::string& extension_id) {
608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
609 BrowserContext* browser_context =
610 reinterpret_cast<BrowserContext*>(browser_context_id);
611 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
612 return;
613 ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context);
614 EventRouter* event_router = extension_system->event_router();
615 if (!event_router)
616 return;
617 const Extension* extension =
618 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
619 extension_id);
620 if (!extension)
621 return;
622 event_router->IncrementInFlightEvents(browser_context, extension);
625 void EventRouter::IncrementInFlightEvents(BrowserContext* context,
626 const Extension* extension) {
627 // Only increment in-flight events if the lazy background page is active,
628 // because that's the only time we'll get an ACK.
629 if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
630 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
631 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
632 if (host)
633 pm->IncrementLazyKeepaliveCount(extension);
637 void EventRouter::OnEventAck(BrowserContext* context,
638 const std::string& extension_id) {
639 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
640 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
641 // The event ACK is routed to the background host, so this should never be
642 // NULL.
643 CHECK(host);
644 // TODO(mpcomplete): We should never get this message unless
645 // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
646 if (host->extension() &&
647 BackgroundInfo::HasLazyBackgroundPage(host->extension()))
648 pm->DecrementLazyKeepaliveCount(host->extension());
651 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
652 ExtensionHost* host) {
653 if (!host)
654 return;
656 if (listeners_.HasProcessListener(host->render_process_host(),
657 host->extension()->id())) {
658 DispatchEventToProcess(host->extension()->id(),
659 host->render_process_host(), event);
663 void EventRouter::Observe(int type,
664 const content::NotificationSource& source,
665 const content::NotificationDetails& details) {
666 switch (type) {
667 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
668 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
669 content::RenderProcessHost* renderer =
670 content::Source<content::RenderProcessHost>(source).ptr();
671 // Remove all event listeners associated with this renderer.
672 listeners_.RemoveListenersForProcess(renderer);
673 break;
675 case chrome::NOTIFICATION_EXTENSION_ENABLED: {
676 // If the extension has a lazy background page, make sure it gets loaded
677 // to register the events the extension is interested in.
678 const Extension* extension =
679 content::Details<const Extension>(details).ptr();
680 if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
681 LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
682 browser_context_)->lazy_background_task_queue();
683 queue->AddPendingTask(browser_context_, extension->id(),
684 base::Bind(&DoNothing));
686 break;
688 case chrome::NOTIFICATION_EXTENSION_LOADED: {
689 // Add all registered lazy listeners to our cache.
690 const Extension* extension =
691 content::Details<const Extension>(details).ptr();
692 std::set<std::string> registered_events =
693 GetRegisteredEvents(extension->id());
694 listeners_.LoadUnfilteredLazyListeners(extension->id(),
695 registered_events);
696 const DictionaryValue* filtered_events =
697 GetFilteredEvents(extension->id());
698 if (filtered_events)
699 listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
700 break;
702 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
703 // Remove all registered lazy listeners from our cache.
704 UnloadedExtensionInfo* unloaded =
705 content::Details<UnloadedExtensionInfo>(details).ptr();
706 listeners_.RemoveLazyListenersForExtension(unloaded->extension->id());
707 break;
709 default:
710 NOTREACHED();
711 return;
715 Event::Event(const std::string& event_name,
716 scoped_ptr<base::ListValue> event_args)
717 : event_name(event_name),
718 event_args(event_args.Pass()),
719 restrict_to_browser_context(NULL),
720 user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
721 can_load_ephemeral_apps(false) {
722 DCHECK(this->event_args.get());
725 Event::Event(const std::string& event_name,
726 scoped_ptr<base::ListValue> event_args,
727 BrowserContext* restrict_to_browser_context)
728 : event_name(event_name),
729 event_args(event_args.Pass()),
730 restrict_to_browser_context(restrict_to_browser_context),
731 user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
732 can_load_ephemeral_apps(false) {
733 DCHECK(this->event_args.get());
736 Event::Event(const std::string& event_name,
737 scoped_ptr<ListValue> event_args,
738 BrowserContext* restrict_to_browser_context,
739 const GURL& event_url,
740 EventRouter::UserGestureState user_gesture,
741 const EventFilteringInfo& filter_info)
742 : event_name(event_name),
743 event_args(event_args.Pass()),
744 restrict_to_browser_context(restrict_to_browser_context),
745 event_url(event_url),
746 user_gesture(user_gesture),
747 filter_info(filter_info),
748 can_load_ephemeral_apps(false) {
749 DCHECK(this->event_args.get());
752 Event::~Event() {}
754 Event* Event::DeepCopy() {
755 Event* copy = new Event(event_name,
756 scoped_ptr<base::ListValue>(event_args->DeepCopy()),
757 restrict_to_browser_context,
758 event_url,
759 user_gesture,
760 filter_info);
761 copy->will_dispatch_callback = will_dispatch_callback;
762 return copy;
765 EventListenerInfo::EventListenerInfo(const std::string& event_name,
766 const std::string& extension_id,
767 content::BrowserContext* browser_context)
768 : event_name(event_name),
769 extension_id(extension_id),
770 browser_context(browser_context) {}
772 } // namespace extensions