summaryrefslogtreecommitdiffstats
path: root/chrome/browser/nacl_host/nacl_broker_service_win.cc
blob: 0fb96f65a2b59a85df1cf06d62a92a0fb32c9845 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/nacl_host/nacl_broker_service_win.h"

#include "chrome/browser/nacl_host/nacl_process_host.h"
#include "components/nacl/common/nacl_process_type.h"
#include "content/public/browser/browser_child_process_host_iterator.h"

using content::BrowserChildProcessHostIterator;

NaClBrokerService* NaClBrokerService::GetInstance() {
  return Singleton<NaClBrokerService>::get();
}

NaClBrokerService::NaClBrokerService()
    : loaders_running_(0) {
}

bool NaClBrokerService::StartBroker() {
  NaClBrokerHost* broker_host = new NaClBrokerHost;
  if (!broker_host->Init()) {
    delete broker_host;
    return false;
  }
  return true;
}

bool NaClBrokerService::LaunchLoader(
    base::WeakPtr<NaClProcessHost> nacl_process_host,
    const std::string& loader_channel_id) {
  // Add task to the list
  pending_launches_[loader_channel_id] = nacl_process_host;
  NaClBrokerHost* broker_host = GetBrokerHost();

  if (!broker_host) {
    if (!StartBroker())
      return false;
    broker_host = GetBrokerHost();
  }
  broker_host->LaunchLoader(loader_channel_id);

  return true;
}

void NaClBrokerService::OnLoaderLaunched(const std::string& channel_id,
                                         base::ProcessHandle handle) {
  PendingLaunchesMap::iterator it = pending_launches_.find(channel_id);
  if (pending_launches_.end() == it)
    NOTREACHED();

  NaClProcessHost* client = it->second.get();
  if (client)
    client->OnProcessLaunchedByBroker(handle);
  pending_launches_.erase(it);
  ++loaders_running_;
}

void NaClBrokerService::OnLoaderDied() {
  DCHECK(loaders_running_ > 0);
  --loaders_running_;
  // Stop the broker only if there are no loaders running or being launched.
  NaClBrokerHost* broker_host = GetBrokerHost();
  if (loaders_running_ + pending_launches_.size() == 0 && broker_host != NULL) {
    broker_host->StopBroker();
  }
}

bool NaClBrokerService::LaunchDebugExceptionHandler(
    base::WeakPtr<NaClProcessHost> nacl_process_host, int32 pid,
    base::ProcessHandle process_handle, const std::string& startup_info) {
  pending_debuggers_[pid] = nacl_process_host;
  NaClBrokerHost* broker_host = GetBrokerHost();
  if (!broker_host)
    return false;
  return broker_host->LaunchDebugExceptionHandler(pid, process_handle,
                                                  startup_info);
}

void NaClBrokerService::OnDebugExceptionHandlerLaunched(int32 pid,
                                                        bool success) {
  PendingDebugExceptionHandlersMap::iterator it = pending_debuggers_.find(pid);
  if (pending_debuggers_.end() == it)
    NOTREACHED();

  NaClProcessHost* client = it->second.get();
  if (client)
    client->OnDebugExceptionHandlerLaunchedByBroker(success);
  pending_debuggers_.erase(it);
}

NaClBrokerHost* NaClBrokerService::GetBrokerHost() {
  BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_BROKER);
  while (!iter.Done()) {
    NaClBrokerHost* host = static_cast<NaClBrokerHost*>(iter.GetDelegate());
    if (!host->IsTerminating())
      return host;
    ++iter;
  }
  return NULL;
}