OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/app/chrome_watcher_command_line_win.h" | 5 #include "chrome/app/chrome_watcher_command_line_win.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "chrome/common/chrome_switches.h" | 14 #include "chrome/common/chrome_switches.h" |
15 | 15 |
16 namespace { | 16 namespace { |
| 17 |
| 18 const char kOnIninitializedEventHandleSwitch[] = "on-initialized-event-handle"; |
17 const char kParentHandleSwitch[] = "parent-handle"; | 19 const char kParentHandleSwitch[] = "parent-handle"; |
| 20 |
| 21 void AppendHandleSwitch(const std::string& switch_name, |
| 22 HANDLE handle, |
| 23 base::CommandLine* command_line) { |
| 24 command_line->AppendSwitchASCII( |
| 25 switch_name, base::UintToString(reinterpret_cast<unsigned int>(handle))); |
| 26 } |
| 27 |
| 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."; |
| 35 return nullptr; |
| 36 } |
| 37 return reinterpret_cast<HANDLE>(switch_uint); |
| 38 } |
| 39 |
18 } // namespace | 40 } // namespace |
19 | 41 |
20 base::CommandLine GenerateChromeWatcherCommandLine( | 42 base::CommandLine GenerateChromeWatcherCommandLine( |
21 const base::FilePath& chrome_exe, | 43 const base::FilePath& chrome_exe, |
22 HANDLE parent_process) { | 44 HANDLE parent_process, |
| 45 HANDLE on_initialized_event) { |
23 base::CommandLine command_line(chrome_exe); | 46 base::CommandLine command_line(chrome_exe); |
24 command_line.AppendSwitchASCII(switches::kProcessType, "watcher"); | 47 command_line.AppendSwitchASCII(switches::kProcessType, "watcher"); |
25 command_line.AppendSwitchASCII( | 48 AppendHandleSwitch(kOnIninitializedEventHandleSwitch, on_initialized_event, |
26 kParentHandleSwitch, | 49 &command_line); |
27 base::UintToString(reinterpret_cast<unsigned int>(parent_process))); | 50 AppendHandleSwitch(kParentHandleSwitch, parent_process, &command_line); |
28 return command_line; | 51 return command_line; |
29 } | 52 } |
30 | 53 |
31 base::win::ScopedHandle InterpretChromeWatcherCommandLine( | 54 bool InterpretChromeWatcherCommandLine( |
32 const base::CommandLine& command_line) { | 55 const base::CommandLine& command_line, |
33 std::string parent_handle_str = | 56 base::win::ScopedHandle* parent_process, |
34 command_line.GetSwitchValueASCII(kParentHandleSwitch); | 57 base::win::ScopedHandle* on_initialized_event) { |
35 unsigned parent_handle_uint = 0; | 58 DCHECK(on_initialized_event); |
36 if (parent_handle_str.empty() || | 59 DCHECK(parent_process); |
37 !base::StringToUint(parent_handle_str, &parent_handle_uint)) { | 60 |
38 LOG(ERROR) << "Missing or invalid " << kParentHandleSwitch << " argument."; | 61 // For consistency, always close any existing HANDLEs here. |
39 return base::win::ScopedHandle(); | 62 on_initialized_event->Close(); |
| 63 parent_process->Close(); |
| 64 |
| 65 HANDLE parent_handle = |
| 66 ReadHandleFromSwitch(command_line, kParentHandleSwitch); |
| 67 HANDLE on_initialized_event_handle = |
| 68 ReadHandleFromSwitch(command_line, kOnIninitializedEventHandleSwitch); |
| 69 |
| 70 if (parent_handle) { |
| 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 |
| 73 // handle. |
| 74 DWORD process_pid = ::GetProcessId(parent_handle); |
| 75 if (process_pid == 0) { |
| 76 DLOG(ERROR) << "Invalid " << kParentHandleSwitch |
| 77 << " argument. Can't get parent PID."; |
| 78 } else { |
| 79 parent_process->Set(parent_handle); |
| 80 } |
40 } | 81 } |
41 | 82 |
42 HANDLE parent_process = reinterpret_cast<HANDLE>(parent_handle_uint); | 83 if (on_initialized_event_handle) { |
43 // Initial test of the handle, a zero PID indicates invalid handle, or not | 84 DWORD result = ::WaitForSingleObject(on_initialized_event_handle, 0); |
44 // a process handle. In this case, parsing fails and we avoid closing the | 85 if (result == WAIT_FAILED) { |
45 // handle. | 86 DPLOG(ERROR) |
46 DWORD process_pid = ::GetProcessId(parent_process); | 87 << "Unexpected error while testing the initialization event."; |
47 if (process_pid == 0) { | 88 } else if (result != WAIT_TIMEOUT) { |
48 LOG(ERROR) << "Invalid " << kParentHandleSwitch | 89 DLOG(ERROR) << "Unexpected result while testing the initialization event " |
49 << " argument. Can't get parent PID."; | 90 "with WaitForSingleObject: " << result; |
50 return base::win::ScopedHandle(); | 91 } else { |
| 92 on_initialized_event->Set(on_initialized_event_handle); |
| 93 } |
51 } | 94 } |
52 | 95 |
53 return base::win::ScopedHandle(parent_process); | 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(); |
| 100 return false; |
| 101 } |
| 102 |
| 103 return true; |
54 } | 104 } |
OLD | NEW |