Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / app / chrome_watcher_client_win.cc
blob23e595eac869207c71e70fb4eae0aa28af5b53d3
1 // Copyright 2015 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.
5 #include "chrome/app/chrome_watcher_client_win.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "components/browser_watcher/watcher_client_win.h"
11 namespace {
13 // Because we can only bind parameters from the left, |parent_process| must be
14 // the last parameter of the method that we bind into a
15 // BrowserWatcherClient::CommandLineGenerator. The ChromeWatcherClient API is
16 // more intuitive if the ChromeWatcherClient::CommandLineGenerator takes
17 // |parent_process| as its second parameter, so we use this intermediate
18 // function to swap the order.
19 base::CommandLine InvokeCommandLineGenerator(
20 const ChromeWatcherClient::CommandLineGenerator& command_line_generator,
21 HANDLE on_initialized_event,
22 HANDLE parent_process) {
23 return command_line_generator.Run(parent_process, ::GetCurrentThreadId(),
24 on_initialized_event);
27 } // namespace
29 ChromeWatcherClient::ChromeWatcherClient(
30 const CommandLineGenerator& command_line_generator)
31 : command_line_generator_(command_line_generator) {
34 ChromeWatcherClient::~ChromeWatcherClient() {
37 bool ChromeWatcherClient::LaunchWatcher() {
38 // Create an inheritable event that the child process will signal when it has
39 // completed initialization.
40 SECURITY_ATTRIBUTES on_initialized_event_attributes = {
41 sizeof(SECURITY_ATTRIBUTES), // nLength
42 nullptr, // lpSecurityDescriptor
43 TRUE // bInheritHandle
45 on_initialized_event_.Set(::CreateEvent(&on_initialized_event_attributes,
46 TRUE, // manual reset
47 FALSE, nullptr));
48 if (!on_initialized_event_.IsValid()) {
49 DPLOG(ERROR) << "Failed to create an event.";
50 return false;
53 // Configure the basic WatcherClient, binding in the initialization event
54 // HANDLE.
55 browser_watcher::WatcherClient watcher_client(
56 base::Bind(&InvokeCommandLineGenerator, command_line_generator_,
57 on_initialized_event_.Get()));
58 // Indicate that the event HANDLE should be inherited.
59 watcher_client.AddInheritedHandle(on_initialized_event_.Get());
60 // Launch the watcher.
61 watcher_client.LaunchWatcher();
62 // Grab a handle to the watcher so that we may later wait on its
63 // initialization.
64 process_ = watcher_client.process().Duplicate();
65 if (!process_.IsValid())
66 on_initialized_event_.Close();
67 return process_.IsValid();
70 bool ChromeWatcherClient::EnsureInitialized() {
71 if (!process_.IsValid())
72 return false;
74 DCHECK(on_initialized_event_.IsValid());
76 HANDLE handles[] = {on_initialized_event_.Get(), process_.Handle()};
77 DWORD result = ::WaitForMultipleObjects(arraysize(handles), handles,
78 FALSE, INFINITE);
80 switch (result) {
81 case WAIT_OBJECT_0:
82 return true;
83 case WAIT_OBJECT_0 + 1:
84 LOG(ERROR) << "Chrome watcher process failed to launch.";
85 return false;
86 case WAIT_FAILED:
87 DPLOG(ERROR) << "Failure while waiting on Chrome watcher process launch.";
88 return false;
89 default:
90 NOTREACHED() << "Unexpected result while waiting on Chrome watcher "
91 "process launch: " << result;
92 return false;
96 bool ChromeWatcherClient::WaitForExit(int* exit_code) {
97 return process_.IsValid() && process_.WaitForExit(exit_code);
100 bool ChromeWatcherClient::WaitForExitWithTimeout(base::TimeDelta timeout,
101 int* exit_code) {
102 return process_.IsValid() &&
103 process_.WaitForExitWithTimeout(timeout, exit_code);