extension_event_router.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 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/child_process_security_policy.h"
9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_devtools_manager.h"
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_processes_api.h"
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_processes_api_constants.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_tabs_module.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_webrequest_api.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/renderer_host/render_process_host.h"
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/extensions/extension.h"
18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/notification_service.h"
19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/render_messages.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));
33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  renderer->Send(new ViewMsg_ExtensionMessageInvoke(MSG_ROUTING_CONTROL,
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      extension_id, kDispatchEvent, args, event_url));
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstruct ExtensionEventRouter::EventListener {
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  RenderProcessHost* process;
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string extension_id;
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  explicit EventListener(RenderProcessHost* process,
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                         const std::string& extension_id)
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      : process(process), extension_id(extension_id) {}
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool operator<(const EventListener& that) const {
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (process < that.process)
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (process == that.process && extension_id < that.extension_id)
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
57513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ExtensionEventRouter::CanCrossIncognito(Profile* profile,
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                             const std::string& extension_id) {
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const Extension* extension =
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      profile->GetExtensionService()->GetExtensionById(extension_id, false);
61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return CanCrossIncognito(profile, extension);
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
65513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ExtensionEventRouter::CanCrossIncognito(Profile* profile,
66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                             const Extension* extension) {
67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // We allow the extension to see events and data from another profile iff it
68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // uses "spanning" behavior and it has incognito access. "split" mode
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // extensions only see events for a matching profile.
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return (profile->GetExtensionService()->IsIncognitoEnabled(extension) &&
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          !extension->incognito_split_mode());
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
74731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionEventRouter::ExtensionEventRouter(Profile* profile)
75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : profile_(profile),
76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      extension_devtools_manager_(profile->GetExtensionDevToolsManager()) {
77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  registrar_.Add(this, NotificationType::RENDERER_PROCESS_TERMINATED,
78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                 NotificationService::AllSources());
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSED,
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                 NotificationService::AllSources());
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
83731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionEventRouter::~ExtensionEventRouter() {
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::AddEventListener(
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name,
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderProcessHost* process,
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id) {
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EventListener listener(process, extension_id);
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name;
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  listeners_[event_name].insert(listener);
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (extension_devtools_manager_.get())
95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    extension_devtools_manager_->AddEventListener(event_name, process->id());
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // We lazily tell the TaskManager to start updating when listeners to the
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // processes.onUpdated event arrive.
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0)
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ExtensionProcessesEventRouter::GetInstance()->ListenerAdded();
101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::RemoveEventListener(
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name,
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderProcessHost* process,
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id) {
107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EventListener listener(process, extension_id);
108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK_EQ(listeners_[event_name].count(listener), 1u) <<
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      " PID=" << process->id() << " extension=" << extension_id <<
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      " event=" << event_name;
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  listeners_[event_name].erase(listener);
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Note: extension_id may point to data in the now-deleted listeners_ object.
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Do not use.
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (extension_devtools_manager_.get())
116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    extension_devtools_manager_->RemoveEventListener(event_name, process->id());
117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // If a processes.onUpdated event listener is removed (or a process with one
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // exits), then we let the TaskManager know that it has one fewer listener.
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0)
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved();
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ExtensionWebRequestEventRouter::RemoveEventListenerOnUIThread(
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      listener.extension_id, event_name);
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionEventRouter::HasEventListener(const std::string& event_name) {
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return (listeners_.find(event_name) != listeners_.end() &&
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          !listeners_[event_name].empty());
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ExtensionEventRouter::ExtensionHasEventListener(
133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id, const std::string& event_name) {
134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ListenerMap::iterator it = listeners_.find(event_name);
135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (it == listeners_.end())
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::set<EventListener>& listeners = it->second;
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (std::set<EventListener>::iterator listener = listeners.begin();
140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       listener != listeners.end(); ++listener) {
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (listener->extension_id == extension_id)
142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return true;
143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return false;
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::DispatchEventToRenderers(
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name, const std::string& event_args,
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Profile* restrict_to_profile, const GURL& event_url) {
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DispatchEventImpl("", event_name, event_args, restrict_to_profile, event_url);
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::DispatchEventToExtension(
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id,
155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name, const std::string& event_args,
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Profile* restrict_to_profile, const GURL& event_url) {
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!extension_id.empty());
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DispatchEventImpl(extension_id, event_name, event_args, restrict_to_profile,
159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    event_url);
160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::DispatchEventImpl(
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& extension_id,
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& event_name, const std::string& event_args,
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Profile* restrict_to_profile, const GURL& event_url) {
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!profile_)
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // We don't expect to get events from a completely different profile.
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!restrict_to_profile || profile_->IsSameProfile(restrict_to_profile));
171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ListenerMap::iterator it = listeners_.find(event_name);
173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (it == listeners_.end())
174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::set<EventListener>& listeners = it->second;
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ExtensionService* service = profile_->GetExtensionService();
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Send the event only to renderers that are listening for it.
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (std::set<EventListener>::iterator listener = listeners.begin();
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick       listener != listeners.end(); ++listener) {
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!ChildProcessSecurityPolicy::GetInstance()->
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            HasExtensionBindings(listener->process->id())) {
184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Don't send browser-level events to unprivileged processes.
185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      continue;
186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (!extension_id.empty() && extension_id != listener->extension_id)
189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      continue;
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Is this event from a different profile than the renderer (ie, an
192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // incognito tab event sent to a normal process, or vice versa).
193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool cross_incognito = restrict_to_profile &&
194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        listener->process->profile() != restrict_to_profile;
195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const Extension* extension = service->GetExtensionById(
196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        listener->extension_id, false);
197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (cross_incognito && !service->CanCrossIncognito(extension))
198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      continue;
199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DispatchEvent(listener->process, listener->extension_id,
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                  event_name, event_args, event_url);
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ExtensionEventRouter::Observe(NotificationType type,
206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   const NotificationSource& source,
207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   const NotificationDetails& details) {
208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  switch (type.value) {
209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case NotificationType::RENDERER_PROCESS_TERMINATED:
210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case NotificationType::RENDERER_PROCESS_CLOSED: {
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr();
212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Remove all event listeners associated with this renderer
213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      for (ListenerMap::iterator it = listeners_.begin();
214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick           it != listeners_.end(); ) {
215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        ListenerMap::iterator current_it = it++;
216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        for (std::set<EventListener>::iterator jt = current_it->second.begin();
217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick             jt != current_it->second.end(); ) {
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          std::set<EventListener>::iterator current_jt = jt++;
219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          if (current_jt->process == renderer) {
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            RemoveEventListener(current_it->first,
221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                current_jt->process,
222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                current_jt->extension_id);
223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          }
224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        }
225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      break;
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    default:
229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      NOTREACHED();
230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return;
231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
233