1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be
3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file.
4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_event_router.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/values.h"
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_devtools_manager.h"
9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_processes_api.h"
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_processes_api_constants.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_tabs_module.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_webrequest_api.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/extensions/extension.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension_messages.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/child_process_security_policy.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
21731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace {
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst char kDispatchEvent[] = "Event.dispatchJSON";
24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic void DispatchEvent(RenderProcessHost* renderer,
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          const std::string& extension_id,
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          const std::string& event_name,
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          const std::string& event_args,
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          const GURL& event_url) {
30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ListValue args;
31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  args.Set(0, Value::CreateStringValue(event_name));
32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  args.Set(1, Value::CreateStringValue(event_args));
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  renderer->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL,
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      extension_id, kDispatchEvent, args, event_url));
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic void NotifyEventListenerRemovedOnIOThread(
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ProfileId profile_id,
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& extension_id,
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& sub_event_name) {
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      profile_id, extension_id, sub_event_name);
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstruct ExtensionEventRouter::EventListener {
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  RenderProcessHost* process;
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string extension_id;
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  explicit EventListener(RenderProcessHost* process,
52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                         const std::string& extension_id)
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      : process(process), extension_id(extension_id) {}
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool operator<(const EventListener& that) const {
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (process < that.process)
57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (process == that.process && extension_id < that.extension_id)
59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
65513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ExtensionEventRouter::CanCrossIncognito(Profile* profile,
66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                             const std::string& extension_id) {
67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const Extension* extension =
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      profile->GetExtensionService()->GetExtensionById(extension_id, false);
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return CanCrossIncognito(profile, extension);
70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
73513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ExtensionEventRouter::CanCrossIncognito(Profile* profile,
74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                             const Extension* extension) {
75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // We allow the extension to see events and data from another profile iff it
76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // uses "spanning" behavior and it has incognito access. "split" mode
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // extensions only see events for a matching profile.
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (profile->GetExtensionService()->IsIncognitoEnabled(extension->id()) &&
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       !extension->incognito_split_mode());
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
83731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionEventRouter::ExtensionEventRouter(Profile* profile)
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : profile_(profile),
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      extension_devtools_manager_(profile->GetExtensionDevToolsManager()) {
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  registrar_.Add(this, NotificationType::RENDERER_PROCESS_TERMINATED,
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                 NotificationService::AllSources());
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSED,
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                 NotificationService::AllSources());
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
92731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionEventRouter::~ExtensionEventRouter() {
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::AddEventListener(
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name,
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderProcessHost* process,
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id) {
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EventListener listener(process, extension_id);
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name;
101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  listeners_[event_name].insert(listener);
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (extension_devtools_manager_.get())
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    extension_devtools_manager_->AddEventListener(event_name, process->id());
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // We lazily tell the TaskManager to start updating when listeners to the
107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // processes.onUpdated event arrive.
108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0)
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ExtensionProcessesEventRouter::GetInstance()->ListenerAdded();
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::RemoveEventListener(
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name,
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderProcessHost* process,
115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id) {
116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EventListener listener(process, extension_id);
117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK_EQ(listeners_[event_name].count(listener), 1u) <<
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      " PID=" << process->id() << " extension=" << extension_id <<
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      " event=" << event_name;
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  listeners_[event_name].erase(listener);
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Note: extension_id may point to data in the now-deleted listeners_ object.
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Do not use.
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (extension_devtools_manager_.get())
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    extension_devtools_manager_->RemoveEventListener(event_name, process->id());
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // If a processes.onUpdated event listener is removed (or a process with one
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // exits), then we let the TaskManager know that it has one fewer listener.
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0)
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved();
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::IO, FROM_HERE,
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableFunction(
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &NotifyEventListenerRemovedOnIOThread,
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          profile_->GetRuntimeId(), listener.extension_id, event_name));
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionEventRouter::HasEventListener(const std::string& event_name) {
140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return (listeners_.find(event_name) != listeners_.end() &&
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          !listeners_[event_name].empty());
142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionEventRouter::ExtensionHasEventListener(
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id, const std::string& event_name) {
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ListenerMap::iterator it = listeners_.find(event_name);
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (it == listeners_.end())
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::set<EventListener>& listeners = it->second;
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (std::set<EventListener>::iterator listener = listeners.begin();
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       listener != listeners.end(); ++listener) {
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (listener->extension_id == extension_id)
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return false;
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::DispatchEventToRenderers(
160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name, const std::string& event_args,
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Profile* restrict_to_profile, const GURL& event_url) {
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DispatchEventImpl("", event_name, event_args, restrict_to_profile, event_url);
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::DispatchEventToExtension(
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id,
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name, const std::string& event_args,
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Profile* restrict_to_profile, const GURL& event_url) {
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!extension_id.empty());
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DispatchEventImpl(extension_id, event_name, event_args, restrict_to_profile,
171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    event_url);
172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::DispatchEventImpl(
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id,
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name, const std::string& event_args,
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Profile* restrict_to_profile, const GURL& event_url) {
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!profile_)
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // We don't expect to get events from a completely different profile.
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!restrict_to_profile || profile_->IsSameProfile(restrict_to_profile));
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ListenerMap::iterator it = listeners_.find(event_name);
185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (it == listeners_.end())
186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::set<EventListener>& listeners = it->second;
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ExtensionService* service = profile_->GetExtensionService();
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Send the event only to renderers that are listening for it.
192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (std::set<EventListener>::iterator listener = listeners.begin();
193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       listener != listeners.end(); ++listener) {
194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!ChildProcessSecurityPolicy::GetInstance()->
195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            HasExtensionBindings(listener->process->id())) {
196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Don't send browser-level events to unprivileged processes.
197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      continue;
198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!extension_id.empty() && extension_id != listener->extension_id)
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      continue;
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Is this event from a different profile than the renderer (ie, an
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // incognito tab event sent to a normal process, or vice versa).
205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool cross_incognito = restrict_to_profile &&
206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        listener->process->profile() != restrict_to_profile;
207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const Extension* extension = service->GetExtensionById(
208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        listener->extension_id, false);
209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (cross_incognito && !service->CanCrossIncognito(extension))
210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      continue;
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DispatchEvent(listener->process, listener->extension_id,
213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                  event_name, event_args, event_url);
214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::Observe(NotificationType type,
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   const NotificationSource& source,
219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   const NotificationDetails& details) {
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  switch (type.value) {
221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case NotificationType::RENDERER_PROCESS_TERMINATED:
222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case NotificationType::RENDERER_PROCESS_CLOSED: {
223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr();
224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Remove all event listeners associated with this renderer
225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      for (ListenerMap::iterator it = listeners_.begin();
226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick           it != listeners_.end(); ) {
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        ListenerMap::iterator current_it = it++;
228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        for (std::set<EventListener>::iterator jt = current_it->second.begin();
229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick             jt != current_it->second.end(); ) {
230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          std::set<EventListener>::iterator current_jt = jt++;
231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          if (current_jt->process == renderer) {
232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            RemoveEventListener(current_it->first,
233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                current_jt->process,
234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                current_jt->extension_id);
235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          }
236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        }
237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      break;
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    default:
241731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      NOTREACHED();
242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return;
243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
245