1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/nacl/browser/nacl_broker_service_win.h" 6 7 #include "components/nacl/browser/nacl_process_host.h" 8 #include "components/nacl/common/nacl_process_type.h" 9 #include "content/public/browser/browser_child_process_host_iterator.h" 10 11 using content::BrowserChildProcessHostIterator; 12 13 namespace nacl { 14 15 NaClBrokerService* NaClBrokerService::GetInstance() { 16 return Singleton<NaClBrokerService>::get(); 17 } 18 19 NaClBrokerService::NaClBrokerService() 20 : loaders_running_(0) { 21 } 22 23 bool NaClBrokerService::StartBroker() { 24 NaClBrokerHost* broker_host = new NaClBrokerHost; 25 if (!broker_host->Init()) { 26 delete broker_host; 27 return false; 28 } 29 return true; 30 } 31 32 bool NaClBrokerService::LaunchLoader( 33 base::WeakPtr<nacl::NaClProcessHost> nacl_process_host, 34 const std::string& loader_channel_id) { 35 // Add task to the list 36 pending_launches_[loader_channel_id] = nacl_process_host; 37 NaClBrokerHost* broker_host = GetBrokerHost(); 38 39 if (!broker_host) { 40 if (!StartBroker()) 41 return false; 42 broker_host = GetBrokerHost(); 43 } 44 broker_host->LaunchLoader(loader_channel_id); 45 46 return true; 47 } 48 49 void NaClBrokerService::OnLoaderLaunched(const std::string& channel_id, 50 base::ProcessHandle handle) { 51 PendingLaunchesMap::iterator it = pending_launches_.find(channel_id); 52 if (pending_launches_.end() == it) 53 NOTREACHED(); 54 55 NaClProcessHost* client = it->second.get(); 56 if (client) 57 client->OnProcessLaunchedByBroker(handle); 58 pending_launches_.erase(it); 59 ++loaders_running_; 60 } 61 62 void NaClBrokerService::OnLoaderDied() { 63 DCHECK(loaders_running_ > 0); 64 --loaders_running_; 65 // Stop the broker only if there are no loaders running or being launched. 66 NaClBrokerHost* broker_host = GetBrokerHost(); 67 if (loaders_running_ + pending_launches_.size() == 0 && broker_host != NULL) { 68 broker_host->StopBroker(); 69 } 70 } 71 72 bool NaClBrokerService::LaunchDebugExceptionHandler( 73 base::WeakPtr<NaClProcessHost> nacl_process_host, int32 pid, 74 base::ProcessHandle process_handle, const std::string& startup_info) { 75 pending_debuggers_[pid] = nacl_process_host; 76 NaClBrokerHost* broker_host = GetBrokerHost(); 77 if (!broker_host) 78 return false; 79 return broker_host->LaunchDebugExceptionHandler(pid, process_handle, 80 startup_info); 81 } 82 83 void NaClBrokerService::OnDebugExceptionHandlerLaunched(int32 pid, 84 bool success) { 85 PendingDebugExceptionHandlersMap::iterator it = pending_debuggers_.find(pid); 86 if (pending_debuggers_.end() == it) 87 NOTREACHED(); 88 89 NaClProcessHost* client = it->second.get(); 90 if (client) 91 client->OnDebugExceptionHandlerLaunchedByBroker(success); 92 pending_debuggers_.erase(it); 93 } 94 95 NaClBrokerHost* NaClBrokerService::GetBrokerHost() { 96 BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_BROKER); 97 while (!iter.Done()) { 98 NaClBrokerHost* host = static_cast<NaClBrokerHost*>(iter.GetDelegate()); 99 if (!host->IsTerminating()) 100 return host; 101 ++iter; 102 } 103 return NULL; 104 } 105 106 } // namespace nacl 107