Index: chrome/test/chromedriver/server/chromedriver_server.cc |
diff --git a/chrome/test/chromedriver/server/chromedriver_server.cc b/chrome/test/chromedriver/server/chromedriver_server.cc |
index 75cc9c2cab3fcc548dbb60eb7d0a13e42e75618e..1da71e8213be9cecb5b73201f0c7f8b65aafabec 100644 |
--- a/chrome/test/chromedriver/server/chromedriver_server.cc |
+++ b/chrome/test/chromedriver/server/chromedriver_server.cc |
@@ -7,14 +7,18 @@ |
#include <vector> |
#include "base/at_exit.h" |
+#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/files/file_path.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_util.h" |
#include "base/strings/stringprintf.h" |
#include "base/synchronization/waitable_event.h" |
+#include "base/threading/thread.h" |
#include "chrome/test/chromedriver/chrome/log.h" |
#include "chrome/test/chromedriver/chrome/version.h" |
#include "chrome/test/chromedriver/server/http_handler.h" |
@@ -29,6 +33,23 @@ |
namespace { |
+void SendHttpResponse(bool shutdown, |
+ const HttpResponseSenderFunc& send_response_func, |
+ scoped_ptr<HttpResponse> response) { |
+ send_response_func.Run(response.Pass()); |
+ if (shutdown) |
+ base::MessageLoop::current()->QuitWhenIdle(); |
+} |
+ |
+void HandleHttpRequest(HttpHandler* handler, |
+ const net::HttpServerRequestInfo& request, |
+ const HttpResponseSenderFunc& send_response_func) { |
+ handler->Handle(request, |
+ base::Bind(&SendHttpResponse, |
+ handler->ShouldShutdown(request), |
+ send_response_func)); |
+} |
+ |
void ReadRequestBody(const struct mg_request_info* const request_info, |
struct mg_connection* const connection, |
std::string* request_body) { |
@@ -56,11 +77,22 @@ void ReadRequestBody(const struct mg_request_info* const request_info, |
} |
} |
+typedef base::Callback< |
+ void(const net::HttpServerRequestInfo&, const HttpResponseSenderFunc&)> |
+ HttpRequestHandlerFunc; |
+ |
struct MongooseUserData { |
- HttpHandler* handler; |
- base::WaitableEvent* shutdown_event; |
+ base::SingleThreadTaskRunner* cmd_task_runner; |
+ HttpRequestHandlerFunc* handler_func; |
}; |
+void DoneProcessing(base::WaitableEvent* event, |
+ scoped_ptr<HttpResponse>* response_to_set, |
+ scoped_ptr<HttpResponse> response) { |
+ *response_to_set = response.Pass(); |
+ event->Signal(); |
+} |
+ |
void* ProcessHttpRequest(mg_event event_raised, |
struct mg_connection* connection, |
const struct mg_request_info* request_info) { |
@@ -74,16 +106,20 @@ void* ProcessHttpRequest(mg_event event_raised, |
request.path = request_info->uri; |
ReadRequestBody(request_info, connection, &request.data); |
- HttpResponse response; |
- user_data->handler->Handle(request, &response); |
+ base::WaitableEvent event(false, false); |
+ scoped_ptr<HttpResponse> response; |
+ user_data->cmd_task_runner |
+ ->PostTask(FROM_HERE, |
+ base::Bind(*user_data->handler_func, |
+ request, |
+ base::Bind(&DoneProcessing, &event, &response))); |
+ event.Wait(); |
// Don't allow HTTP keep alive. |
- response.AddHeader("connection", "close"); |
+ response->AddHeader("connection", "close"); |
std::string data; |
- response.GetData(&data); |
+ response->GetData(&data); |
mg_write(connection, data.data(), data.length()); |
- if (user_data->handler->ShouldShutdown(request)) |
- user_data->shutdown_event->Signal(); |
return reinterpret_cast<void*>(true); |
} |
@@ -103,7 +139,7 @@ void MakeMongooseOptions(const std::string& port, |
int main(int argc, char *argv[]) { |
CommandLine::Init(argc, argv); |
- base::AtExitManager exit; |
+ base::AtExitManager at_exit; |
CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
// Parse command line flags. |
@@ -175,10 +211,16 @@ int main(int argc, char *argv[]) { |
if (!cmd_line->HasSwitch("verbose")) |
logging::SetMinLogLevel(logging::LOG_FATAL); |
+ base::Thread io_thread("ChromeDriver IO"); |
+ CHECK(io_thread.StartWithOptions( |
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); |
+ |
scoped_ptr<Log> log(new Logger(log_level)); |
- HttpHandler handler(log.get(), url_base); |
- base::WaitableEvent shutdown_event(false, false); |
- MongooseUserData user_data = { &handler, &shutdown_event }; |
+ HttpHandler handler(io_thread.message_loop_proxy(), log.get(), url_base); |
+ base::MessageLoop cmd_loop; |
+ HttpRequestHandlerFunc handler_func = |
+ base::Bind(&HandleHttpRequest, &handler); |
+ MongooseUserData user_data = { cmd_loop.message_loop_proxy(), &handler_func }; |
std::vector<std::string> args; |
MakeMongooseOptions(port, http_threads, &args); |
@@ -210,8 +252,10 @@ int main(int argc, char *argv[]) { |
} |
#endif |
- // Run until we receive command to shutdown. |
- shutdown_event.Wait(); |
- |
- return 0; |
+ base::RunLoop cmd_run_loop; |
+ cmd_run_loop.Run(); |
+ // Don't run destructors for objects passed via MongooseUserData, |
+ // because ProcessHttpRequest may be accessing them. |
+ // TODO(kkania): Fix when switching to net::HttpServer. |
+ exit(0); |
} |