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"
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/common/extensions/extension_messages.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "extensions/browser/api_activity_monitor.h"
20 #include "extensions/browser/extension_prefs.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/extension_system.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_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 {
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(
59 base::Bind(&NotifyApiEventDispatched,
63 base::Passed(&args)));
67 // Notify the ApiActivityMonitor about the event dispatch.
68 BrowserContext* context = static_cast<BrowserContext*>(browser_context_id);
69 if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
71 ApiActivityMonitor* monitor =
72 ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context);
74 monitor->OnApiEventDispatched(extension_id, event_name, args.Pass());
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)
92 if (process == that.process && extension_id < that.extension_id)
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,
109 make_scoped_ptr(event_args->DeepCopy()));
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(
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());
131 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
132 size_t slash_sep = full_event_name.find('/');
133 return full_event_name.substr(0, slash_sep);
137 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
138 void* browser_context_id,
139 const std::string& extension_id,
140 const std::string& event_name,
141 scoped_ptr<ListValue> event_args,
142 UserGestureState user_gesture,
143 const EventFilteringInfo& info) {
144 DispatchExtensionMessage(ipc_sender,
152 BrowserThread::PostTask(
155 base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
160 EventRouter::EventRouter(BrowserContext* browser_context,
161 ExtensionPrefs* extension_prefs)
162 : browser_context_(browser_context),
163 extension_prefs_(extension_prefs),
165 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
166 content::NotificationService::AllSources());
167 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
168 content::NotificationService::AllSources());
169 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED,
170 content::Source<BrowserContext>(browser_context_));
171 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
172 content::Source<BrowserContext>(browser_context_));
173 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
174 content::Source<BrowserContext>(browser_context_));
177 EventRouter::~EventRouter() {}
179 void EventRouter::AddEventListener(const std::string& event_name,
180 content::RenderProcessHost* process,
181 const std::string& extension_id) {
182 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
183 event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
186 void EventRouter::RemoveEventListener(const std::string& event_name,
187 content::RenderProcessHost* process,
188 const std::string& extension_id) {
189 EventListener listener(event_name, extension_id, process,
190 scoped_ptr<DictionaryValue>());
191 listeners_.RemoveListener(&listener);
194 void EventRouter::RegisterObserver(Observer* observer,
195 const std::string& event_name) {
196 // Observing sub-event names like "foo.onBar/123" is not allowed.
197 DCHECK(event_name.find('/') == std::string::npos);
198 observers_[event_name] = observer;
201 void EventRouter::UnregisterObserver(Observer* observer) {
202 std::vector<ObserverMap::iterator> iters_to_remove;
203 for (ObserverMap::iterator iter = observers_.begin();
204 iter != observers_.end(); ++iter) {
205 if (iter->second == observer)
206 iters_to_remove.push_back(iter);
208 for (size_t i = 0; i < iters_to_remove.size(); ++i)
209 observers_.erase(iters_to_remove[i]);
212 void EventRouter::OnListenerAdded(const EventListener* listener) {
213 const EventListenerInfo details(
214 listener->event_name,
215 listener->extension_id,
216 listener->process ? listener->process->GetBrowserContext() : NULL);
217 std::string base_event_name = GetBaseEventName(listener->event_name);
218 ObserverMap::iterator observer = observers_.find(base_event_name);
219 if (observer != observers_.end())
220 observer->second->OnListenerAdded(details);
223 void EventRouter::OnListenerRemoved(const EventListener* listener) {
224 const EventListenerInfo details(
225 listener->event_name,
226 listener->extension_id,
227 listener->process ? listener->process->GetBrowserContext() : NULL);
228 std::string base_event_name = GetBaseEventName(listener->event_name);
229 ObserverMap::iterator observer = observers_.find(base_event_name);
230 if (observer != observers_.end())
231 observer->second->OnListenerRemoved(details);
234 void EventRouter::AddLazyEventListener(const std::string& event_name,
235 const std::string& extension_id) {
236 scoped_ptr<EventListener> listener(new EventListener(
237 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
238 bool is_new = listeners_.AddListener(listener.Pass());
241 std::set<std::string> events = GetRegisteredEvents(extension_id);
242 bool prefs_is_new = events.insert(event_name).second;
244 SetRegisteredEvents(extension_id, events);
248 void EventRouter::RemoveLazyEventListener(const std::string& event_name,
249 const std::string& extension_id) {
250 EventListener listener(event_name, extension_id, NULL,
251 scoped_ptr<DictionaryValue>());
252 bool did_exist = listeners_.RemoveListener(&listener);
255 std::set<std::string> events = GetRegisteredEvents(extension_id);
256 bool prefs_did_exist = events.erase(event_name) > 0;
257 DCHECK(prefs_did_exist);
258 SetRegisteredEvents(extension_id, events);
262 void EventRouter::AddFilteredEventListener(const std::string& event_name,
263 content::RenderProcessHost* process,
264 const std::string& extension_id,
265 const base::DictionaryValue& filter,
266 bool add_lazy_listener) {
267 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
268 event_name, extension_id, process,
269 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
271 if (add_lazy_listener) {
272 bool added = listeners_.AddListener(scoped_ptr<EventListener>(
273 new EventListener(event_name, extension_id, NULL,
274 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
277 AddFilterToEvent(event_name, extension_id, &filter);
281 void EventRouter::RemoveFilteredEventListener(
282 const std::string& event_name,
283 content::RenderProcessHost* process,
284 const std::string& extension_id,
285 const base::DictionaryValue& filter,
286 bool remove_lazy_listener) {
287 EventListener listener(event_name, extension_id, process,
288 scoped_ptr<DictionaryValue>(filter.DeepCopy()));
290 listeners_.RemoveListener(&listener);
292 if (remove_lazy_listener) {
293 listener.process = NULL;
294 bool removed = listeners_.RemoveListener(&listener);
297 RemoveFilterFromEvent(event_name, extension_id, &filter);
301 bool EventRouter::HasEventListener(const std::string& event_name) {
302 return listeners_.HasListenerForEvent(event_name);
305 bool EventRouter::ExtensionHasEventListener(const std::string& extension_id,
306 const std::string& event_name) {
307 return listeners_.HasListenerForExtension(extension_id, event_name);
310 bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map,
311 const std::string& extension_id,
312 const std::string& event_name) {
313 ListenerMap::const_iterator it = listener_map.find(event_name);
314 if (it == listener_map.end())
317 const std::set<ListenerProcess>& listeners = it->second;
318 if (extension_id.empty())
319 return !listeners.empty();
321 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
322 listener != listeners.end(); ++listener) {
323 if (listener->extension_id == extension_id)
329 std::set<std::string> EventRouter::GetRegisteredEvents(
330 const std::string& extension_id) {
331 std::set<std::string> events;
332 const ListValue* events_value = NULL;
334 if (!extension_prefs_ ||
335 !extension_prefs_->ReadPrefAsList(
336 extension_id, kRegisteredEvents, &events_value)) {
340 for (size_t i = 0; i < events_value->GetSize(); ++i) {
342 if (events_value->GetString(i, &event))
343 events.insert(event);
348 void EventRouter::SetRegisteredEvents(const std::string& extension_id,
349 const std::set<std::string>& events) {
350 ListValue* events_value = new ListValue;
351 for (std::set<std::string>::const_iterator iter = events.begin();
352 iter != events.end(); ++iter) {
353 events_value->Append(new base::StringValue(*iter));
355 extension_prefs_->UpdateExtensionPref(
356 extension_id, kRegisteredEvents, events_value);
359 void EventRouter::AddFilterToEvent(const std::string& event_name,
360 const std::string& extension_id,
361 const DictionaryValue* filter) {
362 ExtensionPrefs::ScopedDictionaryUpdate update(
363 extension_prefs_, extension_id, kFilteredEvents);
364 DictionaryValue* filtered_events = update.Get();
365 if (!filtered_events)
366 filtered_events = update.Create();
368 ListValue* filter_list = NULL;
369 if (!filtered_events->GetList(event_name, &filter_list)) {
370 filter_list = new ListValue;
371 filtered_events->SetWithoutPathExpansion(event_name, filter_list);
374 filter_list->Append(filter->DeepCopy());
377 void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
378 const std::string& extension_id,
379 const DictionaryValue* filter) {
380 ExtensionPrefs::ScopedDictionaryUpdate update(
381 extension_prefs_, extension_id, kFilteredEvents);
382 DictionaryValue* filtered_events = update.Get();
383 ListValue* filter_list = NULL;
384 if (!filtered_events ||
385 !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
389 for (size_t i = 0; i < filter_list->GetSize(); i++) {
390 DictionaryValue* filter = NULL;
391 CHECK(filter_list->GetDictionary(i, &filter));
392 if (filter->Equals(filter)) {
393 filter_list->Remove(i, NULL);
399 const DictionaryValue* EventRouter::GetFilteredEvents(
400 const std::string& extension_id) {
401 const DictionaryValue* events = NULL;
402 extension_prefs_->ReadPrefAsDictionary(
403 extension_id, kFilteredEvents, &events);
407 void EventRouter::BroadcastEvent(scoped_ptr<Event> event) {
408 DispatchEventImpl(std::string(), linked_ptr<Event>(event.release()));
411 void EventRouter::DispatchEventToExtension(const std::string& extension_id,
412 scoped_ptr<Event> event) {
413 DCHECK(!extension_id.empty());
414 DispatchEventImpl(extension_id, linked_ptr<Event>(event.release()));
417 void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
418 scoped_ptr<Event> event) {
419 DCHECK(!extension_id.empty());
420 std::string event_name = event->event_name;
421 bool has_listener = ExtensionHasEventListener(extension_id, event_name);
423 AddLazyEventListener(event_name, extension_id);
424 DispatchEventToExtension(extension_id, event.Pass());
426 RemoveLazyEventListener(event_name, extension_id);
429 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
430 const linked_ptr<Event>& event) {
431 // We don't expect to get events from a completely different browser context.
432 DCHECK(!event->restrict_to_browser_context ||
433 ExtensionsBrowserClient::Get()->IsSameContext(
434 browser_context_, event->restrict_to_browser_context));
436 std::set<const EventListener*> listeners(
437 listeners_.GetEventListeners(*event));
439 std::set<EventDispatchIdentifier> already_dispatched;
441 // We dispatch events for lazy background pages first because attempting to do
442 // so will cause those that are being suspended to cancel that suspension.
443 // As canceling a suspension entails sending an event to the affected
444 // background page, and as that event needs to be delivered before we dispatch
445 // the event we are dispatching here, we dispatch to the lazy listeners here
447 for (std::set<const EventListener*>::iterator it = listeners.begin();
448 it != listeners.end(); it++) {
449 const EventListener* listener = *it;
450 if (restrict_to_extension_id.empty() ||
451 restrict_to_extension_id == listener->extension_id) {
452 if (!listener->process) {
453 DispatchLazyEvent(listener->extension_id, event, &already_dispatched);
458 for (std::set<const EventListener*>::iterator it = listeners.begin();
459 it != listeners.end(); it++) {
460 const EventListener* listener = *it;
461 if (restrict_to_extension_id.empty() ||
462 restrict_to_extension_id == listener->extension_id) {
463 if (listener->process) {
464 EventDispatchIdentifier dispatch_id(
465 listener->process->GetBrowserContext(), listener->extension_id);
466 if (!ContainsKey(already_dispatched, dispatch_id)) {
467 DispatchEventToProcess(listener->extension_id, listener->process,
475 void EventRouter::DispatchLazyEvent(
476 const std::string& extension_id,
477 const linked_ptr<Event>& event,
478 std::set<EventDispatchIdentifier>* already_dispatched) {
479 // Check both the original and the incognito browser context to see if we
480 // should load a lazy bg page to handle the event. The latter case
481 // occurs in the case of split-mode extensions.
482 const Extension* extension =
483 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
488 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
489 browser_context_, extension, event)) {
490 already_dispatched->insert(std::make_pair(browser_context_, extension_id));
493 ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
494 if (browser_client->HasOffTheRecordContext(browser_context_) &&
495 IncognitoInfo::IsSplitMode(extension)) {
496 BrowserContext* incognito_context =
497 browser_client->GetOffTheRecordContext(browser_context_);
498 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
499 incognito_context, extension, event)) {
500 already_dispatched->insert(
501 std::make_pair(incognito_context, extension_id));
506 void EventRouter::DispatchEventToProcess(const std::string& extension_id,
507 content::RenderProcessHost* process,
508 const linked_ptr<Event>& event) {
509 const Extension* extension =
510 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
513 // The extension could have been removed, but we do not unregister it until
514 // the extension process is unloaded.
518 BrowserContext* listener_context = process->GetBrowserContext();
519 ProcessMap* process_map = ProcessMap::Get(listener_context);
520 // If the event is privileged, only send to extension processes. Otherwise,
521 // it's OK to send to normal renderers (e.g., for content scripts).
522 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
523 !process_map->Contains(extension->id(), process->GetID())) {
527 // If the event is restricted to a URL, only dispatch if the extension has
528 // permission for it (or if the event originated from itself).
529 if (!event->event_url.is_empty() &&
530 event->event_url.host() != extension->id() &&
531 !extension->GetActivePermissions()->HasEffectiveAccessToURL(
536 if (!CanDispatchEventToBrowserContext(listener_context, extension, event))
539 if (!event->will_dispatch_callback.is_null()) {
540 event->will_dispatch_callback.Run(listener_context, extension,
541 event->event_args.get());
544 DispatchExtensionMessage(process, listener_context, extension->id(),
545 event->event_name, event->event_args.get(),
546 event->user_gesture, event->filter_info);
547 IncrementInFlightEvents(listener_context, extension);
550 bool EventRouter::CanDispatchEventToBrowserContext(
551 BrowserContext* context,
552 const Extension* extension,
553 const linked_ptr<Event>& event) {
554 // Is this event from a different browser context than the renderer (ie, an
555 // incognito tab event sent to a normal process, or vice versa).
556 bool cross_incognito = event->restrict_to_browser_context &&
557 context != event->restrict_to_browser_context;
558 if (!cross_incognito)
560 return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
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
571 ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
572 if (!pm->GetBackgroundHostForExtension(extension->id()))
576 if (!CanDispatchEventToBrowserContext(context, extension, event))
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));
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))
613 ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context);
614 EventRouter* event_router = extension_system->event_router();
617 const Extension* extension =
618 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
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());
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
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) {
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) {
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);
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));
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(),
696 const DictionaryValue* filtered_events =
697 GetFilteredEvents(extension->id());
699 listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
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());
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());
754 Event* Event::DeepCopy() {
755 Event* copy = new Event(event_name,
756 scoped_ptr<base::ListValue>(event_args->DeepCopy()),
757 restrict_to_browser_context,
761 copy->will_dispatch_callback = will_dispatch_callback;
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