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