Remove Net.URLRequest_SetReferrer_IsEmptyOrValid histogram.
[chromium-blink-merge.git] / extensions / browser / event_router.cc
blob3c6679fb997e45e2f4412eea8d9b84d8dcf3c63c
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/extension_util.h"
23 #include "extensions/browser/extensions_browser_client.h"
24 #include "extensions/browser/lazy_background_task_queue.h"
25 #include "extensions/browser/process_manager.h"
26 #include "extensions/browser/process_map.h"
27 #include "extensions/common/extension.h"
28 #include "extensions/common/extension_api.h"
29 #include "extensions/common/extension_messages.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"
33 #include "extensions/common/permissions/permissions_data.h"
35 using base::DictionaryValue;
36 using base::ListValue;
37 using content::BrowserContext;
38 using content::BrowserThread;
40 namespace extensions {
42 namespace {
44 void DoNothing(ExtensionHost* host) {}
46 // A dictionary of event names to lists of filters that this extension has
47 // registered from its lazy background page.
48 const char kFilteredEvents[] = "filtered_events";
50 // Sends a notification about an event to the API activity monitor on the
51 // UI thread. Can be called from any thread.
52 void NotifyApiEventDispatched(void* browser_context_id,
53 const std::string& extension_id,
54 const std::string& event_name,
55 scoped_ptr<ListValue> args) {
56 // The ApiActivityMonitor can only be accessed from the UI thread.
57 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
58 BrowserThread::PostTask(
59 BrowserThread::UI,
60 FROM_HERE,
61 base::Bind(&NotifyApiEventDispatched,
62 browser_context_id,
63 extension_id,
64 event_name,
65 base::Passed(&args)));
66 return;
69 // Notify the ApiActivityMonitor about the event dispatch.
70 BrowserContext* context = static_cast<BrowserContext*>(browser_context_id);
71 if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
72 return;
73 ApiActivityMonitor* monitor =
74 ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context);
75 if (monitor)
76 monitor->OnApiEventDispatched(extension_id, event_name, args.Pass());
79 } // namespace
81 const char EventRouter::kRegisteredEvents[] = "events";
83 struct EventRouter::ListenerProcess {
84 content::RenderProcessHost* process;
85 std::string extension_id;
87 ListenerProcess(content::RenderProcessHost* process,
88 const std::string& extension_id)
89 : process(process), extension_id(extension_id) {}
91 bool operator<(const ListenerProcess& that) const {
92 if (process < that.process)
93 return true;
94 if (process == that.process && extension_id < that.extension_id)
95 return true;
96 return false;
100 // static
101 void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
102 void* browser_context_id,
103 const std::string& extension_id,
104 const std::string& event_name,
105 ListValue* event_args,
106 UserGestureState user_gesture,
107 const EventFilteringInfo& info) {
108 NotifyApiEventDispatched(browser_context_id,
109 extension_id,
110 event_name,
111 make_scoped_ptr(event_args->DeepCopy()));
113 ListValue args;
114 args.Set(0, new base::StringValue(event_name));
115 args.Set(1, event_args);
116 args.Set(2, info.AsValue().release());
117 ipc_sender->Send(new ExtensionMsg_MessageInvoke(
118 MSG_ROUTING_CONTROL,
119 extension_id,
120 kEventBindings,
121 "dispatchEvent",
122 args,
123 user_gesture == USER_GESTURE_ENABLED));
125 // DispatchExtensionMessage does _not_ take ownership of event_args, so we
126 // must ensure that the destruction of args does not attempt to free it.
127 scoped_ptr<base::Value> removed_event_args;
128 args.Remove(1, &removed_event_args);
129 ignore_result(removed_event_args.release());
132 // static
133 EventRouter* EventRouter::Get(content::BrowserContext* browser_context) {
134 return ExtensionSystem::Get(browser_context)->event_router();
137 // static
138 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
139 size_t slash_sep = full_event_name.find('/');
140 return full_event_name.substr(0, slash_sep);
143 // static
144 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
145 void* browser_context_id,
146 const std::string& extension_id,
147 const std::string& event_name,
148 scoped_ptr<ListValue> event_args,
149 UserGestureState user_gesture,
150 const EventFilteringInfo& info) {
151 DispatchExtensionMessage(ipc_sender,
152 browser_context_id,
153 extension_id,
154 event_name,
155 event_args.get(),
156 user_gesture,
157 info);
159 BrowserThread::PostTask(
160 BrowserThread::UI,
161 FROM_HERE,
162 base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
163 browser_context_id,
164 extension_id));
167 EventRouter::EventRouter(BrowserContext* browser_context,
168 ExtensionPrefs* extension_prefs)
169 : browser_context_(browser_context),
170 extension_prefs_(extension_prefs),
171 listeners_(this) {
172 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
173 content::NotificationService::AllSources());
174 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
175 content::NotificationService::AllSources());
176 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
177 content::Source<BrowserContext>(browser_context_));
178 registrar_.Add(this,
179 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
180 content::Source<BrowserContext>(browser_context_));
181 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
182 content::Source<BrowserContext>(browser_context_));
185 EventRouter::~EventRouter() {}
187 void EventRouter::AddEventListener(const std::string& event_name,
188 content::RenderProcessHost* process,
189 const std::string& extension_id) {
190 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
191 event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
194 void EventRouter::RemoveEventListener(const std::string& event_name,
195 content::RenderProcessHost* process,
196 const std::string& extension_id) {
197 EventListener listener(event_name, extension_id, process,
198 scoped_ptr<DictionaryValue>());
199 listeners_.RemoveListener(&listener);
202 void EventRouter::RegisterObserver(Observer* observer,
203 const std::string& event_name) {
204 // Observing sub-event names like "foo.onBar/123" is not allowed.
205 DCHECK(event_name.find('/') == std::string::npos);
206 observers_[event_name] = observer;
209 void EventRouter::UnregisterObserver(Observer* observer) {
210 std::vector<ObserverMap::iterator> iters_to_remove;
211 for (ObserverMap::iterator iter = observers_.begin();
212 iter != observers_.end(); ++iter) {
213 if (iter->second == observer)
214 iters_to_remove.push_back(iter);
216 for (size_t i = 0; i < iters_to_remove.size(); ++i)
217 observers_.erase(iters_to_remove[i]);
220 void EventRouter::OnListenerAdded(const EventListener* listener) {
221 const EventListenerInfo details(listener->event_name(),
222 listener->extension_id(),
223 listener->GetBrowserContext());
224 std::string base_event_name = GetBaseEventName(listener->event_name());
225 ObserverMap::iterator observer = observers_.find(base_event_name);
226 if (observer != observers_.end())
227 observer->second->OnListenerAdded(details);
230 void EventRouter::OnListenerRemoved(const EventListener* listener) {
231 const EventListenerInfo details(listener->event_name(),
232 listener->extension_id(),
233 listener->GetBrowserContext());
234 std::string base_event_name = GetBaseEventName(listener->event_name());
235 ObserverMap::iterator observer = observers_.find(base_event_name);
236 if (observer != observers_.end())
237 observer->second->OnListenerRemoved(details);
240 void EventRouter::AddLazyEventListener(const std::string& event_name,
241 const std::string& extension_id) {
242 scoped_ptr<EventListener> listener(new EventListener(
243 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
244 bool is_new = listeners_.AddListener(listener.Pass());
246 if (is_new) {
247 std::set<std::string> events = GetRegisteredEvents(extension_id);
248 bool prefs_is_new = events.insert(event_name).second;
249 if (prefs_is_new)
250 SetRegisteredEvents(extension_id, events);
254 void EventRouter::RemoveLazyEventListener(const std::string& event_name,
255 const std::string& extension_id) {
256 EventListener listener(event_name, extension_id, NULL,
257 scoped_ptr<DictionaryValue>());
258 bool did_exist = listeners_.RemoveListener(&listener);
260 if (did_exist) {
261 std::set<std::string> events = GetRegisteredEvents(extension_id);
262 bool prefs_did_exist = events.erase(event_name) > 0;
263 DCHECK(prefs_did_exist);
264 SetRegisteredEvents(extension_id, events);
268 void EventRouter::AddFilteredEventListener(const std::string& event_name,
269 content::RenderProcessHost* process,
270 const std::string& extension_id,
271 const base::DictionaryValue& filter,
272 bool add_lazy_listener) {
273 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
274 event_name, extension_id, process,
275 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
277 if (add_lazy_listener) {
278 bool added = listeners_.AddListener(scoped_ptr<EventListener>(
279 new EventListener(event_name, extension_id, NULL,
280 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
282 if (added)
283 AddFilterToEvent(event_name, extension_id, &filter);
287 void EventRouter::RemoveFilteredEventListener(
288 const std::string& event_name,
289 content::RenderProcessHost* process,
290 const std::string& extension_id,
291 const base::DictionaryValue& filter,
292 bool remove_lazy_listener) {
293 EventListener listener(event_name, extension_id, process,
294 scoped_ptr<DictionaryValue>(filter.DeepCopy()));
296 listeners_.RemoveListener(&listener);
298 if (remove_lazy_listener) {
299 listener.MakeLazy();
300 bool removed = listeners_.RemoveListener(&listener);
302 if (removed)
303 RemoveFilterFromEvent(event_name, extension_id, &filter);
307 bool EventRouter::HasEventListener(const std::string& event_name) {
308 return listeners_.HasListenerForEvent(event_name);
311 bool EventRouter::ExtensionHasEventListener(const std::string& extension_id,
312 const std::string& event_name) {
313 return listeners_.HasListenerForExtension(extension_id, event_name);
316 bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map,
317 const std::string& extension_id,
318 const std::string& event_name) {
319 ListenerMap::const_iterator it = listener_map.find(event_name);
320 if (it == listener_map.end())
321 return false;
323 const std::set<ListenerProcess>& listeners = it->second;
324 if (extension_id.empty())
325 return !listeners.empty();
327 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
328 listener != listeners.end(); ++listener) {
329 if (listener->extension_id == extension_id)
330 return true;
332 return false;
335 std::set<std::string> EventRouter::GetRegisteredEvents(
336 const std::string& extension_id) {
337 std::set<std::string> events;
338 const ListValue* events_value = NULL;
340 if (!extension_prefs_ ||
341 !extension_prefs_->ReadPrefAsList(
342 extension_id, kRegisteredEvents, &events_value)) {
343 return events;
346 for (size_t i = 0; i < events_value->GetSize(); ++i) {
347 std::string event;
348 if (events_value->GetString(i, &event))
349 events.insert(event);
351 return events;
354 void EventRouter::SetRegisteredEvents(const std::string& extension_id,
355 const std::set<std::string>& events) {
356 ListValue* events_value = new ListValue;
357 for (std::set<std::string>::const_iterator iter = events.begin();
358 iter != events.end(); ++iter) {
359 events_value->Append(new base::StringValue(*iter));
361 extension_prefs_->UpdateExtensionPref(
362 extension_id, kRegisteredEvents, events_value);
365 void EventRouter::AddFilterToEvent(const std::string& event_name,
366 const std::string& extension_id,
367 const DictionaryValue* filter) {
368 ExtensionPrefs::ScopedDictionaryUpdate update(
369 extension_prefs_, extension_id, kFilteredEvents);
370 DictionaryValue* filtered_events = update.Get();
371 if (!filtered_events)
372 filtered_events = update.Create();
374 ListValue* filter_list = NULL;
375 if (!filtered_events->GetList(event_name, &filter_list)) {
376 filter_list = new ListValue;
377 filtered_events->SetWithoutPathExpansion(event_name, filter_list);
380 filter_list->Append(filter->DeepCopy());
383 void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
384 const std::string& extension_id,
385 const DictionaryValue* filter) {
386 ExtensionPrefs::ScopedDictionaryUpdate update(
387 extension_prefs_, extension_id, kFilteredEvents);
388 DictionaryValue* filtered_events = update.Get();
389 ListValue* filter_list = NULL;
390 if (!filtered_events ||
391 !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
392 return;
395 for (size_t i = 0; i < filter_list->GetSize(); i++) {
396 DictionaryValue* filter = NULL;
397 CHECK(filter_list->GetDictionary(i, &filter));
398 if (filter->Equals(filter)) {
399 filter_list->Remove(i, NULL);
400 break;
405 const DictionaryValue* EventRouter::GetFilteredEvents(
406 const std::string& extension_id) {
407 const DictionaryValue* events = NULL;
408 extension_prefs_->ReadPrefAsDictionary(
409 extension_id, kFilteredEvents, &events);
410 return events;
413 void EventRouter::BroadcastEvent(scoped_ptr<Event> event) {
414 DispatchEventImpl(std::string(), linked_ptr<Event>(event.release()));
417 void EventRouter::DispatchEventToExtension(const std::string& extension_id,
418 scoped_ptr<Event> event) {
419 DCHECK(!extension_id.empty());
420 DispatchEventImpl(extension_id, linked_ptr<Event>(event.release()));
423 void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
424 scoped_ptr<Event> event) {
425 DCHECK(!extension_id.empty());
426 std::string event_name = event->event_name;
427 bool has_listener = ExtensionHasEventListener(extension_id, event_name);
428 if (!has_listener)
429 AddLazyEventListener(event_name, extension_id);
430 DispatchEventToExtension(extension_id, event.Pass());
431 if (!has_listener)
432 RemoveLazyEventListener(event_name, extension_id);
435 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
436 const linked_ptr<Event>& event) {
437 // We don't expect to get events from a completely different browser context.
438 DCHECK(!event->restrict_to_browser_context ||
439 ExtensionsBrowserClient::Get()->IsSameContext(
440 browser_context_, event->restrict_to_browser_context));
442 std::set<const EventListener*> listeners(
443 listeners_.GetEventListeners(*event));
445 std::set<EventDispatchIdentifier> already_dispatched;
447 // We dispatch events for lazy background pages first because attempting to do
448 // so will cause those that are being suspended to cancel that suspension.
449 // As canceling a suspension entails sending an event to the affected
450 // background page, and as that event needs to be delivered before we dispatch
451 // the event we are dispatching here, we dispatch to the lazy listeners here
452 // first.
453 for (std::set<const EventListener*>::iterator it = listeners.begin();
454 it != listeners.end(); it++) {
455 const EventListener* listener = *it;
456 if (restrict_to_extension_id.empty() ||
457 restrict_to_extension_id == listener->extension_id()) {
458 if (listener->IsLazy()) {
459 DispatchLazyEvent(listener->extension_id(), event, &already_dispatched);
464 for (std::set<const EventListener*>::iterator it = listeners.begin();
465 it != listeners.end(); it++) {
466 const EventListener* listener = *it;
467 if (restrict_to_extension_id.empty() ||
468 restrict_to_extension_id == listener->extension_id()) {
469 if (listener->process()) {
470 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(),
471 listener->extension_id());
472 if (!ContainsKey(already_dispatched, dispatch_id)) {
473 DispatchEventToProcess(
474 listener->extension_id(), listener->process(), event);
481 void EventRouter::DispatchLazyEvent(
482 const std::string& extension_id,
483 const linked_ptr<Event>& event,
484 std::set<EventDispatchIdentifier>* already_dispatched) {
485 // Check both the original and the incognito browser context to see if we
486 // should load a lazy bg page to handle the event. The latter case
487 // occurs in the case of split-mode extensions.
488 const Extension* extension =
489 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
490 extension_id);
491 if (!extension)
492 return;
494 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
495 browser_context_, extension, event)) {
496 already_dispatched->insert(std::make_pair(browser_context_, extension_id));
499 ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
500 if (browser_client->HasOffTheRecordContext(browser_context_) &&
501 IncognitoInfo::IsSplitMode(extension)) {
502 BrowserContext* incognito_context =
503 browser_client->GetOffTheRecordContext(browser_context_);
504 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
505 incognito_context, extension, event)) {
506 already_dispatched->insert(
507 std::make_pair(incognito_context, extension_id));
512 void EventRouter::DispatchEventToProcess(const std::string& extension_id,
513 content::RenderProcessHost* process,
514 const linked_ptr<Event>& event) {
515 const Extension* extension =
516 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
517 extension_id);
519 // The extension could have been removed, but we do not unregister it until
520 // the extension process is unloaded.
521 if (!extension)
522 return;
524 BrowserContext* listener_context = process->GetBrowserContext();
525 ProcessMap* process_map = ProcessMap::Get(listener_context);
526 // If the event is privileged, only send to extension processes. Otherwise,
527 // it's OK to send to normal renderers (e.g., for content scripts).
528 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
529 !process_map->Contains(extension->id(), process->GetID())) {
530 return;
533 // If the event is restricted to a URL, only dispatch if the extension has
534 // permission for it (or if the event originated from itself).
535 if (!event->event_url.is_empty() &&
536 event->event_url.host() != extension->id() &&
537 !extension->permissions_data()
538 ->active_permissions()
539 ->HasEffectiveAccessToURL(event->event_url)) {
540 return;
543 if (!CanDispatchEventToBrowserContext(listener_context, extension, event))
544 return;
546 if (!event->will_dispatch_callback.is_null()) {
547 event->will_dispatch_callback.Run(listener_context, extension,
548 event->event_args.get());
551 DispatchExtensionMessage(process, listener_context, extension->id(),
552 event->event_name, event->event_args.get(),
553 event->user_gesture, event->filter_info);
554 IncrementInFlightEvents(listener_context, extension);
557 bool EventRouter::CanDispatchEventToBrowserContext(
558 BrowserContext* context,
559 const Extension* extension,
560 const linked_ptr<Event>& event) {
561 // Is this event from a different browser context than the renderer (ie, an
562 // incognito tab event sent to a normal process, or vice versa).
563 bool cross_incognito = event->restrict_to_browser_context &&
564 context != event->restrict_to_browser_context;
565 if (!cross_incognito)
566 return true;
567 return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
568 extension, context);
571 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
572 BrowserContext* context,
573 const Extension* extension,
574 const linked_ptr<Event>& event) {
575 if (util::IsEphemeralApp(extension->id(), context) &&
576 !event->can_load_ephemeral_apps) {
577 // Most events can only be dispatched to ephemeral apps that are already
578 // running.
579 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
580 if (!pm->GetBackgroundHostForExtension(extension->id()))
581 return false;
584 if (!CanDispatchEventToBrowserContext(context, extension, event))
585 return false;
587 LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
588 context)->lazy_background_task_queue();
589 if (queue->ShouldEnqueueTask(context, extension)) {
590 linked_ptr<Event> dispatched_event(event);
592 // If there's a dispatch callback, call it now (rather than dispatch time)
593 // to avoid lifetime issues. Use a separate copy of the event args, so they
594 // last until the event is dispatched.
595 if (!event->will_dispatch_callback.is_null()) {
596 dispatched_event.reset(event->DeepCopy());
597 dispatched_event->will_dispatch_callback.Run(
598 context, extension, dispatched_event->event_args.get());
599 // Ensure we don't call it again at dispatch time.
600 dispatched_event->will_dispatch_callback.Reset();
603 queue->AddPendingTask(context, extension->id(),
604 base::Bind(&EventRouter::DispatchPendingEvent,
605 base::Unretained(this), dispatched_event));
606 return true;
609 return false;
612 // static
613 void EventRouter::IncrementInFlightEventsOnUI(
614 void* browser_context_id,
615 const std::string& extension_id) {
616 DCHECK_CURRENTLY_ON(BrowserThread::UI);
617 BrowserContext* browser_context =
618 reinterpret_cast<BrowserContext*>(browser_context_id);
619 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
620 return;
621 EventRouter* event_router = EventRouter::Get(browser_context);
622 if (!event_router)
623 return;
624 const Extension* extension =
625 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
626 extension_id);
627 if (!extension)
628 return;
629 event_router->IncrementInFlightEvents(browser_context, extension);
632 void EventRouter::IncrementInFlightEvents(BrowserContext* context,
633 const Extension* extension) {
634 // Only increment in-flight events if the lazy background page is active,
635 // because that's the only time we'll get an ACK.
636 if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
637 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
638 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
639 if (host)
640 pm->IncrementLazyKeepaliveCount(extension);
644 void EventRouter::OnEventAck(BrowserContext* context,
645 const std::string& extension_id) {
646 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
647 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
648 // The event ACK is routed to the background host, so this should never be
649 // NULL.
650 CHECK(host);
651 // TODO(mpcomplete): We should never get this message unless
652 // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
653 if (host->extension() &&
654 BackgroundInfo::HasLazyBackgroundPage(host->extension()))
655 pm->DecrementLazyKeepaliveCount(host->extension());
658 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
659 ExtensionHost* host) {
660 if (!host)
661 return;
663 if (listeners_.HasProcessListener(host->render_process_host(),
664 host->extension()->id())) {
665 DispatchEventToProcess(host->extension()->id(),
666 host->render_process_host(), event);
670 void EventRouter::Observe(int type,
671 const content::NotificationSource& source,
672 const content::NotificationDetails& details) {
673 switch (type) {
674 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
675 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
676 content::RenderProcessHost* renderer =
677 content::Source<content::RenderProcessHost>(source).ptr();
678 // Remove all event listeners associated with this renderer.
679 listeners_.RemoveListenersForProcess(renderer);
680 break;
682 case chrome::NOTIFICATION_EXTENSION_ENABLED: {
683 // If the extension has a lazy background page, make sure it gets loaded
684 // to register the events the extension is interested in.
685 const Extension* extension =
686 content::Details<const Extension>(details).ptr();
687 if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
688 LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
689 browser_context_)->lazy_background_task_queue();
690 queue->AddPendingTask(browser_context_, extension->id(),
691 base::Bind(&DoNothing));
693 break;
695 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
696 // Add all registered lazy listeners to our cache.
697 const Extension* extension =
698 content::Details<const Extension>(details).ptr();
699 std::set<std::string> registered_events =
700 GetRegisteredEvents(extension->id());
701 listeners_.LoadUnfilteredLazyListeners(extension->id(),
702 registered_events);
703 const DictionaryValue* filtered_events =
704 GetFilteredEvents(extension->id());
705 if (filtered_events)
706 listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
707 break;
709 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
710 // Remove all registered lazy listeners from our cache.
711 UnloadedExtensionInfo* unloaded =
712 content::Details<UnloadedExtensionInfo>(details).ptr();
713 listeners_.RemoveLazyListenersForExtension(unloaded->extension->id());
714 break;
716 default:
717 NOTREACHED();
718 return;
722 Event::Event(const std::string& event_name,
723 scoped_ptr<base::ListValue> event_args)
724 : event_name(event_name),
725 event_args(event_args.Pass()),
726 restrict_to_browser_context(NULL),
727 user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
728 can_load_ephemeral_apps(false) {
729 DCHECK(this->event_args.get());
732 Event::Event(const std::string& event_name,
733 scoped_ptr<base::ListValue> event_args,
734 BrowserContext* restrict_to_browser_context)
735 : event_name(event_name),
736 event_args(event_args.Pass()),
737 restrict_to_browser_context(restrict_to_browser_context),
738 user_gesture(EventRouter::USER_GESTURE_UNKNOWN),
739 can_load_ephemeral_apps(false) {
740 DCHECK(this->event_args.get());
743 Event::Event(const std::string& event_name,
744 scoped_ptr<ListValue> event_args,
745 BrowserContext* restrict_to_browser_context,
746 const GURL& event_url,
747 EventRouter::UserGestureState user_gesture,
748 const EventFilteringInfo& filter_info)
749 : event_name(event_name),
750 event_args(event_args.Pass()),
751 restrict_to_browser_context(restrict_to_browser_context),
752 event_url(event_url),
753 user_gesture(user_gesture),
754 filter_info(filter_info),
755 can_load_ephemeral_apps(false) {
756 DCHECK(this->event_args.get());
759 Event::~Event() {}
761 Event* Event::DeepCopy() {
762 Event* copy = new Event(event_name,
763 scoped_ptr<base::ListValue>(event_args->DeepCopy()),
764 restrict_to_browser_context,
765 event_url,
766 user_gesture,
767 filter_info);
768 copy->will_dispatch_callback = will_dispatch_callback;
769 return copy;
772 EventListenerInfo::EventListenerInfo(const std::string& event_name,
773 const std::string& extension_id,
774 content::BrowserContext* browser_context)
775 : event_name(event_name),
776 extension_id(extension_id),
777 browser_context(browser_context) {}
779 } // namespace extensions