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 <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "base/win/win_util.h" | 16 #include "base/win/win_util.h" |
17 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
18 #include "content/public/common/content_switches.h" | 18 #include "content/public/common/content_switches.h" |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
| 22 const char kMainThreadIdSwitch[] = "main-thread-id"; |
22 const char kOnIninitializedEventHandleSwitch[] = "on-initialized-event-handle"; | 23 const char kOnIninitializedEventHandleSwitch[] = "on-initialized-event-handle"; |
23 const char kParentHandleSwitch[] = "parent-handle"; | 24 const char kParentHandleSwitch[] = "parent-handle"; |
24 const char kMainThreadIdSwitch[] = "main-thread-id"; | |
25 | 25 |
26 void AppendHandleSwitch(const std::string& switch_name, | 26 void AppendHandleSwitch(const std::string& switch_name, |
27 HANDLE handle, | 27 HANDLE handle, |
28 base::CommandLine* command_line) { | 28 base::CommandLine* command_line) { |
29 command_line->AppendSwitchASCII( | 29 command_line->AppendSwitchASCII( |
30 switch_name, base::UintToString(base::win::HandleToUint32(handle))); | 30 switch_name, base::UintToString(base::win::HandleToUint32(handle))); |
31 } | 31 } |
32 | 32 |
33 uint32_t ReadUintSwitch(const base::CommandLine& command_line, | 33 uint32_t ReadUintSwitch(const base::CommandLine& command_line, |
34 const std::string& switch_name) { | 34 const std::string& switch_name) { |
35 std::string switch_string = command_line.GetSwitchValueASCII(switch_name); | 35 std::string switch_string = command_line.GetSwitchValueASCII(switch_name); |
36 unsigned int switch_uint = 0; | 36 unsigned int switch_uint = 0; |
37 if (switch_string.empty() || | 37 if (switch_string.empty() || |
38 !base::StringToUint(switch_string, &switch_uint)) { | 38 !base::StringToUint(switch_string, &switch_uint)) { |
39 DLOG(ERROR) << "Missing or invalid " << switch_name << " argument."; | 39 DLOG(ERROR) << "Missing or invalid " << switch_name << " argument."; |
40 return 0; | 40 return 0; |
41 } | 41 } |
42 return switch_uint; | 42 return switch_uint; |
43 } | 43 } |
44 | 44 |
45 HANDLE ReadHandleFromSwitch(const base::CommandLine& command_line, | 45 HANDLE ReadHandleFromSwitch(const base::CommandLine& command_line, |
46 const std::string& switch_name) { | 46 const std::string& switch_name) { |
47 return reinterpret_cast<HANDLE>(ReadUintSwitch(command_line, switch_name)); | 47 return reinterpret_cast<HANDLE>(ReadUintSwitch(command_line, switch_name)); |
48 } | 48 } |
49 | 49 |
50 } // namespace | 50 } // namespace |
51 | 51 |
| 52 ChromeWatcherCommandLineGenerator::ChromeWatcherCommandLineGenerator( |
| 53 const base::FilePath& chrome_exe) : chrome_exe_(chrome_exe) { |
| 54 } |
| 55 |
| 56 bool ChromeWatcherCommandLineGenerator::SetOnInitializedEventHandle( |
| 57 HANDLE on_initialized_event_handle) { |
| 58 return SetHandle(on_initialized_event_handle, &on_initialized_event_handle_); |
| 59 } |
| 60 |
| 61 bool ChromeWatcherCommandLineGenerator::SetParentProcessHandle( |
| 62 HANDLE parent_process_handle) { |
| 63 return SetHandle(parent_process_handle, &parent_process_handle_); |
| 64 } |
| 65 |
| 66 // Generates a command-line representing this configuration. |
| 67 base::CommandLine ChromeWatcherCommandLineGenerator::GenerateCommandLine() { |
| 68 // TODO(chrisha): Get rid of the following function and move the |
| 69 // implementation here. |
| 70 return GenerateChromeWatcherCommandLine( |
| 71 chrome_exe_, parent_process_handle_.Get(), ::GetCurrentThreadId(), |
| 72 on_initialized_event_handle_.Get()); |
| 73 } |
| 74 |
| 75 void ChromeWatcherCommandLineGenerator::GetInheritedHandles( |
| 76 std::vector<HANDLE>* inherited_handles) const { |
| 77 if (on_initialized_event_handle_.IsValid()) |
| 78 inherited_handles->push_back(on_initialized_event_handle_.Get()); |
| 79 if (parent_process_handle_.IsValid()) |
| 80 inherited_handles->push_back(parent_process_handle_.Get()); |
| 81 } |
| 82 |
| 83 bool ChromeWatcherCommandLineGenerator::SetHandle( |
| 84 HANDLE handle, base::win::ScopedHandle* scoped_handle) { |
| 85 // Create a duplicate handle that is inheritable. |
| 86 HANDLE proc = ::GetCurrentProcess(); |
| 87 HANDLE new_handle = 0; |
| 88 if (!::DuplicateHandle(proc, handle, proc, &new_handle, 0, TRUE, |
| 89 DUPLICATE_SAME_ACCESS)) { |
| 90 return false; |
| 91 } |
| 92 |
| 93 scoped_handle->Set(new_handle); |
| 94 return true; |
| 95 } |
| 96 |
| 97 ChromeWatcherCommandLine::ChromeWatcherCommandLine( |
| 98 HANDLE on_initialized_event_handle, |
| 99 HANDLE parent_process_handle, |
| 100 DWORD main_thread_id) |
| 101 : on_initialized_event_handle_(on_initialized_event_handle), |
| 102 parent_process_handle_(parent_process_handle), |
| 103 main_thread_id_(main_thread_id) { |
| 104 } |
| 105 |
| 106 ChromeWatcherCommandLine::~ChromeWatcherCommandLine() { |
| 107 // If any handles were not taken then die violently. |
| 108 CHECK(!on_initialized_event_handle_.IsValid() && |
| 109 !parent_process_handle_.IsValid()) |
| 110 << "Handles left untaken."; |
| 111 } |
| 112 |
| 113 scoped_ptr<ChromeWatcherCommandLine> |
| 114 ChromeWatcherCommandLine::InterpretCommandLine( |
| 115 const base::CommandLine& command_line) { |
| 116 base::win::ScopedHandle on_initialized_event_handle; |
| 117 base::win::ScopedHandle parent_process_handle; |
| 118 DWORD main_thread_id = 0; |
| 119 |
| 120 // TODO(chrisha): Get rid of the following function and move the |
| 121 // implementation here. |
| 122 if (!InterpretChromeWatcherCommandLine( |
| 123 command_line, &parent_process_handle, &main_thread_id, |
| 124 &on_initialized_event_handle)) |
| 125 return scoped_ptr<ChromeWatcherCommandLine>(); |
| 126 |
| 127 return scoped_ptr<ChromeWatcherCommandLine>(new ChromeWatcherCommandLine( |
| 128 on_initialized_event_handle.Take(), parent_process_handle.Take(), |
| 129 main_thread_id)); |
| 130 } |
| 131 |
| 132 base::win::ScopedHandle |
| 133 ChromeWatcherCommandLine::TakeOnInitializedEventHandle() { |
| 134 return std::move(on_initialized_event_handle_); |
| 135 } |
| 136 |
| 137 base::win::ScopedHandle ChromeWatcherCommandLine::TakeParentProcessHandle() { |
| 138 return std::move(parent_process_handle_); |
| 139 } |
| 140 |
52 base::CommandLine GenerateChromeWatcherCommandLine( | 141 base::CommandLine GenerateChromeWatcherCommandLine( |
53 const base::FilePath& chrome_exe, | 142 const base::FilePath& chrome_exe, |
54 HANDLE parent_process, | 143 HANDLE parent_process, |
55 DWORD main_thread_id, | 144 DWORD main_thread_id, |
56 HANDLE on_initialized_event) { | 145 HANDLE on_initialized_event) { |
57 base::CommandLine command_line(chrome_exe); | 146 base::CommandLine command_line(chrome_exe); |
58 command_line.AppendSwitchASCII(switches::kProcessType, "watcher"); | 147 command_line.AppendSwitchASCII(switches::kProcessType, "watcher"); |
59 command_line.AppendSwitchASCII(kMainThreadIdSwitch, | 148 command_line.AppendSwitchASCII(kMainThreadIdSwitch, |
60 base::UintToString(main_thread_id)); | 149 base::UintToString(main_thread_id)); |
61 AppendHandleSwitch(kOnIninitializedEventHandleSwitch, on_initialized_event, | 150 AppendHandleSwitch(kOnIninitializedEventHandleSwitch, on_initialized_event, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 !parent_process->IsValid()) { | 201 !parent_process->IsValid()) { |
113 // If one was valid and not the other, free the valid one. | 202 // If one was valid and not the other, free the valid one. |
114 on_initialized_event->Close(); | 203 on_initialized_event->Close(); |
115 parent_process->Close(); | 204 parent_process->Close(); |
116 *main_thread_id = 0; | 205 *main_thread_id = 0; |
117 return false; | 206 return false; |
118 } | 207 } |
119 | 208 |
120 return true; | 209 return true; |
121 } | 210 } |
OLD | NEW |