1 // Copyright 2012 The Chromium Authors
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
GetInstance()15 NaClBrokerService* NaClBrokerService::GetInstance() {
16 return base::Singleton<NaClBrokerService>::get();
17 }
18
NaClBrokerService()19 NaClBrokerService::NaClBrokerService()
20 : loaders_running_(0) {
21 }
22
~NaClBrokerService()23 NaClBrokerService::~NaClBrokerService() {
24 }
25
StartBroker()26 bool NaClBrokerService::StartBroker() {
27 NaClBrokerHost* broker_host = new NaClBrokerHost;
28 if (!broker_host->Init()) {
29 delete broker_host;
30 return false;
31 }
32 return true;
33 }
34
LaunchLoader(base::WeakPtr<nacl::NaClProcessHost> nacl_process_host,mojo::ScopedMessagePipeHandle ipc_channel_handle)35 bool NaClBrokerService::LaunchLoader(
36 base::WeakPtr<nacl::NaClProcessHost> nacl_process_host,
37 mojo::ScopedMessagePipeHandle ipc_channel_handle) {
38 // Add task to the list
39 int launch_id = ++next_launch_id_;
40 pending_launches_[launch_id] = nacl_process_host;
41 NaClBrokerHost* broker_host = GetBrokerHost();
42
43 if (!broker_host) {
44 if (!StartBroker())
45 return false;
46 broker_host = GetBrokerHost();
47 }
48 broker_host->LaunchLoader(launch_id, std::move(ipc_channel_handle));
49
50 return true;
51 }
52
OnLoaderLaunched(int launch_id,base::Process process)53 void NaClBrokerService::OnLoaderLaunched(int launch_id, base::Process process) {
54 PendingLaunchesMap::iterator it = pending_launches_.find(launch_id);
55 if (pending_launches_.end() == it) {
56 NOTREACHED();
57 return;
58 }
59
60 NaClProcessHost* client = it->second.get();
61 if (client)
62 client->OnProcessLaunchedByBroker(std::move(process));
63 pending_launches_.erase(it);
64 ++loaders_running_;
65 }
66
OnLoaderDied()67 void NaClBrokerService::OnLoaderDied() {
68 DCHECK(loaders_running_ > 0);
69 --loaders_running_;
70 // Stop the broker only if there are no loaders running or being launched.
71 NaClBrokerHost* broker_host = GetBrokerHost();
72 if (loaders_running_ + pending_launches_.size() == 0 && broker_host != NULL) {
73 broker_host->StopBroker();
74 }
75 }
76
LaunchDebugExceptionHandler(base::WeakPtr<NaClProcessHost> nacl_process_host,int32_t pid,base::ProcessHandle process_handle,const std::string & startup_info)77 bool NaClBrokerService::LaunchDebugExceptionHandler(
78 base::WeakPtr<NaClProcessHost> nacl_process_host,
79 int32_t pid,
80 base::ProcessHandle process_handle,
81 const std::string& startup_info) {
82 pending_debuggers_[pid] = nacl_process_host;
83 NaClBrokerHost* broker_host = GetBrokerHost();
84 if (!broker_host)
85 return false;
86 return broker_host->LaunchDebugExceptionHandler(pid, process_handle,
87 startup_info);
88 }
89
OnDebugExceptionHandlerLaunched(int32_t pid,bool success)90 void NaClBrokerService::OnDebugExceptionHandlerLaunched(int32_t pid,
91 bool success) {
92 PendingDebugExceptionHandlersMap::iterator it = pending_debuggers_.find(pid);
93 if (pending_debuggers_.end() == it)
94 NOTREACHED();
95
96 NaClProcessHost* client = it->second.get();
97 if (client)
98 client->OnDebugExceptionHandlerLaunchedByBroker(success);
99 pending_debuggers_.erase(it);
100 }
101
GetBrokerHost()102 NaClBrokerHost* NaClBrokerService::GetBrokerHost() {
103 BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_BROKER);
104 while (!iter.Done()) {
105 NaClBrokerHost* host = static_cast<NaClBrokerHost*>(iter.GetDelegate());
106 if (!host->IsTerminating())
107 return host;
108 ++iter;
109 }
110 return NULL;
111 }
112
113 } // namespace nacl
114