Home | History | Annotate | Download | only in extensions
      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.
      4 
      5 #include "chrome/browser/extensions/event_router.h"
      6 
      7 #include <utility>
      8 
      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 "base/version.h"
     15 #include "chrome/browser/browser_process.h"
     16 #include "chrome/browser/chrome_notification_types.h"
     17 #include "chrome/browser/extensions/activity_log/activity_log.h"
     18 #include "chrome/browser/extensions/api/runtime/runtime_api.h"
     19 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
     20 #include "chrome/browser/extensions/event_names.h"
     21 #include "chrome/browser/extensions/extension_host.h"
     22 #include "chrome/browser/extensions/extension_prefs.h"
     23 #include "chrome/browser/extensions/extension_process_manager.h"
     24 #include "chrome/browser/extensions/extension_service.h"
     25 #include "chrome/browser/extensions/extension_system.h"
     26 #include "chrome/browser/extensions/lazy_background_task_queue.h"
     27 #include "chrome/browser/extensions/process_map.h"
     28 #include "chrome/browser/profiles/profile.h"
     29 #include "chrome/browser/profiles/profile_manager.h"
     30 #include "chrome/common/chrome_switches.h"
     31 #include "chrome/common/chrome_version_info.h"
     32 #include "chrome/common/extensions/api/extension_api.h"
     33 #include "chrome/common/extensions/background_info.h"
     34 #include "chrome/common/extensions/extension.h"
     35 #include "chrome/common/extensions/extension_messages.h"
     36 #include "chrome/common/extensions/incognito_handler.h"
     37 #include "content/public/browser/notification_service.h"
     38 #include "content/public/browser/render_process_host.h"
     39 
     40 using base::DictionaryValue;
     41 using base::ListValue;
     42 using content::BrowserThread;
     43 
     44 namespace extensions {
     45 
     46 namespace {
     47 
     48 void NotifyEventListenerRemovedOnIOThread(
     49     void* profile,
     50     const std::string& extension_id,
     51     const std::string& sub_event_name) {
     52   ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
     53       profile, extension_id, sub_event_name);
     54 }
     55 
     56 void DispatchOnInstalledEvent(
     57     Profile* profile,
     58     const std::string& extension_id,
     59     const Version& old_version,
     60     bool chrome_updated) {
     61   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
     62     return;
     63 
     64   RuntimeEventRouter::DispatchOnInstalledEvent(profile, extension_id,
     65                                                old_version, chrome_updated);
     66 }
     67 
     68 void DoNothing(ExtensionHost* host) {}
     69 
     70 // A dictionary of event names to lists of filters that this extension has
     71 // registered from its lazy background page.
     72 const char kFilteredEvents[] = "filtered_events";
     73 
     74 }  // namespace
     75 
     76 const char EventRouter::kRegisteredEvents[] = "events";
     77 
     78 struct EventRouter::ListenerProcess {
     79   content::RenderProcessHost* process;
     80   std::string extension_id;
     81 
     82   ListenerProcess(content::RenderProcessHost* process,
     83                   const std::string& extension_id)
     84       : process(process), extension_id(extension_id) {}
     85 
     86   bool operator<(const ListenerProcess& that) const {
     87     if (process < that.process)
     88       return true;
     89     if (process == that.process && extension_id < that.extension_id)
     90       return true;
     91     return false;
     92   }
     93 };
     94 
     95 // static
     96 void EventRouter::LogExtensionEventMessage(void* profile_id,
     97                                            const std::string& extension_id,
     98                                            const std::string& event_name,
     99                                            scoped_ptr<ListValue> event_args) {
    100   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    101     BrowserThread::PostTask(BrowserThread::UI,
    102                             FROM_HERE,
    103                             base::Bind(&LogExtensionEventMessage,
    104                                        profile_id,
    105                                        extension_id,
    106                                        event_name,
    107                                        base::Passed(&event_args)));
    108   } else {
    109     Profile* profile = reinterpret_cast<Profile*>(profile_id);
    110     if (!g_browser_process->profile_manager()->IsValidProfile(profile))
    111       return;
    112     scoped_refptr<Action> action = new Action(
    113         extension_id, base::Time::Now(), Action::ACTION_API_EVENT, event_name);
    114     action->set_args(event_args.Pass());
    115     ActivityLog::GetInstance(profile)->LogAction(action);
    116   }
    117 }
    118 
    119 // static
    120 void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
    121                                            void* profile_id,
    122                                            const std::string& extension_id,
    123                                            const std::string& event_name,
    124                                            ListValue* event_args,
    125                                            UserGestureState user_gesture,
    126                                            const EventFilteringInfo& info) {
    127   if (ActivityLog::IsLogEnabledOnAnyProfile()) {
    128     LogExtensionEventMessage(profile_id, extension_id, event_name,
    129                              scoped_ptr<ListValue>(event_args->DeepCopy()));
    130   }
    131 
    132   ListValue args;
    133   args.Set(0, Value::CreateStringValue(event_name));
    134   args.Set(1, event_args);
    135   args.Set(2, info.AsValue().release());
    136   ipc_sender->Send(new ExtensionMsg_MessageInvoke(
    137       MSG_ROUTING_CONTROL,
    138       extension_id,
    139       "event_bindings",
    140       "dispatchEvent",
    141       args,
    142       user_gesture == USER_GESTURE_ENABLED));
    143 
    144   // DispatchExtensionMessage does _not_ take ownership of event_args, so we
    145   // must ensure that the destruction of args does not attempt to free it.
    146   scoped_ptr<Value> removed_event_args;
    147   args.Remove(1, &removed_event_args);
    148   ignore_result(removed_event_args.release());
    149 }
    150 
    151 // static
    152 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
    153                                 void* profile_id,
    154                                 const std::string& extension_id,
    155                                 const std::string& event_name,
    156                                 scoped_ptr<ListValue> event_args,
    157                                 UserGestureState user_gesture,
    158                                 const EventFilteringInfo& info) {
    159   DispatchExtensionMessage(ipc_sender, profile_id, extension_id, event_name,
    160                            event_args.get(), user_gesture, info);
    161 
    162   BrowserThread::PostTask(
    163       BrowserThread::UI,
    164       FROM_HERE,
    165       base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
    166                   profile_id,
    167                   extension_id));
    168 }
    169 
    170 EventRouter::EventRouter(Profile* profile, ExtensionPrefs* extension_prefs)
    171     : profile_(profile),
    172       listeners_(this),
    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_));
    188 
    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_ = !CheckRegisteredEventsUpToDate();
    194   }
    195 }
    196 
    197 EventRouter::~EventRouter() {}
    198 
    199 void EventRouter::AddEventListener(const std::string& event_name,
    200                                    content::RenderProcessHost* process,
    201                                    const std::string& extension_id) {
    202   listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
    203       event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
    204 }
    205 
    206 void EventRouter::RemoveEventListener(const std::string& event_name,
    207                                       content::RenderProcessHost* process,
    208                                       const std::string& extension_id) {
    209   EventListener listener(event_name, extension_id, process,
    210                          scoped_ptr<DictionaryValue>());
    211   listeners_.RemoveListener(&listener);
    212 }
    213 
    214 void EventRouter::RegisterObserver(Observer* observer,
    215                                    const std::string& event_name) {
    216   observers_[event_name] = observer;
    217 }
    218 
    219 void EventRouter::UnregisterObserver(Observer* observer) {
    220   std::vector<ObserverMap::iterator> iters_to_remove;
    221   for (ObserverMap::iterator iter = observers_.begin();
    222        iter != observers_.end(); ++iter) {
    223     if (iter->second == observer)
    224       iters_to_remove.push_back(iter);
    225   }
    226   for (size_t i = 0; i < iters_to_remove.size(); ++i)
    227     observers_.erase(iters_to_remove[i]);
    228 }
    229 
    230 void EventRouter::OnListenerAdded(const EventListener* listener) {
    231   const std::string& event_name = listener->event_name;
    232   const EventListenerInfo details(event_name, listener->extension_id);
    233   ObserverMap::iterator observer = observers_.find(event_name);
    234   if (observer != observers_.end())
    235     observer->second->OnListenerAdded(details);
    236 
    237 #if 0
    238   // TODO(felt): Experimentally determine if these are needed, or if they
    239   // can be permanently removed. Temporarily removing for now to reduce log
    240   // size while under investigation.
    241   const Extension* extension = ExtensionSystem::Get(profile_)->
    242       extension_service()->GetExtensionById(listener->extension_id,
    243                                             ExtensionService::INCLUDE_ENABLED);
    244   if (extension) {
    245     scoped_ptr<ListValue> args(new ListValue());
    246     if (listener->filter)
    247       args->Append(listener->filter->DeepCopy());
    248     ActivityLog::GetInstance(profile)->LogAPIAction(
    249         extension, event_name + ".addListener", args.get(), std::string());
    250   }
    251 #endif
    252 }
    253 
    254 void EventRouter::OnListenerRemoved(const EventListener* listener) {
    255   const std::string& event_name = listener->event_name;
    256   const EventListenerInfo details(event_name, listener->extension_id);
    257   ObserverMap::iterator observer = observers_.find(event_name);
    258   if (observer != observers_.end())
    259     observer->second->OnListenerRemoved(details);
    260 
    261   void* profile =
    262       listener->process
    263           ? Profile::FromBrowserContext(listener->process->GetBrowserContext())
    264           : NULL;
    265   BrowserThread::PostTask(
    266       BrowserThread::IO, FROM_HERE,
    267       base::Bind(&NotifyEventListenerRemovedOnIOThread,
    268                  profile, listener->extension_id, event_name));
    269 #if 0
    270   // TODO(felt): Experimentally determine if these are needed, or if they
    271   // can be permanently removed. Temporarily removing for now to reduce log
    272   // size while under investigation.
    273   const Extension* extension = ExtensionSystem::Get(profile_)->
    274       extension_service()->GetExtensionById(listener->extension_id,
    275                                             ExtensionService::INCLUDE_ENABLED);
    276   if (extension) {
    277     scoped_ptr<ListValue> args(new ListValue());
    278     ActivityLog::GetInstance(profile)->LogAPIAction(
    279         extension, event_name + ".removeListener", args.get(), std::string());
    280   }
    281 #endif
    282 }
    283 
    284 void EventRouter::AddLazyEventListener(const std::string& event_name,
    285                                        const std::string& extension_id) {
    286   scoped_ptr<EventListener> listener(new EventListener(
    287       event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
    288   bool is_new = listeners_.AddListener(listener.Pass());
    289 
    290   if (is_new) {
    291     std::set<std::string> events = GetRegisteredEvents(extension_id);
    292     bool prefs_is_new = events.insert(event_name).second;
    293     if (prefs_is_new)
    294       SetRegisteredEvents(extension_id, events);
    295   }
    296 }
    297 
    298 void EventRouter::RemoveLazyEventListener(const std::string& event_name,
    299                                           const std::string& extension_id) {
    300   EventListener listener(event_name, extension_id, NULL,
    301                          scoped_ptr<DictionaryValue>());
    302   bool did_exist = listeners_.RemoveListener(&listener);
    303 
    304   if (did_exist) {
    305     std::set<std::string> events = GetRegisteredEvents(extension_id);
    306     bool prefs_did_exist = events.erase(event_name) > 0;
    307     DCHECK(prefs_did_exist);
    308     SetRegisteredEvents(extension_id, events);
    309   }
    310 }
    311 
    312 void EventRouter::AddFilteredEventListener(const std::string& event_name,
    313                                            content::RenderProcessHost* process,
    314                                            const std::string& extension_id,
    315                                            const base::DictionaryValue& filter,
    316                                            bool add_lazy_listener) {
    317   listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
    318       event_name, extension_id, process,
    319       scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
    320 
    321   if (add_lazy_listener) {
    322     bool added = listeners_.AddListener(scoped_ptr<EventListener>(
    323         new EventListener(event_name, extension_id, NULL,
    324         scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
    325 
    326     if (added)
    327       AddFilterToEvent(event_name, extension_id, &filter);
    328   }
    329 }
    330 
    331 void EventRouter::RemoveFilteredEventListener(
    332     const std::string& event_name,
    333     content::RenderProcessHost* process,
    334     const std::string& extension_id,
    335     const base::DictionaryValue& filter,
    336     bool remove_lazy_listener) {
    337   EventListener listener(event_name, extension_id, process,
    338                          scoped_ptr<DictionaryValue>(filter.DeepCopy()));
    339 
    340   listeners_.RemoveListener(&listener);
    341 
    342   if (remove_lazy_listener) {
    343     listener.process = NULL;
    344     bool removed = listeners_.RemoveListener(&listener);
    345 
    346     if (removed)
    347       RemoveFilterFromEvent(event_name, extension_id, &filter);
    348   }
    349 }
    350 
    351 bool EventRouter::HasEventListener(const std::string& event_name) {
    352   return listeners_.HasListenerForEvent(event_name);
    353 }
    354 
    355 bool EventRouter::ExtensionHasEventListener(const std::string& extension_id,
    356                                             const std::string& event_name) {
    357   return listeners_.HasListenerForExtension(extension_id, event_name);
    358 }
    359 
    360 bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map,
    361                                        const std::string& extension_id,
    362                                        const std::string& event_name) {
    363   ListenerMap::const_iterator it = listener_map.find(event_name);
    364   if (it == listener_map.end())
    365     return false;
    366 
    367   const std::set<ListenerProcess>& listeners = it->second;
    368   if (extension_id.empty())
    369     return !listeners.empty();
    370 
    371   for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
    372        listener != listeners.end(); ++listener) {
    373     if (listener->extension_id == extension_id)
    374       return true;
    375   }
    376   return false;
    377 }
    378 
    379 std::set<std::string> EventRouter::GetRegisteredEvents(
    380     const std::string& extension_id) {
    381   std::set<std::string> events;
    382   const ListValue* events_value = NULL;
    383   ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
    384 
    385   if (!prefs ||
    386       !prefs->ReadPrefAsList(extension_id, kRegisteredEvents, &events_value)) {
    387     return events;
    388   }
    389 
    390   for (size_t i = 0; i < events_value->GetSize(); ++i) {
    391     std::string event;
    392     if (events_value->GetString(i, &event))
    393       events.insert(event);
    394   }
    395   return events;
    396 }
    397 
    398 void EventRouter::SetRegisteredEvents(const std::string& extension_id,
    399                                       const std::set<std::string>& events) {
    400   ListValue* events_value = new ListValue;
    401   for (std::set<std::string>::const_iterator iter = events.begin();
    402        iter != events.end(); ++iter) {
    403     events_value->Append(new StringValue(*iter));
    404   }
    405   ExtensionPrefs::Get(profile_)->UpdateExtensionPref(
    406       extension_id,
    407       kRegisteredEvents,
    408       events_value);
    409 }
    410 
    411 bool EventRouter::CheckRegisteredEventsUpToDate() {
    412   // If we're running inside a test, then assume prefs are all up-to-date.
    413   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType))
    414     return true;
    415 
    416   base::Version version;
    417   PrefService* pref_service = profile_->GetPrefs();
    418   if (pref_service->HasPrefPath(ExtensionPrefs::kExtensionsLastChromeVersion)) {
    419     std::string version_str =
    420         pref_service->GetString(ExtensionPrefs::kExtensionsLastChromeVersion);
    421     version = Version(version_str);
    422   }
    423 
    424   chrome::VersionInfo current_version_info;
    425   std::string current_version = current_version_info.Version();
    426   pref_service->SetString(ExtensionPrefs::kExtensionsLastChromeVersion,
    427                           current_version);
    428 
    429   // If there was no version string in prefs, assume we're out of date.
    430   if (!version.IsValid() || version.IsOlderThan(current_version))
    431     return false;
    432 
    433   return true;
    434 }
    435 
    436 void EventRouter::AddFilterToEvent(const std::string& event_name,
    437                                    const std::string& extension_id,
    438                                    const DictionaryValue* filter) {
    439   ExtensionPrefs::ScopedDictionaryUpdate update(
    440       ExtensionPrefs::Get(profile_),
    441       extension_id,
    442       kFilteredEvents);
    443   DictionaryValue* filtered_events = update.Get();
    444   if (!filtered_events)
    445     filtered_events = update.Create();
    446 
    447   ListValue* filter_list = NULL;
    448   if (!filtered_events->GetList(event_name, &filter_list)) {
    449     filter_list = new ListValue;
    450     filtered_events->SetWithoutPathExpansion(event_name, filter_list);
    451   }
    452 
    453   filter_list->Append(filter->DeepCopy());
    454 }
    455 
    456 void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
    457                                         const std::string& extension_id,
    458                                         const DictionaryValue* filter) {
    459   ExtensionPrefs::ScopedDictionaryUpdate update(
    460       ExtensionPrefs::Get(profile_),
    461       extension_id,
    462       kFilteredEvents);
    463   DictionaryValue* filtered_events = update.Get();
    464   ListValue* filter_list = NULL;
    465   if (!filtered_events ||
    466       !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
    467     return;
    468   }
    469 
    470   for (size_t i = 0; i < filter_list->GetSize(); i++) {
    471     DictionaryValue* filter = NULL;
    472     CHECK(filter_list->GetDictionary(i, &filter));
    473     if (filter->Equals(filter)) {
    474       filter_list->Remove(i, NULL);
    475       break;
    476     }
    477   }
    478 }
    479 
    480 const DictionaryValue* EventRouter::GetFilteredEvents(
    481     const std::string& extension_id) {
    482   const DictionaryValue* events = NULL;
    483   ExtensionPrefs::Get(profile_)->ReadPrefAsDictionary(
    484       extension_id, kFilteredEvents, &events);
    485   return events;
    486 }
    487 
    488 void EventRouter::BroadcastEvent(scoped_ptr<Event> event) {
    489   DispatchEventImpl(std::string(), linked_ptr<Event>(event.release()));
    490 }
    491 
    492 void EventRouter::DispatchEventToExtension(const std::string& extension_id,
    493                                            scoped_ptr<Event> event) {
    494   DCHECK(!extension_id.empty());
    495   DispatchEventImpl(extension_id, linked_ptr<Event>(event.release()));
    496 }
    497 
    498 void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
    499                                                 scoped_ptr<Event> event) {
    500   DCHECK(!extension_id.empty());
    501   std::string event_name = event->event_name;
    502   bool has_listener = ExtensionHasEventListener(extension_id, event_name);
    503   if (!has_listener)
    504     AddLazyEventListener(event_name, extension_id);
    505   DispatchEventToExtension(extension_id, event.Pass());
    506   if (!has_listener)
    507     RemoveLazyEventListener(event_name, extension_id);
    508 }
    509 
    510 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
    511                                     const linked_ptr<Event>& event) {
    512   // We don't expect to get events from a completely different profile.
    513   DCHECK(!event->restrict_to_profile ||
    514          profile_->IsSameProfile(event->restrict_to_profile));
    515 
    516   std::set<const EventListener*> listeners(
    517       listeners_.GetEventListeners(*event));
    518 
    519   std::set<EventDispatchIdentifier> already_dispatched;
    520 
    521   // We dispatch events for lazy background pages first because attempting to do
    522   // so will cause those that are being suspended to cancel that suspension.
    523   // As canceling a suspension entails sending an event to the affected
    524   // background page, and as that event needs to be delivered before we dispatch
    525   // the event we are dispatching here, we dispatch to the lazy listeners here
    526   // first.
    527   for (std::set<const EventListener*>::iterator it = listeners.begin();
    528        it != listeners.end(); it++) {
    529     const EventListener* listener = *it;
    530     if (restrict_to_extension_id.empty() ||
    531         restrict_to_extension_id == listener->extension_id) {
    532       if (!listener->process) {
    533         DispatchLazyEvent(listener->extension_id, event, &already_dispatched);
    534       }
    535     }
    536   }
    537 
    538   for (std::set<const EventListener*>::iterator it = listeners.begin();
    539        it != listeners.end(); it++) {
    540     const EventListener* listener = *it;
    541     if (restrict_to_extension_id.empty() ||
    542         restrict_to_extension_id == listener->extension_id) {
    543       if (listener->process) {
    544         EventDispatchIdentifier dispatch_id(
    545             listener->process->GetBrowserContext(), listener->extension_id);
    546         if (!ContainsKey(already_dispatched, dispatch_id)) {
    547           DispatchEventToProcess(listener->extension_id, listener->process,
    548               event);
    549         }
    550       }
    551     }
    552   }
    553 }
    554 
    555 void EventRouter::DispatchLazyEvent(
    556     const std::string& extension_id,
    557     const linked_ptr<Event>& event,
    558     std::set<EventDispatchIdentifier>* already_dispatched) {
    559   ExtensionService* service =
    560       ExtensionSystem::Get(profile_)->extension_service();
    561   // Check both the original and the incognito profile to see if we
    562   // should load a lazy bg page to handle the event. The latter case
    563   // occurs in the case of split-mode extensions.
    564   const Extension* extension = service->extensions()->GetByID(extension_id);
    565   if (extension) {
    566     if (MaybeLoadLazyBackgroundPageToDispatchEvent(
    567           profile_, extension, event)) {
    568       already_dispatched->insert(std::make_pair(profile_, extension_id));
    569     }
    570 
    571     if (profile_->HasOffTheRecordProfile() &&
    572         IncognitoInfo::IsSplitMode(extension)) {
    573       if (MaybeLoadLazyBackgroundPageToDispatchEvent(
    574           profile_->GetOffTheRecordProfile(), extension, event)) {
    575         already_dispatched->insert(
    576             std::make_pair(profile_->GetOffTheRecordProfile(), extension_id));
    577       }
    578     }
    579   }
    580 }
    581 
    582 void EventRouter::DispatchEventToProcess(const std::string& extension_id,
    583                                          content::RenderProcessHost* process,
    584                                          const linked_ptr<Event>& event) {
    585   ExtensionService* service =
    586       ExtensionSystem::Get(profile_)->extension_service();
    587   const Extension* extension = service->extensions()->GetByID(extension_id);
    588 
    589   // The extension could have been removed, but we do not unregister it until
    590   // the extension process is unloaded.
    591   if (!extension)
    592     return;
    593 
    594   Profile* listener_profile = Profile::FromBrowserContext(
    595       process->GetBrowserContext());
    596   ProcessMap* process_map = ExtensionSystem::Get(listener_profile)->
    597       extension_service()->process_map();
    598   // If the event is privileged, only send to extension processes. Otherwise,
    599   // it's OK to send to normal renderers (e.g., for content scripts).
    600   if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
    601       !process_map->Contains(extension->id(), process->GetID())) {
    602     return;
    603   }
    604 
    605   // If the event is restricted to a URL, only dispatch if the extension has
    606   // permission for it (or if the event originated from itself).
    607   if (!event->event_url.is_empty() &&
    608       event->event_url.host() != extension->id() &&
    609       !extension->GetActivePermissions()->HasEffectiveAccessToURL(
    610           event->event_url)) {
    611     return;
    612   }
    613 
    614   if (!CanDispatchEventToProfile(listener_profile, extension, event))
    615     return;
    616 
    617   if (!event->will_dispatch_callback.is_null()) {
    618     event->will_dispatch_callback.Run(listener_profile, extension,
    619                                       event->event_args.get());
    620   }
    621 
    622   DispatchExtensionMessage(process, listener_profile, extension->id(),
    623                            event->event_name, event->event_args.get(),
    624                            event->user_gesture, event->filter_info);
    625   IncrementInFlightEvents(listener_profile, extension);
    626 }
    627 
    628 bool EventRouter::CanDispatchEventToProfile(Profile* profile,
    629                                             const Extension* extension,
    630                                             const linked_ptr<Event>& event) {
    631   // Is this event from a different profile than the renderer (ie, an
    632   // incognito tab event sent to a normal process, or vice versa).
    633   bool cross_incognito =
    634       event->restrict_to_profile && profile != event->restrict_to_profile;
    635   if (cross_incognito &&
    636       !ExtensionSystem::Get(profile)->extension_service()->
    637           CanCrossIncognito(extension)) {
    638     return false;
    639   }
    640 
    641   return true;
    642 }
    643 
    644 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
    645     Profile* profile,
    646     const Extension* extension,
    647     const linked_ptr<Event>& event) {
    648   if (!CanDispatchEventToProfile(profile, extension, event))
    649     return false;
    650 
    651   LazyBackgroundTaskQueue* queue =
    652       ExtensionSystem::Get(profile)->lazy_background_task_queue();
    653   if (queue->ShouldEnqueueTask(profile, extension)) {
    654     linked_ptr<Event> dispatched_event(event);
    655 
    656     // If there's a dispatch callback, call it now (rather than dispatch time)
    657     // to avoid lifetime issues. Use a separate copy of the event args, so they
    658     // last until the event is dispatched.
    659     if (!event->will_dispatch_callback.is_null()) {
    660       dispatched_event.reset(event->DeepCopy());
    661       dispatched_event->will_dispatch_callback.Run(
    662           profile, extension, dispatched_event->event_args.get());
    663       // Ensure we don't call it again at dispatch time.
    664       dispatched_event->will_dispatch_callback.Reset();
    665     }
    666 
    667     queue->AddPendingTask(profile, extension->id(),
    668                           base::Bind(&EventRouter::DispatchPendingEvent,
    669                                      base::Unretained(this), dispatched_event));
    670     return true;
    671   }
    672 
    673   return false;
    674 }
    675 
    676 // static
    677 void EventRouter::IncrementInFlightEventsOnUI(
    678     void* profile_id,
    679     const std::string& extension_id) {
    680   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    681   Profile* profile = reinterpret_cast<Profile*>(profile_id);
    682   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
    683     return;
    684   extensions::EventRouter* event_router =
    685       extensions::ExtensionSystem::Get(profile)->event_router();
    686   if (!event_router)
    687     return;
    688   ExtensionService* extension_service =
    689       extensions::ExtensionSystem::Get(profile)->extension_service();
    690   const Extension* extension =
    691       extension_service->extensions()->GetByID(extension_id);
    692   if (!extension)
    693     return;
    694   event_router->IncrementInFlightEvents(profile, extension);
    695 }
    696 
    697 void EventRouter::IncrementInFlightEvents(Profile* profile,
    698                                           const Extension* extension) {
    699   // Only increment in-flight events if the lazy background page is active,
    700   // because that's the only time we'll get an ACK.
    701   if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
    702     ExtensionProcessManager* pm =
    703         ExtensionSystem::Get(profile)->process_manager();
    704     ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
    705     if (host)
    706       pm->IncrementLazyKeepaliveCount(extension);
    707   }
    708 }
    709 
    710 void EventRouter::OnEventAck(Profile* profile,
    711                              const std::string& extension_id) {
    712   ExtensionProcessManager* pm =
    713       ExtensionSystem::Get(profile)->process_manager();
    714   ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
    715   // The event ACK is routed to the background host, so this should never be
    716   // NULL.
    717   CHECK(host);
    718   // TODO(mpcomplete): We should never get this message unless
    719   // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
    720   if (host->extension() &&
    721       BackgroundInfo::HasLazyBackgroundPage(host->extension()))
    722     pm->DecrementLazyKeepaliveCount(host->extension());
    723 }
    724 
    725 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
    726                                        ExtensionHost* host) {
    727   if (!host)
    728     return;
    729 
    730   if (listeners_.HasProcessListener(host->render_process_host(),
    731                                     host->extension()->id())) {
    732     DispatchEventToProcess(host->extension()->id(),
    733                            host->render_process_host(), event);
    734   }
    735 }
    736 
    737 void EventRouter::Observe(int type,
    738                           const content::NotificationSource& source,
    739                           const content::NotificationDetails& details) {
    740   switch (type) {
    741     case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
    742     case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
    743       content::RenderProcessHost* renderer =
    744           content::Source<content::RenderProcessHost>(source).ptr();
    745       // Remove all event listeners associated with this renderer.
    746       listeners_.RemoveListenersForProcess(renderer);
    747       break;
    748     }
    749     case chrome::NOTIFICATION_EXTENSIONS_READY: {
    750       // We're done restarting Chrome after an update.
    751       dispatch_chrome_updated_event_ = false;
    752       break;
    753     }
    754     case chrome::NOTIFICATION_EXTENSION_ENABLED: {
    755       // If the extension has a lazy background page, make sure it gets loaded
    756       // to register the events the extension is interested in.
    757       const Extension* extension =
    758           content::Details<const Extension>(details).ptr();
    759       if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
    760         LazyBackgroundTaskQueue* queue =
    761             ExtensionSystem::Get(profile_)->lazy_background_task_queue();
    762         queue->AddPendingTask(profile_, extension->id(),
    763                               base::Bind(&DoNothing));
    764       }
    765       break;
    766     }
    767     case chrome::NOTIFICATION_EXTENSION_LOADED: {
    768       // Add all registered lazy listeners to our cache.
    769       const Extension* extension =
    770           content::Details<const Extension>(details).ptr();
    771       std::set<std::string> registered_events =
    772           GetRegisteredEvents(extension->id());
    773       listeners_.LoadUnfilteredLazyListeners(extension->id(),
    774                                              registered_events);
    775       const DictionaryValue* filtered_events =
    776           GetFilteredEvents(extension->id());
    777       if (filtered_events)
    778         listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
    779 
    780       if (dispatch_chrome_updated_event_) {
    781         base::MessageLoop::current()->PostTask(FROM_HERE,
    782             base::Bind(&DispatchOnInstalledEvent, profile_, extension->id(),
    783                        Version(), true));
    784       }
    785       break;
    786     }
    787     case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
    788       // Remove all registered lazy listeners from our cache.
    789       UnloadedExtensionInfo* unloaded =
    790           content::Details<UnloadedExtensionInfo>(details).ptr();
    791       listeners_.RemoveLazyListenersForExtension(unloaded->extension->id());
    792       break;
    793     }
    794     case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
    795       // Dispatch the onInstalled event.
    796       const Extension* extension =
    797           content::Details<const InstalledExtensionInfo>(details)->extension;
    798 
    799       // Get the previous version, if this is an upgrade.
    800       ExtensionService* service =
    801           ExtensionSystem::Get(profile_)->extension_service();
    802       const Extension* old = service->GetExtensionById(extension->id(), true);
    803       Version old_version;
    804       if (old)
    805         old_version = *old->version();
    806 
    807       base::MessageLoop::current()->PostTask(FROM_HERE,
    808           base::Bind(&DispatchOnInstalledEvent, profile_, extension->id(),
    809                      old_version, false));
    810       break;
    811     }
    812     default:
    813       NOTREACHED();
    814       return;
    815   }
    816 }
    817 
    818 Event::Event(const std::string& event_name,
    819              scoped_ptr<base::ListValue> event_args)
    820     : event_name(event_name),
    821       event_args(event_args.Pass()),
    822       restrict_to_profile(NULL),
    823       user_gesture(EventRouter::USER_GESTURE_UNKNOWN) {
    824   DCHECK(this->event_args.get());
    825 }
    826 
    827 Event::Event(const std::string& event_name,
    828              scoped_ptr<base::ListValue> event_args,
    829              Profile* restrict_to_profile)
    830     : event_name(event_name),
    831       event_args(event_args.Pass()),
    832       restrict_to_profile(restrict_to_profile),
    833       user_gesture(EventRouter::USER_GESTURE_UNKNOWN) {
    834   DCHECK(this->event_args.get());
    835 }
    836 
    837 Event::Event(const std::string& event_name,
    838              scoped_ptr<ListValue> event_args,
    839              Profile* restrict_to_profile,
    840              const GURL& event_url,
    841              EventRouter::UserGestureState user_gesture,
    842              const EventFilteringInfo& filter_info)
    843     : event_name(event_name),
    844       event_args(event_args.Pass()),
    845       restrict_to_profile(restrict_to_profile),
    846       event_url(event_url),
    847       user_gesture(user_gesture),
    848       filter_info(filter_info) {
    849   DCHECK(this->event_args.get());
    850 }
    851 
    852 Event::~Event() {}
    853 
    854 Event* Event::DeepCopy() {
    855   Event* copy = new Event(event_name,
    856                           scoped_ptr<base::ListValue>(event_args->DeepCopy()),
    857                           restrict_to_profile,
    858                           event_url,
    859                           user_gesture,
    860                           filter_info);
    861   copy->will_dispatch_callback = will_dispatch_callback;
    862   return copy;
    863 }
    864 
    865 EventListenerInfo::EventListenerInfo(const std::string& event_name,
    866                                      const std::string& extension_id)
    867     : event_name(event_name),
    868       extension_id(extension_id) {}
    869 
    870 }  // namespace extensions
    871