15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/profiler/scoped_profile.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/child_process_security_policy.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/api_activity_monitor.h"
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/browser/lazy_background_task_queue.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_manager.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_map.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h"
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h"
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/extension_urls.h"
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h"
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/incognito_info.h"
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::DictionaryValue;
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::ListValue;
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using content::BrowserContext;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void DoNothing(ExtensionHost* host) {}
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// A dictionary of event names to lists of filters that this extension has
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// registered from its lazy background page.
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kFilteredEvents[] = "filtered_events";
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Sends a notification about an event to the API activity monitor on the
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// UI thread. Can be called from any thread.
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotifyApiEventDispatched(void* browser_context_id,
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              const std::string& extension_id,
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              const std::string& event_name,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              scoped_ptr<ListValue> args) {
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The ApiActivityMonitor can only be accessed from the UI thread.
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostTask(
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::UI,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&NotifyApiEventDispatched,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   browser_context_id,
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   extension_id,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   event_name,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   base::Passed(&args)));
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Notify the ApiActivityMonitor about the event dispatch.
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserContext* context = static_cast<BrowserContext*>(browser_context_id);
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ApiActivityMonitor* monitor =
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context);
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (monitor)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    monitor->OnApiEventDispatched(extension_id, event_name, args.Pass());
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char EventRouter::kRegisteredEvents[] = "events";
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EventRouter::ListenerProcess {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderProcessHost* process;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerProcess(content::RenderProcessHost* process,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::string& extension_id)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : process(process), extension_id(extension_id) {}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator<(const ListenerProcess& that) const {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (process < that.process)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (process == that.process && extension_id < that.extension_id)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender,
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                           void* browser_context_id,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::string& extension_id,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::string& event_name,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           ListValue* event_args,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           UserGestureState user_gesture,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const EventFilteringInfo& info) {
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyApiEventDispatched(browser_context_id,
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           extension_id,
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           event_name,
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           make_scoped_ptr(event_args->DeepCopy()));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  args.Set(0, new base::StringValue(event_name));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Set(1, event_args);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Set(2, info.AsValue().release());
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ipc_sender->Send(new ExtensionMsg_MessageInvoke(
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      MSG_ROUTING_CONTROL,
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      extension_id,
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kEventBindings,
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      "dispatchEvent",
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      args,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_gesture == USER_GESTURE_ENABLED));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DispatchExtensionMessage does _not_ take ownership of event_args, so we
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // must ensure that the destruction of args does not attempt to free it.
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> removed_event_args;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Remove(1, &removed_event_args);
1303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  ignore_result(removed_event_args.release());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
134effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochEventRouter* EventRouter::Get(content::BrowserContext* browser_context) {
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return ExtensionSystem::Get(browser_context)->event_router();
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t slash_sep = full_event_name.find('/');
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return full_event_name.substr(0, slash_sep);
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                void* browser_context_id,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& extension_id,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& event_name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                scoped_ptr<ListValue> event_args,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                UserGestureState user_gesture,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const EventFilteringInfo& info) {
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DispatchExtensionMessage(ipc_sender,
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           browser_context_id,
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           extension_id,
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           event_name,
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           event_args.get(),
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           user_gesture,
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           info);
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BrowserThread::PostTask(
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      BrowserThread::UI,
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE,
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  browser_context_id,
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  extension_id));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)EventRouter::EventRouter(BrowserContext* browser_context,
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         ExtensionPrefs* extension_prefs)
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : browser_context_(browser_context),
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_prefs_(extension_prefs),
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_observer_(this),
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      listeners_(this) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  registrar_.Add(this,
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_ENABLED,
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 content::Source<BrowserContext>(browser_context_));
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventRouter::~EventRouter() {}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::AddEventListener(const std::string& event_name,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   content::RenderProcessHost* process,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& extension_id) {
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.AddListener(EventListener::ForExtension(
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name, extension_id, process, scoped_ptr<DictionaryValue>()));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RemoveEventListener(const std::string& event_name,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      content::RenderProcessHost* process,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& extension_id) {
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<EventListener> listener = EventListener::ForExtension(
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name, extension_id, process, scoped_ptr<DictionaryValue>());
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.RemoveListener(listener.get());
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EventRouter::AddEventListenerForURL(const std::string& event_name,
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         content::RenderProcessHost* process,
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         const GURL& listener_url) {
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.AddListener(EventListener::ForURL(
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name, listener_url, process, scoped_ptr<DictionaryValue>()));
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EventRouter::RemoveEventListenerForURL(const std::string& event_name,
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            content::RenderProcessHost* process,
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            const GURL& listener_url) {
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<EventListener> listener = EventListener::ForURL(
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name, listener_url, process, scoped_ptr<DictionaryValue>());
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.RemoveListener(listener.get());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RegisterObserver(Observer* observer,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& event_name) {
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Observing sub-event names like "foo.onBar/123" is not allowed.
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(event_name.find('/') == std::string::npos);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_[event_name] = observer;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::UnregisterObserver(Observer* observer) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<ObserverMap::iterator> iters_to_remove;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ObserverMap::iterator iter = observers_.begin();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != observers_.end(); ++iter) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter->second == observer)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iters_to_remove.push_back(iter);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < iters_to_remove.size(); ++i)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.erase(iters_to_remove[i]);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::OnListenerAdded(const EventListener* listener) {
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const EventListenerInfo details(listener->event_name(),
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  listener->extension_id(),
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  listener->listener_url(),
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  listener->GetBrowserContext());
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string base_event_name = GetBaseEventName(listener->event_name());
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObserverMap::iterator observer = observers_.find(base_event_name);
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (observer != observers_.end()) {
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(vadimt): Remove ScopedProfile below once crbug.com/417106 is fixed.
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    tracked_objects::ScopedProfile tracking_profile(
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE_WITH_EXPLICIT_FUNCTION(
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "EventRouter_OnListenerAdded_ObserverCall"));
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    observer->second->OnListenerAdded(details);
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::OnListenerRemoved(const EventListener* listener) {
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const EventListenerInfo details(listener->event_name(),
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  listener->extension_id(),
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  listener->listener_url(),
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  listener->GetBrowserContext());
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string base_event_name = GetBaseEventName(listener->event_name());
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObserverMap::iterator observer = observers_.find(base_event_name);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observer != observers_.end())
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    observer->second->OnListenerRemoved(details);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::AddLazyEventListener(const std::string& event_name,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& extension_id) {
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool is_new = listeners_.AddListener(EventListener::ForExtension(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_new) {
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::set<std::string> events = GetRegisteredEvents(extension_id);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool prefs_is_new = events.insert(event_name).second;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (prefs_is_new)
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SetRegisteredEvents(extension_id, events);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RemoveLazyEventListener(const std::string& event_name,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::string& extension_id) {
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<EventListener> listener = EventListener::ForExtension(
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name, extension_id, NULL, scoped_ptr<DictionaryValue>());
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool did_exist = listeners_.RemoveListener(listener.get());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (did_exist) {
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::set<std::string> events = GetRegisteredEvents(extension_id);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool prefs_did_exist = events.erase(event_name) > 0;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(prefs_did_exist);
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetRegisteredEvents(extension_id, events);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::AddFilteredEventListener(const std::string& event_name,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           content::RenderProcessHost* process,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::string& extension_id,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const base::DictionaryValue& filter,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool add_lazy_listener) {
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.AddListener(EventListener::ForExtension(
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name,
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_id,
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      process,
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_ptr<DictionaryValue>(filter.DeepCopy())));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (add_lazy_listener) {
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool added = listeners_.AddListener(EventListener::ForExtension(
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        event_name,
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extension_id,
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NULL,
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        scoped_ptr<DictionaryValue>(filter.DeepCopy())));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (added)
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      AddFilterToEvent(event_name, extension_id, &filter);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RemoveFilteredEventListener(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderProcessHost* process,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& filter,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool remove_lazy_listener) {
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<EventListener> listener = EventListener::ForExtension(
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_name,
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_id,
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      process,
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_ptr<DictionaryValue>(filter.DeepCopy()));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.RemoveListener(listener.get());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remove_lazy_listener) {
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    listener->MakeLazy();
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool removed = listeners_.RemoveListener(listener.get());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (removed)
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RemoveFilterFromEvent(event_name, extension_id, &filter);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::HasEventListener(const std::string& event_name) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return listeners_.HasListenerForEvent(event_name);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::ExtensionHasEventListener(const std::string& extension_id,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const std::string& event_name) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return listeners_.HasListenerForExtension(extension_id, event_name);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& extension_id,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& event_name) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::const_iterator it = listener_map.find(event_name);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == listener_map.end())
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::set<ListenerProcess>& listeners = it->second;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extension_id.empty())
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !listeners.empty();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       listener != listeners.end(); ++listener) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (listener->extension_id == extension_id)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::set<std::string> EventRouter::GetRegisteredEvents(
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& extension_id) {
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::set<std::string> events;
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const ListValue* events_value = NULL;
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!extension_prefs_ ||
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      !extension_prefs_->ReadPrefAsList(
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           extension_id, kRegisteredEvents, &events_value)) {
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return events;
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < events_value->GetSize(); ++i) {
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string event;
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (events_value->GetString(i, &event))
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      events.insert(event);
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return events;
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::SetRegisteredEvents(const std::string& extension_id,
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      const std::set<std::string>& events) {
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ListValue* events_value = new ListValue;
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::set<std::string>::const_iterator iter = events.begin();
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       iter != events.end(); ++iter) {
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    events_value->Append(new base::StringValue(*iter));
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extension_prefs_->UpdateExtensionPref(
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_id, kRegisteredEvents, events_value);
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::AddFilterToEvent(const std::string& event_name,
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   const std::string& extension_id,
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   const DictionaryValue* filter) {
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ExtensionPrefs::ScopedDictionaryUpdate update(
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_prefs_, extension_id, kFilteredEvents);
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DictionaryValue* filtered_events = update.Get();
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!filtered_events)
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    filtered_events = update.Create();
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ListValue* filter_list = NULL;
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!filtered_events->GetList(event_name, &filter_list)) {
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    filter_list = new ListValue;
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    filtered_events->SetWithoutPathExpansion(event_name, filter_list);
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  filter_list->Append(filter->DeepCopy());
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                        const std::string& extension_id,
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                        const DictionaryValue* filter) {
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ExtensionPrefs::ScopedDictionaryUpdate update(
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_prefs_, extension_id, kFilteredEvents);
41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DictionaryValue* filtered_events = update.Get();
41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ListValue* filter_list = NULL;
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!filtered_events ||
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < filter_list->GetSize(); i++) {
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DictionaryValue* filter = NULL;
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CHECK(filter_list->GetDictionary(i, &filter));
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (filter->Equals(filter)) {
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      filter_list->Remove(i, NULL);
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const DictionaryValue* EventRouter::GetFilteredEvents(
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& extension_id) {
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const DictionaryValue* events = NULL;
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extension_prefs_->ReadPrefAsDictionary(
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      extension_id, kFilteredEvents, &events);
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return events;
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventRouter::BroadcastEvent(scoped_ptr<Event> event) {
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DispatchEventImpl(std::string(), linked_ptr<Event>(event.release()));
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEventToExtension(const std::string& extension_id,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           scoped_ptr<Event> event) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!extension_id.empty());
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DispatchEventImpl(extension_id, linked_ptr<Event>(event.release()));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                scoped_ptr<Event> event) {
452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(!extension_id.empty());
453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::string event_name = event->event_name;
454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool has_listener = ExtensionHasEventListener(extension_id, event_name);
455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!has_listener)
456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    AddLazyEventListener(event_name, extension_id);
457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DispatchEventToExtension(extension_id, event.Pass());
458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!has_listener)
459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    RemoveLazyEventListener(event_name, extension_id);
460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const linked_ptr<Event>& event) {
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We don't expect to get events from a completely different browser context.
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!event->restrict_to_browser_context ||
466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         ExtensionsBrowserClient::Get()->IsSameContext(
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             browser_context_, event->restrict_to_browser_context));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<const EventListener*> listeners(
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listeners_.GetEventListeners(*event));
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<EventDispatchIdentifier> already_dispatched;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We dispatch events for lazy background pages first because attempting to do
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so will cause those that are being suspended to cancel that suspension.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As canceling a suspension entails sending an event to the affected
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // background page, and as that event needs to be delivered before we dispatch
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the event we are dispatching here, we dispatch to the lazy listeners here
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<const EventListener*>::iterator it = listeners.begin();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners.end(); it++) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventListener* listener = *it;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (restrict_to_extension_id.empty() ||
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        restrict_to_extension_id == listener->extension_id()) {
485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (listener->IsLazy()) {
486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        DispatchLazyEvent(listener->extension_id(), event, &already_dispatched);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<const EventListener*>::iterator it = listeners.begin();
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners.end(); it++) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventListener* listener = *it;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (restrict_to_extension_id.empty() ||
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        restrict_to_extension_id == listener->extension_id()) {
496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (listener->process()) {
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(),
498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                            listener->extension_id());
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ContainsKey(already_dispatched, dispatch_id)) {
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          DispatchEventToProcess(listener->extension_id(),
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 listener->listener_url(),
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 listener->process(),
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 event);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchLazyEvent(
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const linked_ptr<Event>& event,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<EventDispatchIdentifier>* already_dispatched) {
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Check both the original and the incognito browser context to see if we
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should load a lazy bg page to handle the event. The latter case
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // occurs in the case of split-mode extensions.
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Extension* extension =
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          extension_id);
520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!extension)
521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (MaybeLoadLazyBackgroundPageToDispatchEvent(
524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          browser_context_, extension, event)) {
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    already_dispatched->insert(std::make_pair(browser_context_, extension_id));
526f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
528f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (browser_client->HasOffTheRecordContext(browser_context_) &&
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      IncognitoInfo::IsSplitMode(extension)) {
531f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserContext* incognito_context =
532f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        browser_client->GetOffTheRecordContext(browser_context_);
533f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (MaybeLoadLazyBackgroundPageToDispatchEvent(
534f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            incognito_context, extension, event)) {
535f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      already_dispatched->insert(
536f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          std::make_pair(incognito_context, extension_id));
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEventToProcess(const std::string& extension_id,
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         const GURL& listener_url,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         content::RenderProcessHost* process,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const linked_ptr<Event>& event) {
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BrowserContext* listener_context = process->GetBrowserContext();
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ProcessMap* process_map = ProcessMap::Get(listener_context);
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // TODO(kalman): Convert this method to use
5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // ProcessMap::GetMostLikelyContextType.
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Extension* extension =
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          extension_id);
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // NOTE: |extension| being NULL does not necessarily imply that this event
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // shouldn't be dispatched. Events can be dispatched to WebUI as well.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!extension && !extension_id.empty()) {
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Trying to dispatch an event to an extension that doesn't exist. The
5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // extension could have been removed, but we do not unregister it until the
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // extension process is unloaded.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (extension) {
5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Dispatching event to an extension.
5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // If the event is privileged, only send to extension processes. Otherwise,
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // it's OK to send to normal renderers (e.g., for content scripts).
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!process_map->Contains(extension->id(), process->GetID()) &&
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        !ExtensionAPI::GetSharedInstance()->IsAvailableInUntrustedContext(
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            event->event_name, extension)) {
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // If the event is restricted to a URL, only dispatch if the extension has
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // permission for it (or if the event originated from itself).
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!event->event_url.is_empty() &&
5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        event->event_url.host() != extension->id() &&
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        !extension->permissions_data()
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             ->active_permissions()
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             ->HasEffectiveAccessToURL(event->event_url)) {
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) {
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else if (content::ChildProcessSecurityPolicy::GetInstance()
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 ->HasWebUIBindings(process->GetID())) {
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Dispatching event to WebUI.
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!ExtensionAPI::GetSharedInstance()->IsAvailableToWebUI(
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            event->event_name, listener_url)) {
5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Dispatching event to a webpage - however, all such events (e.g.
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // messaging) don't go through EventRouter so this should be impossible.
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NOTREACHED();
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!event->will_dispatch_callback.is_null()) {
6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    event->will_dispatch_callback.Run(
6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        listener_context, extension, event->event_args.get());
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DispatchExtensionMessage(process,
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           listener_context,
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           extension_id,
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           event->event_name,
6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           event->event_args.get(),
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           event->user_gesture,
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           event->filter_info);
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (extension)
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IncrementInFlightEvents(listener_context, extension);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool EventRouter::CanDispatchEventToBrowserContext(
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserContext* context,
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const Extension* extension,
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const linked_ptr<Event>& event) {
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Is this event from a different browser context than the renderer (ie, an
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // incognito tab event sent to a normal process, or vice versa).
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool cross_incognito = event->restrict_to_browser_context &&
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         context != event->restrict_to_browser_context;
626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!cross_incognito)
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extension, context);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserContext* context,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const linked_ptr<Event>& event) {
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!CanDispatchEventToBrowserContext(context, extension, event))
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      context)->lazy_background_task_queue();
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (queue->ShouldEnqueueTask(context, extension)) {
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    linked_ptr<Event> dispatched_event(event);
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If there's a dispatch callback, call it now (rather than dispatch time)
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to avoid lifetime issues. Use a separate copy of the event args, so they
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // last until the event is dispatched.
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!event->will_dispatch_callback.is_null()) {
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dispatched_event.reset(event->DeepCopy());
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dispatched_event->will_dispatch_callback.Run(
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          context, extension, dispatched_event->event_args.get());
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Ensure we don't call it again at dispatch time.
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dispatched_event->will_dispatch_callback.Reset();
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    queue->AddPendingTask(context, extension->id(),
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::Bind(&EventRouter::DispatchPendingEvent,
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     base::Unretained(this), dispatched_event));
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
66590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::IncrementInFlightEventsOnUI(
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    void* browser_context_id,
66790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& extension_id) {
668effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserContext* browser_context =
670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      reinterpret_cast<BrowserContext*>(browser_context_id);
671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
6727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
6730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(browser_context);
67490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!event_router)
67590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
67690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const Extension* extension =
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          extension_id);
67990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!extension)
68090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  event_router->IncrementInFlightEvents(browser_context, extension);
68290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
68390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EventRouter::IncrementInFlightEvents(BrowserContext* context,
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const Extension* extension) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only increment in-flight events if the lazy background page is active,
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because that's the only time we'll get an ACK.
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (host)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pm->IncrementLazyKeepaliveCount(extension);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EventRouter::OnEventAck(BrowserContext* context,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const std::string& extension_id) {
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessManager* pm = ExtensionSystem::Get(context)->process_manager();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The event ACK is routed to the background host, so this should never be
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NULL.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(host);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mpcomplete): We should never get this message unless
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (host->extension() &&
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BackgroundInfo::HasLazyBackgroundPage(host->extension()))
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pm->DecrementLazyKeepaliveCount(host->extension());
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ExtensionHost* host) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!host)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners_.HasProcessListener(host->render_process_host(),
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    host->extension()->id())) {
7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // URL events cannot be lazy therefore can't be pending, hence the GURL().
7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DispatchEventToProcess(
7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        host->extension()->id(), GURL(), host->render_process_host(), event);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::Observe(int type,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const content::NotificationSource& source,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const content::NotificationDetails& details) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::RenderProcessHost* renderer =
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Source<content::RenderProcessHost>(source).ptr();
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Remove all event listeners associated with this renderer.
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listeners_.RemoveListenersForProcess(renderer);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_ENABLED: {
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the extension has a lazy background page, make sure it gets loaded
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // to register the events the extension is interested in.
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const Extension* extension =
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          content::Details<const Extension>(details).ptr();
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        LazyBackgroundTaskQueue* queue = ExtensionSystem::Get(
742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            browser_context_)->lazy_background_task_queue();
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        queue->AddPendingTask(browser_context_, extension->id(),
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              base::Bind(&DoNothing));
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EventRouter::OnExtensionLoaded(content::BrowserContext* browser_context,
7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    const Extension* extension) {
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Add all registered lazy listeners to our cache.
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::set<std::string> registered_events =
7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetRegisteredEvents(extension->id());
7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.LoadUnfilteredLazyListeners(extension->id(), registered_events);
7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const DictionaryValue* filtered_events = GetFilteredEvents(extension->id());
7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (filtered_events)
7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EventRouter::OnExtensionUnloaded(content::BrowserContext* browser_context,
7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      const Extension* extension,
7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      UnloadedExtensionInfo::Reason reason) {
7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Remove all registered lazy listeners from our cache.
7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  listeners_.RemoveLazyListenersForExtension(extension->id());
7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Event::Event(const std::string& event_name,
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             scoped_ptr<base::ListValue> event_args)
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : event_name(event_name),
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event_args(event_args.Pass()),
775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      restrict_to_browser_context(NULL),
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      user_gesture(EventRouter::USER_GESTURE_UNKNOWN) {
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(this->event_args.get());
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Event::Event(const std::string& event_name,
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             scoped_ptr<base::ListValue> event_args,
782f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             BrowserContext* restrict_to_browser_context)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : event_name(event_name),
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_args(event_args.Pass()),
785f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      restrict_to_browser_context(restrict_to_browser_context),
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      user_gesture(EventRouter::USER_GESTURE_UNKNOWN) {
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(this->event_args.get());
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Event::Event(const std::string& event_name,
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             scoped_ptr<ListValue> event_args,
792f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             BrowserContext* restrict_to_browser_context,
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             const GURL& event_url,
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             EventRouter::UserGestureState user_gesture,
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             const EventFilteringInfo& filter_info)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : event_name(event_name),
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_args(event_args.Pass()),
798f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      restrict_to_browser_context(restrict_to_browser_context),
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event_url(event_url),
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_gesture(user_gesture),
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      filter_info(filter_info) {
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(this->event_args.get());
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Event::~Event() {}
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Event* Event::DeepCopy() {
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Event* copy = new Event(event_name,
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_ptr<base::ListValue>(event_args->DeepCopy()),
810f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          restrict_to_browser_context,
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          event_url,
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          user_gesture,
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          filter_info);
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  copy->will_dispatch_callback = will_dispatch_callback;
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return copy;
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventListenerInfo::EventListenerInfo(const std::string& event_name,
819f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     const std::string& extension_id,
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     const GURL& listener_url,
821f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     content::BrowserContext* browser_context)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : event_name(event_name),
823f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extension_id(extension_id),
8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      listener_url(listener_url),
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      browser_context(browser_context) {
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
827f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
829