15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_broker_service_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/nacl_process_host.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "components/nacl/common/nacl_process_type.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_child_process_host_iterator.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserChildProcessHostIterator;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace nacl {
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClBrokerService* NaClBrokerService::GetInstance() {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<NaClBrokerService>::get();
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClBrokerService::NaClBrokerService()
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : loaders_running_(0) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClBrokerService::StartBroker() {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClBrokerHost* broker_host = new NaClBrokerHost;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!broker_host->Init()) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete broker_host;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClBrokerService::LaunchLoader(
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::WeakPtr<nacl::NaClProcessHost> nacl_process_host,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& loader_channel_id) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add task to the list
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_launches_[loader_channel_id] = nacl_process_host;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClBrokerHost* broker_host = GetBrokerHost();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!broker_host) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!StartBroker())
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    broker_host = GetBrokerHost();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  broker_host->LaunchLoader(loader_channel_id);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClBrokerService::OnLoaderLaunched(const std::string& channel_id,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         base::ProcessHandle handle) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingLaunchesMap::iterator it = pending_launches_.find(channel_id);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_launches_.end() == it)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NaClProcessHost* client = it->second.get();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client->OnProcessLaunchedByBroker(handle);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_launches_.erase(it);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++loaders_running_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClBrokerService::OnLoaderDied() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaders_running_ > 0);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --loaders_running_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop the broker only if there are no loaders running or being launched.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClBrokerHost* broker_host = GetBrokerHost();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaders_running_ + pending_launches_.size() == 0 && broker_host != NULL) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    broker_host->StopBroker();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClBrokerService::LaunchDebugExceptionHandler(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<NaClProcessHost> nacl_process_host, int32 pid,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle process_handle, const std::string& startup_info) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_debuggers_[pid] = nacl_process_host;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NaClBrokerHost* broker_host = GetBrokerHost();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!broker_host)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return broker_host->LaunchDebugExceptionHandler(pid, process_handle,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  startup_info);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClBrokerService::OnDebugExceptionHandlerLaunched(int32 pid,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        bool success) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingDebugExceptionHandlersMap::iterator it = pending_debuggers_.find(pid);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_debuggers_.end() == it)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NaClProcessHost* client = it->second.get();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client->OnDebugExceptionHandlerLaunchedByBroker(success);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_debuggers_.erase(it);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClBrokerHost* NaClBrokerService::GetBrokerHost() {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_BROKER);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!iter.Done()) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NaClBrokerHost* host = static_cast<NaClBrokerHost*>(iter.GetDelegate());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!host->IsTerminating())
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return host;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++iter;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace nacl
107