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