| Index: chrome/test/webdriver/dispatch.cc
|
| diff --git a/chrome/test/webdriver/dispatch.cc b/chrome/test/webdriver/dispatch.cc
|
| index f1bfb77720770121e6e970108ce5f51897ac3eec..8f73ddfc045cd411d9da7edd88925ed3d9f45885 100644
|
| --- a/chrome/test/webdriver/dispatch.cc
|
| +++ b/chrome/test/webdriver/dispatch.cc
|
| @@ -9,7 +9,9 @@
|
| #include <vector>
|
|
|
| #include "base/format_macros.h"
|
| +#include "base/json/json_reader.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| #include "base/message_loop_proxy.h"
|
| #include "base/string_split.h"
|
| #include "base/string_util.h"
|
| @@ -20,11 +22,16 @@
|
| #include "chrome/test/webdriver/commands/command.h"
|
| #include "chrome/test/webdriver/session_manager.h"
|
| #include "chrome/test/webdriver/utility_functions.h"
|
| +#include "chrome/test/webdriver/webdriver_logging.h"
|
|
|
| namespace webdriver {
|
|
|
| namespace {
|
|
|
| +// Maximum safe size of HTTP response message. Any larger than this,
|
| +// the message may not be transferred at all.
|
| +const int kMaxHttpMessageSize = 1024 * 1024 * 16; // 16MB
|
| +
|
| bool ForbidsMessageBody(const std::string& request_method,
|
| const HttpResponse& response) {
|
| return request_method == "HEAD" ||
|
| @@ -59,15 +66,40 @@ void Shutdown(struct mg_connection* connection,
|
| shutdown_event->Signal();
|
| }
|
|
|
| -void SendStatus(struct mg_connection* connection,
|
| - const struct mg_request_info* request_info,
|
| - void* user_data) {
|
| - std::string response = "HTTP/1.1 200 OK\r\n"
|
| - "Content-Length:2\r\n\r\n"
|
| - "ok";
|
| +void SendOkWithBody(struct mg_connection* connection,
|
| + const std::string& content) {
|
| + const char* response_fmt = "HTTP/1.1 200 OK\r\n"
|
| + "Content-Length:%d\r\n\r\n"
|
| + "%s";
|
| + std::string response = base::StringPrintf(
|
| + response_fmt, content.length(), content.c_str());
|
| mg_write(connection, response.data(), response.length());
|
| }
|
|
|
| +void SendHealthz(struct mg_connection* connection,
|
| + const struct mg_request_info* request_info,
|
| + void* user_data) {
|
| + SendOkWithBody(connection, "ok");
|
| +}
|
| +
|
| +void SendLog(struct mg_connection* connection,
|
| + const struct mg_request_info* request_info,
|
| + void* user_data) {
|
| + std::string content, log;
|
| + if (GetLogContents(&log)) {
|
| + content = "START ChromeDriver log";
|
| + const int kMaxSizeWithoutHeaders = kMaxHttpMessageSize - 10000;
|
| + if (log.size() > kMaxSizeWithoutHeaders) {
|
| + log = log.substr(log.size() - kMaxSizeWithoutHeaders);
|
| + content += " (only last several MB)";
|
| + }
|
| + content += ":\n" + log + "END ChromeDriver log";
|
| + } else {
|
| + content = "No ChromeDriver log found";
|
| + }
|
| + SendOkWithBody(connection, content);
|
| +}
|
| +
|
| void SendNoContentResponse(struct mg_connection* connection,
|
| const struct mg_request_info* request_info,
|
| void* user_data) {
|
| @@ -99,7 +131,6 @@ void SendNotImplementedError(struct mg_connection* connection,
|
| "Content-Length:%" PRIuS "\r\n"
|
| "\r\n", body.length());
|
|
|
| - LOG(ERROR) << header << body;
|
| mg_write(connection, header.data(), header.length());
|
| mg_write(connection, body.data(), body.length());
|
| }
|
| @@ -225,18 +256,24 @@ bool ParseRequestInfo(const struct mg_request_info* const request_info,
|
| base::SplitString(uri, '/', path_segments);
|
|
|
| if (*method == "POST" && request_info->post_data_len > 0) {
|
| - VLOG(1) << "...parsing request body";
|
| std::string json(request_info->post_data, request_info->post_data_len);
|
| - std::string error;
|
| - if (!ParseJSONDictionary(json, parameters, &error)) {
|
| + std::string error_msg;
|
| + scoped_ptr<Value> params(base::JSONReader::ReadAndReturnError(
|
| + json, true, NULL, &error_msg));
|
| + if (!params.get()) {
|
| response->SetError(new Error(
|
| kBadRequest,
|
| - "Failed to parse command data: " + error + "\n Data: " + json));
|
| + "Failed to parse command data: " + error_msg + "\n Data: " + json));
|
| return false;
|
| }
|
| + if (!params->IsType(Value::TYPE_DICTIONARY)) {
|
| + response->SetError(new Error(
|
| + kBadRequest,
|
| + "Data passed in URL must be a dictionary. Data: " + json));
|
| + return false;
|
| + }
|
| + *parameters = static_cast<DictionaryValue*>(params.release());
|
| }
|
| - VLOG(1) << "Parsed " << method << " " << uri
|
| - << std::string(request_info->post_data, request_info->post_data_len);
|
| return true;
|
| }
|
|
|
| @@ -283,8 +320,12 @@ void Dispatcher::AddShutdown(const std::string& pattern,
|
| shutdown_event);
|
| }
|
|
|
| -void Dispatcher::AddStatus(const std::string& pattern) {
|
| - mg_set_uri_callback(context_, (root_ + pattern).c_str(), &SendStatus, NULL);
|
| +void Dispatcher::AddHealthz(const std::string& pattern) {
|
| + mg_set_uri_callback(context_, (root_ + pattern).c_str(), &SendHealthz, NULL);
|
| +}
|
| +
|
| +void Dispatcher::AddLog(const std::string& pattern) {
|
| + mg_set_uri_callback(context_, (root_ + pattern).c_str(), &SendLog, NULL);
|
| }
|
|
|
| void Dispatcher::SetNotImplemented(const std::string& pattern) {
|
|
|