1 // Copyright (c) 2014 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_command_line_win.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "chrome/common/chrome_switches.h"
18 const char kOnIninitializedEventHandleSwitch
[] = "on-initialized-event-handle";
19 const char kParentHandleSwitch
[] = "parent-handle";
21 void AppendHandleSwitch(const std::string
& switch_name
,
23 base::CommandLine
* command_line
) {
24 command_line
->AppendSwitchASCII(
25 switch_name
, base::UintToString(reinterpret_cast<unsigned int>(handle
)));
28 HANDLE
ReadHandleFromSwitch(const base::CommandLine
& command_line
,
29 const std::string
& switch_name
) {
30 std::string switch_string
= command_line
.GetSwitchValueASCII(switch_name
);
31 unsigned int switch_uint
= 0;
32 if (switch_string
.empty() ||
33 !base::StringToUint(switch_string
, &switch_uint
)) {
34 DLOG(ERROR
) << "Missing or invalid " << switch_name
<< " argument.";
37 return reinterpret_cast<HANDLE
>(switch_uint
);
42 base::CommandLine
GenerateChromeWatcherCommandLine(
43 const base::FilePath
& chrome_exe
,
44 HANDLE parent_process
,
45 HANDLE on_initialized_event
) {
46 base::CommandLine
command_line(chrome_exe
);
47 command_line
.AppendSwitchASCII(switches::kProcessType
, "watcher");
48 AppendHandleSwitch(kOnIninitializedEventHandleSwitch
, on_initialized_event
,
50 AppendHandleSwitch(kParentHandleSwitch
, parent_process
, &command_line
);
54 bool InterpretChromeWatcherCommandLine(
55 const base::CommandLine
& command_line
,
56 base::win::ScopedHandle
* parent_process
,
57 base::win::ScopedHandle
* on_initialized_event
) {
58 DCHECK(on_initialized_event
);
59 DCHECK(parent_process
);
61 // For consistency, always close any existing HANDLEs here.
62 on_initialized_event
->Close();
63 parent_process
->Close();
65 HANDLE parent_handle
=
66 ReadHandleFromSwitch(command_line
, kParentHandleSwitch
);
67 HANDLE on_initialized_event_handle
=
68 ReadHandleFromSwitch(command_line
, kOnIninitializedEventHandleSwitch
);
71 // Initial test of the handle, a zero PID indicates invalid handle, or not
72 // a process handle. In this case, parsing fails and we avoid closing the
74 DWORD process_pid
= ::GetProcessId(parent_handle
);
75 if (process_pid
== 0) {
76 DLOG(ERROR
) << "Invalid " << kParentHandleSwitch
77 << " argument. Can't get parent PID.";
79 parent_process
->Set(parent_handle
);
83 if (on_initialized_event_handle
) {
84 DWORD result
= ::WaitForSingleObject(on_initialized_event_handle
, 0);
85 if (result
== WAIT_FAILED
) {
87 << "Unexpected error while testing the initialization event.";
88 } else if (result
!= WAIT_TIMEOUT
) {
89 DLOG(ERROR
) << "Unexpected result while testing the initialization event "
90 "with WaitForSingleObject: " << result
;
92 on_initialized_event
->Set(on_initialized_event_handle
);
96 if (!on_initialized_event
->IsValid() || !parent_process
->IsValid()) {
97 // If one was valid and not the other, free the valid one.
98 on_initialized_event
->Close();
99 parent_process
->Close();