Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: chrome/test/chromedriver/server/chromedriver_server.cc

Issue 19616008: [chromedriver] Allow commands to be async. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 <stdio.h> 5 #include <stdio.h>
6 #include <string> 6 #include <string>
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/at_exit.h" 9 #include "base/at_exit.h"
10 #include "base/bind.h"
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
17 #include "base/synchronization/waitable_event.h" 20 #include "base/synchronization/waitable_event.h"
21 #include "base/threading/thread.h"
18 #include "chrome/test/chromedriver/chrome/log.h" 22 #include "chrome/test/chromedriver/chrome/log.h"
19 #include "chrome/test/chromedriver/chrome/version.h" 23 #include "chrome/test/chromedriver/chrome/version.h"
20 #include "chrome/test/chromedriver/server/http_handler.h" 24 #include "chrome/test/chromedriver/server/http_handler.h"
21 #include "chrome/test/chromedriver/server/http_response.h" 25 #include "chrome/test/chromedriver/server/http_response.h"
22 #include "net/server/http_server_request_info.h" 26 #include "net/server/http_server_request_info.h"
23 #include "third_party/mongoose/mongoose.h" 27 #include "third_party/mongoose/mongoose.h"
24 28
25 #if defined(OS_POSIX) 29 #if defined(OS_POSIX)
26 #include <fcntl.h> 30 #include <fcntl.h>
27 #include <unistd.h> 31 #include <unistd.h>
28 #endif 32 #endif
29 33
30 namespace { 34 namespace {
31 35
36 void SendHttpResponse(bool shutdown,
37 const HttpResponseSenderFunc& send_response_func,
38 scoped_ptr<HttpResponse> response) {
39 send_response_func.Run(response.Pass());
40 if (shutdown)
41 base::MessageLoop::current()->QuitWhenIdle();
42 }
43
44 void HandleHttpRequest(HttpHandler* handler,
45 const net::HttpServerRequestInfo& request,
46 const HttpResponseSenderFunc& send_response_func) {
47 handler->Handle(request,
48 base::Bind(&SendHttpResponse,
49 handler->ShouldShutdown(request),
50 send_response_func));
51 }
52
32 void ReadRequestBody(const struct mg_request_info* const request_info, 53 void ReadRequestBody(const struct mg_request_info* const request_info,
33 struct mg_connection* const connection, 54 struct mg_connection* const connection,
34 std::string* request_body) { 55 std::string* request_body) {
35 int content_length = 0; 56 int content_length = 0;
36 // 64 maximum header count hard-coded in mongoose.h 57 // 64 maximum header count hard-coded in mongoose.h
37 for (int header_index = 0; header_index < 64; ++header_index) { 58 for (int header_index = 0; header_index < 64; ++header_index) {
38 if (request_info->http_headers[header_index].name == NULL) { 59 if (request_info->http_headers[header_index].name == NULL) {
39 break; 60 break;
40 } 61 }
41 if (LowerCaseEqualsASCII(request_info->http_headers[header_index].name, 62 if (LowerCaseEqualsASCII(request_info->http_headers[header_index].name,
42 "content-length")) { 63 "content-length")) {
43 base::StringToInt( 64 base::StringToInt(
44 request_info->http_headers[header_index].value, &content_length); 65 request_info->http_headers[header_index].value, &content_length);
45 break; 66 break;
46 } 67 }
47 } 68 }
48 if (content_length > 0) { 69 if (content_length > 0) {
49 request_body->resize(content_length); 70 request_body->resize(content_length);
50 int bytes_read = 0; 71 int bytes_read = 0;
51 while (bytes_read < content_length) { 72 while (bytes_read < content_length) {
52 bytes_read += mg_read(connection, 73 bytes_read += mg_read(connection,
53 &(*request_body)[bytes_read], 74 &(*request_body)[bytes_read],
54 content_length - bytes_read); 75 content_length - bytes_read);
55 } 76 }
56 } 77 }
57 } 78 }
58 79
80 typedef base::Callback<
81 void(const net::HttpServerRequestInfo&, const HttpResponseSenderFunc&)>
82 HttpRequestHandlerFunc;
83
59 struct MongooseUserData { 84 struct MongooseUserData {
60 HttpHandler* handler; 85 base::SingleThreadTaskRunner* cmd_task_runner;
61 base::WaitableEvent* shutdown_event; 86 HttpRequestHandlerFunc* handler_func;
62 }; 87 };
63 88
89 void DoneProcessing(base::WaitableEvent* event,
90 scoped_ptr<HttpResponse>* response_to_set,
91 scoped_ptr<HttpResponse> response) {
92 *response_to_set = response.Pass();
93 event->Signal();
94 }
95
64 void* ProcessHttpRequest(mg_event event_raised, 96 void* ProcessHttpRequest(mg_event event_raised,
65 struct mg_connection* connection, 97 struct mg_connection* connection,
66 const struct mg_request_info* request_info) { 98 const struct mg_request_info* request_info) {
67 if (event_raised != MG_NEW_REQUEST) 99 if (event_raised != MG_NEW_REQUEST)
68 return reinterpret_cast<void*>(false); 100 return reinterpret_cast<void*>(false);
69 MongooseUserData* user_data = 101 MongooseUserData* user_data =
70 reinterpret_cast<MongooseUserData*>(request_info->user_data); 102 reinterpret_cast<MongooseUserData*>(request_info->user_data);
71 103
72 net::HttpServerRequestInfo request; 104 net::HttpServerRequestInfo request;
73 request.method = request_info->request_method; 105 request.method = request_info->request_method;
74 request.path = request_info->uri; 106 request.path = request_info->uri;
75 ReadRequestBody(request_info, connection, &request.data); 107 ReadRequestBody(request_info, connection, &request.data);
76 108
77 HttpResponse response; 109 base::WaitableEvent event(false, false);
78 user_data->handler->Handle(request, &response); 110 scoped_ptr<HttpResponse> response;
111 user_data->cmd_task_runner
112 ->PostTask(FROM_HERE,
113 base::Bind(*user_data->handler_func,
114 request,
115 base::Bind(&DoneProcessing, &event, &response)));
116 event.Wait();
79 117
80 // Don't allow HTTP keep alive. 118 // Don't allow HTTP keep alive.
81 response.AddHeader("connection", "close"); 119 response->AddHeader("connection", "close");
82 std::string data; 120 std::string data;
83 response.GetData(&data); 121 response->GetData(&data);
84 mg_write(connection, data.data(), data.length()); 122 mg_write(connection, data.data(), data.length());
85 if (user_data->handler->ShouldShutdown(request))
86 user_data->shutdown_event->Signal();
87 return reinterpret_cast<void*>(true); 123 return reinterpret_cast<void*>(true);
88 } 124 }
89 125
90 void MakeMongooseOptions(const std::string& port, 126 void MakeMongooseOptions(const std::string& port,
91 int http_threads, 127 int http_threads,
92 std::vector<std::string>* out_options) { 128 std::vector<std::string>* out_options) {
93 out_options->push_back("listening_ports"); 129 out_options->push_back("listening_ports");
94 out_options->push_back(port); 130 out_options->push_back(port);
95 out_options->push_back("enable_keep_alive"); 131 out_options->push_back("enable_keep_alive");
96 out_options->push_back("no"); 132 out_options->push_back("no");
97 out_options->push_back("num_threads"); 133 out_options->push_back("num_threads");
98 out_options->push_back(base::IntToString(http_threads)); 134 out_options->push_back(base::IntToString(http_threads));
99 } 135 }
100 136
101 } // namespace 137 } // namespace
102 138
103 int main(int argc, char *argv[]) { 139 int main(int argc, char *argv[]) {
104 CommandLine::Init(argc, argv); 140 CommandLine::Init(argc, argv);
105 141
106 base::AtExitManager exit; 142 base::AtExitManager at_exit;
107 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 143 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
108 144
109 // Parse command line flags. 145 // Parse command line flags.
110 std::string port = "9515"; 146 std::string port = "9515";
111 std::string url_base; 147 std::string url_base;
112 int http_threads = 4; 148 int http_threads = 4;
113 base::FilePath log_path; 149 base::FilePath log_path;
114 Log::Level log_level = Log::kError; 150 Log::Level log_level = Log::kError;
115 if (cmd_line->HasSwitch("h") || cmd_line->HasSwitch("help")) { 151 if (cmd_line->HasSwitch("h") || cmd_line->HasSwitch("help")) {
116 std::string options; 152 std::string options;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 if (!success) { 204 if (!success) {
169 PLOG(ERROR) << "Unable to initialize logging"; 205 PLOG(ERROR) << "Unable to initialize logging";
170 } 206 }
171 logging::SetLogItems(false, // enable_process_id 207 logging::SetLogItems(false, // enable_process_id
172 false, // enable_thread_id 208 false, // enable_thread_id
173 false, // enable_timestamp 209 false, // enable_timestamp
174 false); // enable_tickcount 210 false); // enable_tickcount
175 if (!cmd_line->HasSwitch("verbose")) 211 if (!cmd_line->HasSwitch("verbose"))
176 logging::SetMinLogLevel(logging::LOG_FATAL); 212 logging::SetMinLogLevel(logging::LOG_FATAL);
177 213
214 base::Thread io_thread("ChromeDriver IO");
215 CHECK(io_thread.StartWithOptions(
216 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
217
178 scoped_ptr<Log> log(new Logger(log_level)); 218 scoped_ptr<Log> log(new Logger(log_level));
179 HttpHandler handler(log.get(), url_base); 219 HttpHandler handler(io_thread.message_loop_proxy(), log.get(), url_base);
180 base::WaitableEvent shutdown_event(false, false); 220 base::MessageLoop cmd_loop;
181 MongooseUserData user_data = { &handler, &shutdown_event }; 221 HttpRequestHandlerFunc handler_func =
222 base::Bind(&HandleHttpRequest, &handler);
223 MongooseUserData user_data = { cmd_loop.message_loop_proxy(), &handler_func };
182 224
183 std::vector<std::string> args; 225 std::vector<std::string> args;
184 MakeMongooseOptions(port, http_threads, &args); 226 MakeMongooseOptions(port, http_threads, &args);
185 scoped_ptr<const char*[]> options(new const char*[args.size() + 1]); 227 scoped_ptr<const char*[]> options(new const char*[args.size() + 1]);
186 for (size_t i = 0; i < args.size(); ++i) { 228 for (size_t i = 0; i < args.size(); ++i) {
187 options[i] = args[i].c_str(); 229 options[i] = args[i].c_str();
188 } 230 }
189 options[args.size()] = NULL; 231 options[args.size()] = NULL;
190 232
191 struct mg_context* ctx = mg_start(&ProcessHttpRequest, 233 struct mg_context* ctx = mg_start(&ProcessHttpRequest,
(...skipping 11 matching lines...) Expand all
203 fflush(stdout); 245 fflush(stdout);
204 } 246 }
205 247
206 #if defined(OS_POSIX) 248 #if defined(OS_POSIX)
207 if (!cmd_line->HasSwitch("verbose")) { 249 if (!cmd_line->HasSwitch("verbose")) {
208 // Close stderr on exec, so that Chrome log spew doesn't confuse users. 250 // Close stderr on exec, so that Chrome log spew doesn't confuse users.
209 fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC); 251 fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC);
210 } 252 }
211 #endif 253 #endif
212 254
213 // Run until we receive command to shutdown. 255 base::RunLoop cmd_run_loop;
214 shutdown_event.Wait(); 256 cmd_run_loop.Run();
215 257 // Don't run destructors for objects passed via MongooseUserData,
216 return 0; 258 // because ProcessHttpRequest may be accessing them.
259 // TODO(kkania): Fix when switching to net::HttpServer.
260 exit(0);
217 } 261 }
OLDNEW
« no previous file with comments | « chrome/test/chromedriver/fake_session_accessor.cc ('k') | chrome/test/chromedriver/server/http_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698