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 "chrome/browser/extensions/event_router.h"
10 #include "base/command_line.h"
11 #include "base/message_loop.h"
12 #include "base/stl_util.h"
13 #include "base/values.h"
14 #include "base/version.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/extensions/activity_log.h"
17 #include "chrome/browser/extensions/api/runtime/runtime_api.h"
18 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
19 #include "chrome/browser/extensions/event_names.h"
20 #include "chrome/browser/extensions/extension_host.h"
21 #include "chrome/browser/extensions/extension_prefs.h"
22 #include "chrome/browser/extensions/extension_process_manager.h"
23 #include "chrome/browser/extensions/extension_service.h"
24 #include "chrome/browser/extensions/extension_system.h"
25 #include "chrome/browser/extensions/lazy_background_task_queue.h"
26 #include "chrome/browser/extensions/process_map.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/common/chrome_notification_types.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/extensions/api/extension_api.h"
32 #include "chrome/common/extensions/background_info.h"
33 #include "chrome/common/extensions/extension.h"
34 #include "chrome/common/extensions/extension_messages.h"
35 #include "chrome/common/extensions/incognito_handler.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/render_process_host.h"
40 using content::BrowserThread
;
42 namespace extensions
{
46 const char kDispatchEvent
[] = "Event.dispatchEvent";
48 void NotifyEventListenerRemovedOnIOThread(
50 const std::string
& extension_id
,
51 const std::string
& sub_event_name
) {
52 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
53 profile
, extension_id
, sub_event_name
);
56 void DispatchOnInstalledEvent(
58 const std::string
& extension_id
,
59 const Version
& old_version
,
60 bool chrome_updated
) {
61 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
64 RuntimeEventRouter::DispatchOnInstalledEvent(profile
, extension_id
,
65 old_version
, chrome_updated
);
68 void DoNothing(ExtensionHost
* host
) {}
72 struct EventRouter::ListenerProcess
{
73 content::RenderProcessHost
* process
;
74 std::string extension_id
;
76 ListenerProcess(content::RenderProcessHost
* process
,
77 const std::string
& extension_id
)
78 : process(process
), extension_id(extension_id
) {}
80 bool operator<(const ListenerProcess
& that
) const {
81 if (process
< that
.process
)
83 if (process
== that
.process
&& extension_id
< that
.extension_id
)
90 void EventRouter::LogExtensionEventMessage(void* profile_id
,
91 const std::string
& extension_id
,
92 const std::string
& event_name
,
93 scoped_ptr
<ListValue
> event_args
) {
94 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
95 BrowserThread::PostTask(BrowserThread::UI
,
97 base::Bind(&LogExtensionEventMessage
,
101 base::Passed(&event_args
)));
103 Profile
* profile
= reinterpret_cast<Profile
*>(profile_id
);
104 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
107 // An ExtensionService might not be running during unit tests, or an
108 // extension might have been unloaded by the time we get to logging it. In
109 // those cases log a warning.
110 ExtensionService
* extension_service
=
111 ExtensionSystem::Get(profile
)->extension_service();
112 if (!extension_service
) {
113 LOG(WARNING
) << "ExtensionService does not seem to be available "
114 << "(this may be normal for unit tests)";
116 const Extension
* extension
=
117 extension_service
->extensions()->GetByID(extension_id
);
119 LOG(WARNING
) << "Extension " << extension_id
<< " not found!";
121 ActivityLog::GetInstance(profile
)->LogEventAction(
122 extension
, event_name
, event_args
.get(), std::string());
129 void EventRouter::DispatchExtensionMessage(IPC::Sender
* ipc_sender
,
131 const std::string
& extension_id
,
132 const std::string
& event_name
,
133 ListValue
* event_args
,
134 const GURL
& event_url
,
135 UserGestureState user_gesture
,
136 const EventFilteringInfo
& info
) {
137 if (ActivityLog::IsLogEnabled()) {
138 LogExtensionEventMessage(profile_id
, extension_id
, event_name
,
139 scoped_ptr
<ListValue
>(event_args
->DeepCopy()));
143 args
.Set(0, Value::CreateStringValue(event_name
));
144 args
.Set(1, event_args
);
145 args
.Set(2, info
.AsValue().release());
146 ipc_sender
->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL
,
147 extension_id
, kDispatchEvent
, args
, event_url
,
148 user_gesture
== USER_GESTURE_ENABLED
));
150 // DispatchExtensionMessage does _not_ take ownership of event_args, so we
151 // must ensure that the destruction of args does not attempt to free it.
152 Value
* removed_event_args
= NULL
;
153 args
.Remove(1, &removed_event_args
);
157 void EventRouter::DispatchEvent(IPC::Sender
* ipc_sender
,
159 const std::string
& extension_id
,
160 const std::string
& event_name
,
161 scoped_ptr
<ListValue
> event_args
,
162 const GURL
& event_url
,
163 UserGestureState user_gesture
,
164 const EventFilteringInfo
& info
) {
165 DispatchExtensionMessage(ipc_sender
, profile_id
, extension_id
, event_name
,
166 event_args
.get(), event_url
, user_gesture
, info
);
169 EventRouter::EventRouter(Profile
* profile
, ExtensionPrefs
* extension_prefs
)
172 activity_log_(ActivityLog::GetInstance(profile
)),
173 dispatch_chrome_updated_event_(false) {
174 registrar_
.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED
,
175 content::NotificationService::AllSources());
176 registrar_
.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED
,
177 content::NotificationService::AllSources());
178 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY
,
179 content::Source
<Profile
>(profile_
));
180 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED
,
181 content::Source
<Profile
>(profile_
));
182 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED
,
183 content::Source
<Profile
>(profile_
));
184 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED
,
185 content::Source
<Profile
>(profile_
));
186 registrar_
.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED
,
187 content::Source
<Profile
>(profile_
));
189 // NULL in unit_tests.
190 if (extension_prefs
) {
191 // Check if registered events are up-to-date. We can only do this once
192 // per profile, since it updates internal state when called.
193 dispatch_chrome_updated_event_
=
194 !extension_prefs
->CheckRegisteredEventsUpToDate();
198 EventRouter::~EventRouter() {}
200 void EventRouter::AddEventListener(const std::string
& event_name
,
201 content::RenderProcessHost
* process
,
202 const std::string
& extension_id
) {
203 listeners_
.AddListener(scoped_ptr
<EventListener
>(new EventListener(
204 event_name
, extension_id
, process
, scoped_ptr
<DictionaryValue
>())));
207 void EventRouter::RemoveEventListener(const std::string
& event_name
,
208 content::RenderProcessHost
* process
,
209 const std::string
& extension_id
) {
210 EventListener
listener(event_name
, extension_id
, process
,
211 scoped_ptr
<DictionaryValue
>());
212 listeners_
.RemoveListener(&listener
);
215 void EventRouter::RegisterObserver(Observer
* observer
,
216 const std::string
& event_name
) {
217 observers_
[event_name
] = observer
;
220 void EventRouter::UnregisterObserver(Observer
* observer
) {
221 std::vector
<ObserverMap::iterator
> iters_to_remove
;
222 for (ObserverMap::iterator iter
= observers_
.begin();
223 iter
!= observers_
.end(); ++iter
) {
224 if (iter
->second
== observer
)
225 iters_to_remove
.push_back(iter
);
227 for (size_t i
= 0; i
< iters_to_remove
.size(); ++i
)
228 observers_
.erase(iters_to_remove
[i
]);
231 void EventRouter::OnListenerAdded(const EventListener
* listener
) {
232 const std::string
& event_name
= listener
->event_name
;
233 const EventListenerInfo
details(event_name
, listener
->extension_id
);
234 ObserverMap::iterator observer
= observers_
.find(event_name
);
235 if (observer
!= observers_
.end())
236 observer
->second
->OnListenerAdded(details
);
239 // TODO(felt): Experimentally determine if these are needed, or if they
240 // can be permanently removed. Temporarily removing for now to reduce log
241 // size while under investigation.
242 const Extension
* extension
= ExtensionSystem::Get(profile_
)->
243 extension_service()->GetExtensionById(listener
->extension_id
,
244 ExtensionService::INCLUDE_ENABLED
);
246 scoped_ptr
<ListValue
> args(new ListValue());
247 if (listener
->filter
)
248 args
->Append(listener
->filter
->DeepCopy());
249 activity_log_
->LogAPIAction(
250 extension
, event_name
+ ".addListener", args
.get(), std::string());
255 void EventRouter::OnListenerRemoved(const EventListener
* listener
) {
256 const std::string
& event_name
= listener
->event_name
;
257 const EventListenerInfo
details(event_name
, listener
->extension_id
);
258 ObserverMap::iterator observer
= observers_
.find(event_name
);
259 if (observer
!= observers_
.end())
260 observer
->second
->OnListenerRemoved(details
);
264 ? Profile::FromBrowserContext(listener
->process
->GetBrowserContext())
266 BrowserThread::PostTask(
267 BrowserThread::IO
, FROM_HERE
,
268 base::Bind(&NotifyEventListenerRemovedOnIOThread
,
269 profile
, listener
->extension_id
, event_name
));
271 // TODO(felt): Experimentally determine if these are needed, or if they
272 // can be permanently removed. Temporarily removing for now to reduce log
273 // size while under investigation.
274 const Extension
* extension
= ExtensionSystem::Get(profile_
)->
275 extension_service()->GetExtensionById(listener
->extension_id
,
276 ExtensionService::INCLUDE_ENABLED
);
278 scoped_ptr
<ListValue
> args(new ListValue());
279 activity_log_
->LogAPIAction(
280 extension
, event_name
+ ".removeListener", args
.get(), std::string());
285 void EventRouter::AddLazyEventListener(const std::string
& event_name
,
286 const std::string
& extension_id
) {
287 scoped_ptr
<EventListener
> listener(new EventListener(
288 event_name
, extension_id
, NULL
, scoped_ptr
<DictionaryValue
>()));
289 bool is_new
= listeners_
.AddListener(listener
.Pass());
292 ExtensionPrefs
* prefs
= ExtensionSystem::Get(profile_
)->extension_prefs();
293 std::set
<std::string
> events
= prefs
->GetRegisteredEvents(extension_id
);
294 bool prefs_is_new
= events
.insert(event_name
).second
;
296 prefs
->SetRegisteredEvents(extension_id
, events
);
300 void EventRouter::RemoveLazyEventListener(const std::string
& event_name
,
301 const std::string
& extension_id
) {
302 EventListener
listener(event_name
, extension_id
, NULL
,
303 scoped_ptr
<DictionaryValue
>());
304 bool did_exist
= listeners_
.RemoveListener(&listener
);
307 ExtensionPrefs
* prefs
= ExtensionSystem::Get(profile_
)->extension_prefs();
308 std::set
<std::string
> events
= prefs
->GetRegisteredEvents(extension_id
);
309 bool prefs_did_exist
= events
.erase(event_name
) > 0;
310 DCHECK(prefs_did_exist
);
311 prefs
->SetRegisteredEvents(extension_id
, events
);
315 void EventRouter::AddFilteredEventListener(const std::string
& event_name
,
316 content::RenderProcessHost
* process
,
317 const std::string
& extension_id
,
318 const base::DictionaryValue
& filter
,
319 bool add_lazy_listener
) {
320 listeners_
.AddListener(scoped_ptr
<EventListener
>(new EventListener(
321 event_name
, extension_id
, process
,
322 scoped_ptr
<DictionaryValue
>(filter
.DeepCopy()))));
324 if (add_lazy_listener
) {
325 bool added
= listeners_
.AddListener(scoped_ptr
<EventListener
>(
326 new EventListener(event_name
, extension_id
, NULL
,
327 scoped_ptr
<DictionaryValue
>(filter
.DeepCopy()))));
330 ExtensionPrefs
* prefs
= ExtensionSystem::Get(profile_
)->extension_prefs();
331 prefs
->AddFilterToEvent(event_name
, extension_id
, &filter
);
336 void EventRouter::RemoveFilteredEventListener(
337 const std::string
& event_name
,
338 content::RenderProcessHost
* process
,
339 const std::string
& extension_id
,
340 const base::DictionaryValue
& filter
,
341 bool remove_lazy_listener
) {
342 EventListener
listener(event_name
, extension_id
, process
,
343 scoped_ptr
<DictionaryValue
>(filter
.DeepCopy()));
345 listeners_
.RemoveListener(&listener
);
347 if (remove_lazy_listener
) {
348 listener
.process
= NULL
;
349 bool removed
= listeners_
.RemoveListener(&listener
);
352 ExtensionPrefs
* prefs
= ExtensionSystem::Get(profile_
)->extension_prefs();
353 prefs
->RemoveFilterFromEvent(event_name
, extension_id
, &filter
);
358 bool EventRouter::HasEventListener(const std::string
& event_name
) {
359 return listeners_
.HasListenerForEvent(event_name
);
362 bool EventRouter::ExtensionHasEventListener(const std::string
& extension_id
,
363 const std::string
& event_name
) {
364 return listeners_
.HasListenerForExtension(extension_id
, event_name
);
367 bool EventRouter::HasEventListenerImpl(const ListenerMap
& listener_map
,
368 const std::string
& extension_id
,
369 const std::string
& event_name
) {
370 ListenerMap::const_iterator it
= listener_map
.find(event_name
);
371 if (it
== listener_map
.end())
374 const std::set
<ListenerProcess
>& listeners
= it
->second
;
375 if (extension_id
.empty())
376 return !listeners
.empty();
378 for (std::set
<ListenerProcess
>::const_iterator listener
= listeners
.begin();
379 listener
!= listeners
.end(); ++listener
) {
380 if (listener
->extension_id
== extension_id
)
386 void EventRouter::BroadcastEvent(scoped_ptr
<Event
> event
) {
387 DispatchEventImpl(std::string(), linked_ptr
<Event
>(event
.release()));
390 void EventRouter::DispatchEventToExtension(const std::string
& extension_id
,
391 scoped_ptr
<Event
> event
) {
392 DCHECK(!extension_id
.empty());
393 DispatchEventImpl(extension_id
, linked_ptr
<Event
>(event
.release()));
396 void EventRouter::DispatchEventImpl(const std::string
& restrict_to_extension_id
,
397 const linked_ptr
<Event
>& event
) {
398 // We don't expect to get events from a completely different profile.
399 DCHECK(!event
->restrict_to_profile
||
400 profile_
->IsSameProfile(event
->restrict_to_profile
));
402 std::set
<const EventListener
*> listeners(
403 listeners_
.GetEventListeners(*event
));
405 std::set
<EventDispatchIdentifier
> already_dispatched
;
407 // We dispatch events for lazy background pages first because attempting to do
408 // so will cause those that are being suspended to cancel that suspension.
409 // As canceling a suspension entails sending an event to the affected
410 // background page, and as that event needs to be delivered before we dispatch
411 // the event we are dispatching here, we dispatch to the lazy listeners here
413 for (std::set
<const EventListener
*>::iterator it
= listeners
.begin();
414 it
!= listeners
.end(); it
++) {
415 const EventListener
* listener
= *it
;
416 if (restrict_to_extension_id
.empty() ||
417 restrict_to_extension_id
== listener
->extension_id
) {
418 if (!listener
->process
) {
419 DispatchLazyEvent(listener
->extension_id
, event
, &already_dispatched
);
424 for (std::set
<const EventListener
*>::iterator it
= listeners
.begin();
425 it
!= listeners
.end(); it
++) {
426 const EventListener
* listener
= *it
;
427 if (restrict_to_extension_id
.empty() ||
428 restrict_to_extension_id
== listener
->extension_id
) {
429 if (listener
->process
) {
430 EventDispatchIdentifier
dispatch_id(
431 listener
->process
->GetBrowserContext(), listener
->extension_id
);
432 if (!ContainsKey(already_dispatched
, dispatch_id
)) {
433 DispatchEventToProcess(listener
->extension_id
, listener
->process
,
441 void EventRouter::DispatchLazyEvent(
442 const std::string
& extension_id
,
443 const linked_ptr
<Event
>& event
,
444 std::set
<EventDispatchIdentifier
>* already_dispatched
) {
445 ExtensionService
* service
=
446 ExtensionSystem::Get(profile_
)->extension_service();
447 // Check both the original and the incognito profile to see if we
448 // should load a lazy bg page to handle the event. The latter case
449 // occurs in the case of split-mode extensions.
450 const Extension
* extension
= service
->extensions()->GetByID(extension_id
);
452 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
453 profile_
, extension
, event
)) {
454 already_dispatched
->insert(std::make_pair(profile_
, extension_id
));
457 if (profile_
->HasOffTheRecordProfile() &&
458 IncognitoInfo::IsSplitMode(extension
)) {
459 if (MaybeLoadLazyBackgroundPageToDispatchEvent(
460 profile_
->GetOffTheRecordProfile(), extension
, event
)) {
461 already_dispatched
->insert(
462 std::make_pair(profile_
->GetOffTheRecordProfile(), extension_id
));
468 void EventRouter::DispatchEventToProcess(const std::string
& extension_id
,
469 content::RenderProcessHost
* process
,
470 const linked_ptr
<Event
>& event
) {
471 ExtensionService
* service
=
472 ExtensionSystem::Get(profile_
)->extension_service();
473 const Extension
* extension
= service
->extensions()->GetByID(extension_id
);
475 // The extension could have been removed, but we do not unregister it until
476 // the extension process is unloaded.
480 Profile
* listener_profile
= Profile::FromBrowserContext(
481 process
->GetBrowserContext());
482 ProcessMap
* process_map
= ExtensionSystem::Get(listener_profile
)->
483 extension_service()->process_map();
484 // If the event is privileged, only send to extension processes. Otherwise,
485 // it's OK to send to normal renderers (e.g., for content scripts).
486 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event
->event_name
) &&
487 !process_map
->Contains(extension
->id(), process
->GetID())) {
491 if (!CanDispatchEventToProfile(listener_profile
, extension
, event
))
494 if (!event
->will_dispatch_callback
.is_null()) {
495 event
->will_dispatch_callback
.Run(listener_profile
, extension
,
496 event
->event_args
.get());
499 DispatchExtensionMessage(process
, listener_profile
, extension_id
,
500 event
->event_name
, event
->event_args
.get(),
501 event
->event_url
, event
->user_gesture
,
503 IncrementInFlightEvents(listener_profile
, extension
);
506 bool EventRouter::CanDispatchEventToProfile(Profile
* profile
,
507 const Extension
* extension
,
508 const linked_ptr
<Event
>& event
) {
509 // Is this event from a different profile than the renderer (ie, an
510 // incognito tab event sent to a normal process, or vice versa).
511 bool cross_incognito
=
512 event
->restrict_to_profile
&& profile
!= event
->restrict_to_profile
;
513 if (cross_incognito
&&
514 !ExtensionSystem::Get(profile
)->extension_service()->
515 CanCrossIncognito(extension
)) {
522 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
524 const Extension
* extension
,
525 const linked_ptr
<Event
>& event
) {
526 if (!CanDispatchEventToProfile(profile
, extension
, event
))
529 LazyBackgroundTaskQueue
* queue
=
530 ExtensionSystem::Get(profile
)->lazy_background_task_queue();
531 if (queue
->ShouldEnqueueTask(profile
, extension
)) {
532 linked_ptr
<Event
> dispatched_event(event
);
534 // If there's a dispatch callback, call it now (rather than dispatch time)
535 // to avoid lifetime issues. Use a separate copy of the event args, so they
536 // last until the event is dispatched.
537 if (!event
->will_dispatch_callback
.is_null()) {
538 dispatched_event
.reset(event
->DeepCopy());
539 dispatched_event
->will_dispatch_callback
.Run(
540 profile
, extension
, dispatched_event
->event_args
.get());
541 // Ensure we don't call it again at dispatch time.
542 dispatched_event
->will_dispatch_callback
.Reset();
545 queue
->AddPendingTask(profile
, extension
->id(),
546 base::Bind(&EventRouter::DispatchPendingEvent
,
547 base::Unretained(this), dispatched_event
));
554 void EventRouter::IncrementInFlightEvents(Profile
* profile
,
555 const Extension
* extension
) {
556 // Only increment in-flight events if the lazy background page is active,
557 // because that's the only time we'll get an ACK.
558 if (BackgroundInfo::HasLazyBackgroundPage(extension
)) {
559 ExtensionProcessManager
* pm
=
560 ExtensionSystem::Get(profile
)->process_manager();
561 ExtensionHost
* host
= pm
->GetBackgroundHostForExtension(extension
->id());
563 pm
->IncrementLazyKeepaliveCount(extension
);
567 void EventRouter::OnEventAck(Profile
* profile
,
568 const std::string
& extension_id
) {
569 ExtensionProcessManager
* pm
=
570 ExtensionSystem::Get(profile
)->process_manager();
571 ExtensionHost
* host
= pm
->GetBackgroundHostForExtension(extension_id
);
572 // The event ACK is routed to the background host, so this should never be
575 // TODO(mpcomplete): We should never get this message unless
576 // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
577 if (host
->extension() &&
578 BackgroundInfo::HasLazyBackgroundPage(host
->extension()))
579 pm
->DecrementLazyKeepaliveCount(host
->extension());
582 void EventRouter::DispatchPendingEvent(const linked_ptr
<Event
>& event
,
583 ExtensionHost
* host
) {
587 if (listeners_
.HasProcessListener(host
->render_process_host(),
588 host
->extension()->id())) {
589 DispatchEventToProcess(host
->extension()->id(),
590 host
->render_process_host(), event
);
594 void EventRouter::Observe(int type
,
595 const content::NotificationSource
& source
,
596 const content::NotificationDetails
& details
) {
598 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED
:
599 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED
: {
600 content::RenderProcessHost
* renderer
=
601 content::Source
<content::RenderProcessHost
>(source
).ptr();
602 // Remove all event listeners associated with this renderer.
603 listeners_
.RemoveListenersForProcess(renderer
);
606 case chrome::NOTIFICATION_EXTENSIONS_READY
: {
607 // We're done restarting Chrome after an update.
608 dispatch_chrome_updated_event_
= false;
611 case chrome::NOTIFICATION_EXTENSION_ENABLED
: {
612 // If the extension has a lazy background page, make sure it gets loaded
613 // to register the events the extension is interested in.
614 const Extension
* extension
=
615 content::Details
<const Extension
>(details
).ptr();
616 if (BackgroundInfo::HasLazyBackgroundPage(extension
)) {
617 LazyBackgroundTaskQueue
* queue
=
618 ExtensionSystem::Get(profile_
)->lazy_background_task_queue();
619 queue
->AddPendingTask(profile_
, extension
->id(),
620 base::Bind(&DoNothing
));
624 case chrome::NOTIFICATION_EXTENSION_LOADED
: {
625 // Add all registered lazy listeners to our cache.
626 const Extension
* extension
=
627 content::Details
<const Extension
>(details
).ptr();
628 ExtensionPrefs
* prefs
= ExtensionSystem::Get(profile_
)->extension_prefs();
629 std::set
<std::string
> registered_events
=
630 prefs
->GetRegisteredEvents(extension
->id());
631 listeners_
.LoadUnfilteredLazyListeners(extension
->id(),
633 const DictionaryValue
* filtered_events
=
634 prefs
->GetFilteredEvents(extension
->id());
636 listeners_
.LoadFilteredLazyListeners(extension
->id(), *filtered_events
);
638 if (dispatch_chrome_updated_event_
) {
639 MessageLoop::current()->PostTask(FROM_HERE
,
640 base::Bind(&DispatchOnInstalledEvent
, profile_
, extension
->id(),
645 case chrome::NOTIFICATION_EXTENSION_UNLOADED
: {
646 // Remove all registered lazy listeners from our cache.
647 UnloadedExtensionInfo
* unloaded
=
648 content::Details
<UnloadedExtensionInfo
>(details
).ptr();
649 listeners_
.RemoveLazyListenersForExtension(unloaded
->extension
->id());
652 case chrome::NOTIFICATION_EXTENSION_INSTALLED
: {
653 // Dispatch the onInstalled event.
654 const Extension
* extension
=
655 content::Details
<const InstalledExtensionInfo
>(details
)->extension
;
657 // Get the previous version, if this is an upgrade.
658 ExtensionService
* service
=
659 ExtensionSystem::Get(profile_
)->extension_service();
660 const Extension
* old
= service
->GetExtensionById(extension
->id(), true);
663 old_version
= *old
->version();
665 MessageLoop::current()->PostTask(FROM_HERE
,
666 base::Bind(&DispatchOnInstalledEvent
, profile_
, extension
->id(),
667 old_version
, false));
676 Event::Event(const std::string
& event_name
,
677 scoped_ptr
<base::ListValue
> event_args
)
678 : event_name(event_name
),
679 event_args(event_args
.Pass()),
680 restrict_to_profile(NULL
),
681 user_gesture(EventRouter::USER_GESTURE_UNKNOWN
) {
682 DCHECK(this->event_args
.get());
685 Event::Event(const std::string
& event_name
,
686 scoped_ptr
<base::ListValue
> event_args
,
687 Profile
* restrict_to_profile
)
688 : event_name(event_name
),
689 event_args(event_args
.Pass()),
690 restrict_to_profile(restrict_to_profile
),
691 user_gesture(EventRouter::USER_GESTURE_UNKNOWN
) {
692 DCHECK(this->event_args
.get());
695 Event::Event(const std::string
& event_name
,
696 scoped_ptr
<ListValue
> event_args
,
697 Profile
* restrict_to_profile
,
698 const GURL
& event_url
,
699 EventRouter::UserGestureState user_gesture
,
700 const EventFilteringInfo
& filter_info
)
701 : event_name(event_name
),
702 event_args(event_args
.Pass()),
703 restrict_to_profile(restrict_to_profile
),
704 event_url(event_url
),
705 user_gesture(user_gesture
),
706 filter_info(filter_info
) {
707 DCHECK(this->event_args
.get());
712 Event
* Event::DeepCopy() {
713 Event
* copy
= new Event(event_name
,
714 scoped_ptr
<base::ListValue
>(event_args
->DeepCopy()),
719 copy
->will_dispatch_callback
= will_dispatch_callback
;
723 EventListenerInfo::EventListenerInfo(const std::string
& event_name
,
724 const std::string
& extension_id
)
725 : event_name(event_name
),
726 extension_id(extension_id
) {}
728 } // namespace extensions