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