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

Side by Side Diff: chrome/test/webdriver/dispatch.cc

Issue 7104085: In chromedriver, add /log handler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 6 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
« no previous file with comments | « chrome/test/webdriver/dispatch.h ('k') | chrome/test/webdriver/keymap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/test/webdriver/dispatch.h" 5 #include "chrome/test/webdriver/dispatch.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/format_macros.h" 11 #include "base/format_macros.h"
12 #include "base/json/json_reader.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop_proxy.h" 15 #include "base/message_loop_proxy.h"
14 #include "base/string_split.h" 16 #include "base/string_split.h"
15 #include "base/string_util.h" 17 #include "base/string_util.h"
16 #include "base/stringprintf.h" 18 #include "base/stringprintf.h"
17 #include "base/synchronization/waitable_event.h" 19 #include "base/synchronization/waitable_event.h"
18 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
19 #include "chrome/test/webdriver/http_response.h" 21 #include "chrome/test/webdriver/http_response.h"
20 #include "chrome/test/webdriver/commands/command.h" 22 #include "chrome/test/webdriver/commands/command.h"
21 #include "chrome/test/webdriver/session_manager.h" 23 #include "chrome/test/webdriver/session_manager.h"
22 #include "chrome/test/webdriver/utility_functions.h" 24 #include "chrome/test/webdriver/utility_functions.h"
25 #include "chrome/test/webdriver/webdriver_logging.h"
23 26
24 namespace webdriver { 27 namespace webdriver {
25 28
26 namespace { 29 namespace {
27 30
31 // Maximum safe size of HTTP response message. Any larger than this,
32 // the message may not be transferred at all.
33 const size_t kMaxHttpMessageSize = 1024 * 1024 * 16; // 16MB
34
28 bool ForbidsMessageBody(const std::string& request_method, 35 bool ForbidsMessageBody(const std::string& request_method,
29 const HttpResponse& response) { 36 const HttpResponse& response) {
30 return request_method == "HEAD" || 37 return request_method == "HEAD" ||
31 response.status() == HttpResponse::kNoContent || 38 response.status() == HttpResponse::kNoContent ||
32 response.status() == HttpResponse::kNotModified || 39 response.status() == HttpResponse::kNotModified ||
33 (response.status() >= 100 && response.status() < 200); 40 (response.status() >= 100 && response.status() < 200);
34 } 41 }
35 42
36 void DispatchCommand(Command* const command, 43 void DispatchCommand(Command* const command,
37 const std::string& method, 44 const std::string& method,
(...skipping 14 matching lines...) Expand all
52 59
53 void Shutdown(struct mg_connection* connection, 60 void Shutdown(struct mg_connection* connection,
54 const struct mg_request_info* request_info, 61 const struct mg_request_info* request_info,
55 void* user_data) { 62 void* user_data) {
56 base::WaitableEvent* shutdown_event = 63 base::WaitableEvent* shutdown_event =
57 reinterpret_cast<base::WaitableEvent*>(user_data); 64 reinterpret_cast<base::WaitableEvent*>(user_data);
58 mg_printf(connection, "HTTP/1.1 200 OK\r\n\r\n"); 65 mg_printf(connection, "HTTP/1.1 200 OK\r\n\r\n");
59 shutdown_event->Signal(); 66 shutdown_event->Signal();
60 } 67 }
61 68
62 void SendStatus(struct mg_connection* connection, 69 void SendOkWithBody(struct mg_connection* connection,
63 const struct mg_request_info* request_info, 70 const std::string& content) {
64 void* user_data) { 71 const char* response_fmt = "HTTP/1.1 200 OK\r\n"
65 std::string response = "HTTP/1.1 200 OK\r\n" 72 "Content-Length:%d\r\n\r\n"
66 "Content-Length:2\r\n\r\n" 73 "%s";
67 "ok"; 74 std::string response = base::StringPrintf(
75 response_fmt, content.length(), content.c_str());
68 mg_write(connection, response.data(), response.length()); 76 mg_write(connection, response.data(), response.length());
69 } 77 }
70 78
79 void SendHealthz(struct mg_connection* connection,
80 const struct mg_request_info* request_info,
81 void* user_data) {
82 SendOkWithBody(connection, "ok");
83 }
84
85 void SendLog(struct mg_connection* connection,
86 const struct mg_request_info* request_info,
87 void* user_data) {
88 std::string content, log;
89 if (GetLogContents(&log)) {
90 content = "START ChromeDriver log";
91 const size_t kMaxSizeWithoutHeaders = kMaxHttpMessageSize - 10000;
92 if (log.size() > kMaxSizeWithoutHeaders) {
93 log = log.substr(log.size() - kMaxSizeWithoutHeaders);
94 content += " (only last several MB)";
95 }
96 content += ":\n" + log + "END ChromeDriver log";
97 } else {
98 content = "No ChromeDriver log found";
99 }
100 SendOkWithBody(connection, content);
101 }
102
71 void SendNoContentResponse(struct mg_connection* connection, 103 void SendNoContentResponse(struct mg_connection* connection,
72 const struct mg_request_info* request_info, 104 const struct mg_request_info* request_info,
73 void* user_data) { 105 void* user_data) {
74 std::string response = "HTTP/1.1 204 No Content\r\n" 106 std::string response = "HTTP/1.1 204 No Content\r\n"
75 "Content-Length:0\r\n" 107 "Content-Length:0\r\n"
76 "\r\n"; 108 "\r\n";
77 mg_write(connection, response.data(), response.length()); 109 mg_write(connection, response.data(), response.length());
78 } 110 }
79 111
80 void SendForbidden(struct mg_connection* connection, 112 void SendForbidden(struct mg_connection* connection,
(...skipping 11 matching lines...) Expand all
92 "{\"status\":%d,\"value\":{\"message\":" 124 "{\"status\":%d,\"value\":{\"message\":"
93 "\"Command has not been implemented yet: %s %s\"}}", 125 "\"Command has not been implemented yet: %s %s\"}}",
94 kUnknownCommand, request_info->request_method, request_info->uri); 126 kUnknownCommand, request_info->request_method, request_info->uri);
95 127
96 std::string header = base::StringPrintf( 128 std::string header = base::StringPrintf(
97 "HTTP/1.1 501 Not Implemented\r\n" 129 "HTTP/1.1 501 Not Implemented\r\n"
98 "Content-Type:application/json\r\n" 130 "Content-Type:application/json\r\n"
99 "Content-Length:%" PRIuS "\r\n" 131 "Content-Length:%" PRIuS "\r\n"
100 "\r\n", body.length()); 132 "\r\n", body.length());
101 133
102 LOG(ERROR) << header << body;
103 mg_write(connection, header.data(), header.length()); 134 mg_write(connection, header.data(), header.length());
104 mg_write(connection, body.data(), body.length()); 135 mg_write(connection, body.data(), body.length());
105 } 136 }
106 137
107 } // namespace 138 } // namespace
108 139
109 namespace internal { 140 namespace internal {
110 141
111 void PrepareHttpResponse(const Response& command_response, 142 void PrepareHttpResponse(const Response& command_response,
112 HttpResponse* const http_response) { 143 HttpResponse* const http_response) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 else if (*method == "PUT") 249 else if (*method == "PUT")
219 *method = "POST"; 250 *method = "POST";
220 251
221 std::string uri(request_info->uri); 252 std::string uri(request_info->uri);
222 SessionManager* manager = SessionManager::GetInstance(); 253 SessionManager* manager = SessionManager::GetInstance();
223 uri = uri.substr(manager->url_base().length()); 254 uri = uri.substr(manager->url_base().length());
224 255
225 base::SplitString(uri, '/', path_segments); 256 base::SplitString(uri, '/', path_segments);
226 257
227 if (*method == "POST" && request_info->post_data_len > 0) { 258 if (*method == "POST" && request_info->post_data_len > 0) {
228 VLOG(1) << "...parsing request body";
229 std::string json(request_info->post_data, request_info->post_data_len); 259 std::string json(request_info->post_data, request_info->post_data_len);
230 std::string error; 260 std::string error_msg;
231 if (!ParseJSONDictionary(json, parameters, &error)) { 261 scoped_ptr<Value> params(base::JSONReader::ReadAndReturnError(
262 json, true, NULL, &error_msg));
263 if (!params.get()) {
232 response->SetError(new Error( 264 response->SetError(new Error(
233 kBadRequest, 265 kBadRequest,
234 "Failed to parse command data: " + error + "\n Data: " + json)); 266 "Failed to parse command data: " + error_msg + "\n Data: " + json));
235 return false; 267 return false;
236 } 268 }
237 } 269 if (!params->IsType(Value::TYPE_DICTIONARY)) {
238 VLOG(1) << "Parsed " << method << " " << uri 270 response->SetError(new Error(
239 << std::string(request_info->post_data, request_info->post_data_len); 271 kBadRequest,
272 "Data passed in URL must be a dictionary. Data: " + json));
273 return false;
274 }
275 *parameters = static_cast<DictionaryValue*>(params.release());
276 }
240 return true; 277 return true;
241 } 278 }
242 279
243 void DispatchHelper(Command* command_ptr, 280 void DispatchHelper(Command* command_ptr,
244 const std::string& method, 281 const std::string& method,
245 Response* response) { 282 Response* response) {
246 CHECK(method == "GET" || method == "POST" || method == "DELETE"); 283 CHECK(method == "GET" || method == "POST" || method == "DELETE");
247 scoped_ptr<Command> command(command_ptr); 284 scoped_ptr<Command> command(command_ptr);
248 285
249 if ((method == "GET" && !command->DoesGet()) || 286 if ((method == "GET" && !command->DoesGet()) ||
(...skipping 26 matching lines...) Expand all
276 } 313 }
277 314
278 Dispatcher::~Dispatcher() {} 315 Dispatcher::~Dispatcher() {}
279 316
280 void Dispatcher::AddShutdown(const std::string& pattern, 317 void Dispatcher::AddShutdown(const std::string& pattern,
281 base::WaitableEvent* shutdown_event) { 318 base::WaitableEvent* shutdown_event) {
282 mg_set_uri_callback(context_, (root_ + pattern).c_str(), &Shutdown, 319 mg_set_uri_callback(context_, (root_ + pattern).c_str(), &Shutdown,
283 shutdown_event); 320 shutdown_event);
284 } 321 }
285 322
286 void Dispatcher::AddStatus(const std::string& pattern) { 323 void Dispatcher::AddHealthz(const std::string& pattern) {
287 mg_set_uri_callback(context_, (root_ + pattern).c_str(), &SendStatus, NULL); 324 mg_set_uri_callback(context_, (root_ + pattern).c_str(), &SendHealthz, NULL);
325 }
326
327 void Dispatcher::AddLog(const std::string& pattern) {
328 mg_set_uri_callback(context_, (root_ + pattern).c_str(), &SendLog, NULL);
288 } 329 }
289 330
290 void Dispatcher::SetNotImplemented(const std::string& pattern) { 331 void Dispatcher::SetNotImplemented(const std::string& pattern) {
291 mg_set_uri_callback(context_, (root_ + pattern).c_str(), 332 mg_set_uri_callback(context_, (root_ + pattern).c_str(),
292 &SendNotImplementedError, NULL); 333 &SendNotImplementedError, NULL);
293 } 334 }
294 335
295 void Dispatcher::ForbidAllOtherRequests() { 336 void Dispatcher::ForbidAllOtherRequests() {
296 mg_set_uri_callback(context_, "*", &SendForbidden, NULL); 337 mg_set_uri_callback(context_, "*", &SendForbidden, NULL);
297 } 338 }
298 339
299 } // namespace webdriver 340 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/dispatch.h ('k') | chrome/test/webdriver/keymap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698