OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "net/test/test_server.h" | 5 #include "net/test/test_server.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <wincrypt.h> | 8 #include <wincrypt.h> |
9 | 9 |
10 #include "base/base_paths.h" | 10 #include "base/base_paths.h" |
| 11 #include "base/command_line.h" |
11 #include "base/file_util.h" | 12 #include "base/file_util.h" |
12 #include "base/path_service.h" | 13 #include "base/path_service.h" |
13 #include "base/string_number_conversions.h" | 14 #include "base/string_number_conversions.h" |
14 #include "base/string_util.h" | 15 #include "base/string_util.h" |
15 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
16 | 17 |
17 #pragma comment(lib, "crypt32.lib") | 18 #pragma comment(lib, "crypt32.lib") |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 bool LaunchTestServerAsJob(const std::wstring& cmdline, | 22 bool LaunchTestServerAsJob(const CommandLine& cmdline, |
22 bool start_hidden, | 23 bool start_hidden, |
23 base::ProcessHandle* process_handle, | 24 base::ProcessHandle* process_handle, |
24 ScopedHandle* job_handle) { | 25 ScopedHandle* job_handle) { |
25 // Launch test server process. | 26 // Launch test server process. |
26 STARTUPINFO startup_info = {0}; | 27 STARTUPINFO startup_info = {0}; |
27 startup_info.cb = sizeof(startup_info); | 28 startup_info.cb = sizeof(startup_info); |
28 startup_info.dwFlags = STARTF_USESHOWWINDOW; | 29 startup_info.dwFlags = STARTF_USESHOWWINDOW; |
29 startup_info.wShowWindow = start_hidden ? SW_HIDE : SW_SHOW; | 30 startup_info.wShowWindow = start_hidden ? SW_HIDE : SW_SHOW; |
30 PROCESS_INFORMATION process_info; | 31 PROCESS_INFORMATION process_info; |
31 | 32 |
32 // If this code is run under a debugger, the test server process is | 33 // If this code is run under a debugger, the test server process is |
33 // automatically associated with a job object created by the debugger. | 34 // automatically associated with a job object created by the debugger. |
34 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. | 35 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. |
35 if (!CreateProcess(NULL, | 36 if (!CreateProcess( |
36 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL, | 37 NULL, const_cast<wchar_t*>(cmdline.command_line_string().c_str()), |
37 TRUE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, | 38 NULL, NULL, TRUE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, |
38 &startup_info, &process_info)) { | 39 &startup_info, &process_info)) { |
39 LOG(ERROR) << "Could not create process."; | 40 LOG(ERROR) << "Could not create process."; |
40 return false; | 41 return false; |
41 } | 42 } |
42 CloseHandle(process_info.hThread); | 43 CloseHandle(process_info.hThread); |
43 | 44 |
44 // If the caller wants the process handle, we won't close it. | 45 // If the caller wants the process handle, we won't close it. |
45 if (process_handle) { | 46 if (process_handle) { |
46 *process_handle = process_info.hProcess; | 47 *process_handle = process_info.hProcess; |
47 } else { | 48 } else { |
48 CloseHandle(process_info.hProcess); | 49 CloseHandle(process_info.hProcess); |
(...skipping 18 matching lines...) Expand all Loading... |
67 LOG(ERROR) << "Could not AssignProcessToObject."; | 68 LOG(ERROR) << "Could not AssignProcessToObject."; |
68 return false; | 69 return false; |
69 } | 70 } |
70 } | 71 } |
71 return true; | 72 return true; |
72 } | 73 } |
73 | 74 |
74 } // namespace | 75 } // namespace |
75 | 76 |
76 namespace net { | 77 namespace net { |
| 78 |
77 bool TestServer::LaunchPython(const FilePath& testserver_path) { | 79 bool TestServer::LaunchPython(const FilePath& testserver_path) { |
78 FilePath python_exe; | 80 FilePath python_exe; |
79 if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_exe)) | 81 if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_exe)) |
80 return false; | 82 return false; |
81 python_exe = python_exe | 83 python_exe = python_exe |
82 .Append(FILE_PATH_LITERAL("third_party")) | 84 .Append(FILE_PATH_LITERAL("third_party")) |
83 .Append(FILE_PATH_LITERAL("python_24")) | 85 .Append(FILE_PATH_LITERAL("python_24")) |
84 .Append(FILE_PATH_LITERAL("python.exe")); | 86 .Append(FILE_PATH_LITERAL("python.exe")); |
85 | 87 |
86 std::wstring command_line = | 88 CommandLine python_command(python_exe); |
87 L"\"" + python_exe.value() + L"\" " + | 89 python_command.AppendArgPath(testserver_path); |
88 L"\"" + testserver_path.value() + | 90 if (!AddCommandLineArguments(&python_command)) |
89 L"\" --port=" + ASCIIToWide(base::IntToString(host_port_pair_.port())) + | 91 return false; |
90 L" --data-dir=\"" + document_root_.value() + L"\""; | |
91 | |
92 if (type_ == TYPE_FTP) | |
93 command_line.append(L" -f"); | |
94 | |
95 FilePath certificate_path(GetCertificatePath()); | |
96 if (!certificate_path.value().empty()) { | |
97 if (!file_util::PathExists(certificate_path)) { | |
98 LOG(ERROR) << "Certificate path " << certificate_path.value() | |
99 << " doesn't exist. Can't launch https server."; | |
100 return false; | |
101 } | |
102 command_line.append(L" --https=\""); | |
103 command_line.append(certificate_path.value()); | |
104 command_line.append(L"\""); | |
105 } | |
106 | |
107 if (type_ == TYPE_HTTPS_CLIENT_AUTH) | |
108 command_line.append(L" --ssl-client-auth"); | |
109 | 92 |
110 HANDLE child_read = NULL; | 93 HANDLE child_read = NULL; |
111 HANDLE child_write = NULL; | 94 HANDLE child_write = NULL; |
112 if (!CreatePipe(&child_read, &child_write, NULL, 0)) { | 95 if (!CreatePipe(&child_read, &child_write, NULL, 0)) { |
113 PLOG(ERROR) << "Failed to create pipe"; | 96 PLOG(ERROR) << "Failed to create pipe"; |
114 return false; | 97 return false; |
115 } | 98 } |
116 child_fd_.Set(child_read); | 99 child_fd_.Set(child_read); |
117 ScopedHandle scoped_child_write(child_write); | 100 ScopedHandle scoped_child_write(child_write); |
118 | 101 |
119 // Have the child inherit the write half. | 102 // Have the child inherit the write half. |
120 if (!SetHandleInformation(child_write, HANDLE_FLAG_INHERIT, | 103 if (!SetHandleInformation(child_write, HANDLE_FLAG_INHERIT, |
121 HANDLE_FLAG_INHERIT)) { | 104 HANDLE_FLAG_INHERIT)) { |
122 PLOG(ERROR) << "Failed to enable pipe inheritance"; | 105 PLOG(ERROR) << "Failed to enable pipe inheritance"; |
123 return false; | 106 return false; |
124 } | 107 } |
125 | 108 |
126 // Pass the handle on the command-line. Although HANDLE is a | 109 // Pass the handle on the command-line. Although HANDLE is a |
127 // pointer, truncating it on 64-bit machines is okay. See | 110 // pointer, truncating it on 64-bit machines is okay. See |
128 // http://msdn.microsoft.com/en-us/library/aa384203.aspx | 111 // http://msdn.microsoft.com/en-us/library/aa384203.aspx |
129 // | 112 // |
130 // "64-bit versions of Windows use 32-bit handles for | 113 // "64-bit versions of Windows use 32-bit handles for |
131 // interoperability. When sharing a handle between 32-bit and 64-bit | 114 // interoperability. When sharing a handle between 32-bit and 64-bit |
132 // applications, only the lower 32 bits are significant, so it is | 115 // applications, only the lower 32 bits are significant, so it is |
133 // safe to truncate the handle (when passing it from 64-bit to | 116 // safe to truncate the handle (when passing it from 64-bit to |
134 // 32-bit) or sign-extend the handle (when passing it from 32-bit to | 117 // 32-bit) or sign-extend the handle (when passing it from 32-bit to |
135 // 64-bit)." | 118 // 64-bit)." |
136 command_line.append( | 119 python_command.AppendSwitchASCII( |
137 L" --startup-pipe=" + | 120 "startup-pipe", |
138 ASCIIToWide(base::IntToString(reinterpret_cast<uintptr_t>(child_write)))); | 121 base::IntToString(reinterpret_cast<uintptr_t>(child_write))); |
139 | 122 |
140 if (!LaunchTestServerAsJob(command_line, | 123 if (!LaunchTestServerAsJob(python_command, |
141 true, | 124 true, |
142 &process_handle_, | 125 &process_handle_, |
143 &job_handle_)) { | 126 &job_handle_)) { |
144 LOG(ERROR) << "Failed to launch " << command_line; | 127 LOG(ERROR) << "Failed to launch " << python_command.command_line_string(); |
145 return false; | 128 return false; |
146 } | 129 } |
147 | 130 |
148 return true; | 131 return true; |
149 } | 132 } |
150 | 133 |
151 bool TestServer::WaitToStart() { | 134 bool TestServer::WaitToStart() { |
152 char buf[8]; | 135 char buf[8]; |
153 DWORD bytes_read; | 136 DWORD bytes_read; |
154 BOOL result = ReadFile(child_fd_, buf, sizeof(buf), &bytes_read, NULL); | 137 BOOL result = ReadFile(child_fd_, buf, sizeof(buf), &bytes_read, NULL); |
(...skipping 23 matching lines...) Expand all Loading... |
178 "certificate to your trusted roots for this test to work. " | 161 "certificate to your trusted roots for this test to work. " |
179 "For more info visit:\n" | 162 "For more info visit:\n" |
180 "http://dev.chromium.org/developers/testing\n"; | 163 "http://dev.chromium.org/developers/testing\n"; |
181 return false; | 164 return false; |
182 } | 165 } |
183 | 166 |
184 return true; | 167 return true; |
185 } | 168 } |
186 | 169 |
187 } // namespace net | 170 } // namespace net |
OLD | NEW |