| 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 |