Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / test / chromedriver / server / http_handler.cc
blob65f05ee941987a0673e8603c3218480a854ebab2
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
3 // found in the LICENSE file.
5 #include "chrome/test/chromedriver/server/http_handler.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h"
11 #include "base/logging.h" // For CHECK macros.
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/sys_info.h"
19 #include "base/values.h"
20 #include "chrome/test/chromedriver/alert_commands.h"
21 #include "chrome/test/chromedriver/chrome/adb_impl.h"
22 #include "chrome/test/chromedriver/chrome/device_manager.h"
23 #include "chrome/test/chromedriver/chrome/status.h"
24 #include "chrome/test/chromedriver/net/port_server.h"
25 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
26 #include "chrome/test/chromedriver/session.h"
27 #include "chrome/test/chromedriver/session_thread_map.h"
28 #include "chrome/test/chromedriver/util.h"
29 #include "chrome/test/chromedriver/version.h"
30 #include "net/server/http_server_request_info.h"
31 #include "net/server/http_server_response_info.h"
33 #if defined(OS_MACOSX)
34 #include "base/mac/scoped_nsautorelease_pool.h"
35 #endif
37 namespace {
39 const char kLocalStorage[] = "localStorage";
40 const char kSessionStorage[] = "sessionStorage";
41 const char kShutdownPath[] = "shutdown";
43 void UnimplementedCommand(
44 const base::DictionaryValue& params,
45 const std::string& session_id,
46 const CommandCallback& callback) {
47 callback.Run(Status(kUnknownCommand), scoped_ptr<base::Value>(), session_id);
50 } // namespace
52 CommandMapping::CommandMapping(HttpMethod method,
53 const std::string& path_pattern,
54 const Command& command)
55 : method(method), path_pattern(path_pattern), command(command) {}
57 CommandMapping::~CommandMapping() {}
59 HttpHandler::HttpHandler(const std::string& url_base)
60 : url_base_(url_base),
61 received_shutdown_(false),
62 command_map_(new CommandMap()),
63 weak_ptr_factory_(this) {}
65 HttpHandler::HttpHandler(
66 const base::Closure& quit_func,
67 const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
68 const std::string& url_base,
69 int adb_port,
70 scoped_ptr<PortServer> port_server)
71 : quit_func_(quit_func),
72 url_base_(url_base),
73 received_shutdown_(false),
74 weak_ptr_factory_(this) {
75 #if defined(OS_MACOSX)
76 base::mac::ScopedNSAutoreleasePool autorelease_pool;
77 #endif
78 context_getter_ = new URLRequestContextGetter(io_task_runner);
79 socket_factory_ = CreateSyncWebSocketFactory(context_getter_.get());
80 adb_.reset(new AdbImpl(io_task_runner, adb_port));
81 device_manager_.reset(new DeviceManager(adb_.get()));
82 port_server_ = port_server.Pass();
83 port_manager_.reset(new PortManager(12000, 13000));
85 CommandMapping commands[] = {
86 CommandMapping(
87 kPost,
88 internal::kNewSessionPathPattern,
89 base::Bind(&ExecuteCreateSession,
90 &session_thread_map_,
91 WrapToCommand(
92 "InitSession",
93 base::Bind(&ExecuteInitSession,
94 InitSessionParams(context_getter_,
95 socket_factory_,
96 device_manager_.get(),
97 port_server_.get(),
98 port_manager_.get()))))),
99 CommandMapping(kGet,
100 "sessions",
101 base::Bind(&ExecuteGetSessions,
102 WrapToCommand("GetSessions",
103 base::Bind(&ExecuteGetSessionCapabilities)),
104 &session_thread_map_)),
105 CommandMapping(kGet,
106 "session/:sessionId",
107 WrapToCommand("GetSessionCapabilities",
108 base::Bind(&ExecuteGetSessionCapabilities))),
109 CommandMapping(kDelete,
110 "session/:sessionId",
111 base::Bind(&ExecuteSessionCommand,
112 &session_thread_map_,
113 "Quit",
114 base::Bind(&ExecuteQuit, false),
115 true)),
116 CommandMapping(kGet,
117 "session/:sessionId/window_handle",
118 WrapToCommand("GetWindow",
119 base::Bind(&ExecuteGetCurrentWindowHandle))),
120 CommandMapping(
121 kGet,
122 "session/:sessionId/window_handles",
123 WrapToCommand("GetWindows", base::Bind(&ExecuteGetWindowHandles))),
124 CommandMapping(kPost,
125 "session/:sessionId/url",
126 WrapToCommand("Navigate", base::Bind(&ExecuteGet))),
127 CommandMapping(kPost,
128 "session/:sessionId/chromium/launch_app",
129 WrapToCommand("LaunchApp", base::Bind(&ExecuteLaunchApp))),
130 CommandMapping(kGet,
131 "session/:sessionId/alert",
132 WrapToCommand("IsAlertOpen",
133 base::Bind(&ExecuteAlertCommand,
134 base::Bind(&ExecuteGetAlert)))),
135 CommandMapping(
136 kPost,
137 "session/:sessionId/dismiss_alert",
138 WrapToCommand("DismissAlert",
139 base::Bind(&ExecuteAlertCommand,
140 base::Bind(&ExecuteDismissAlert)))),
141 CommandMapping(
142 kPost,
143 "session/:sessionId/accept_alert",
144 WrapToCommand("AcceptAlert",
145 base::Bind(&ExecuteAlertCommand,
146 base::Bind(&ExecuteAcceptAlert)))),
147 CommandMapping(
148 kGet,
149 "session/:sessionId/alert_text",
150 WrapToCommand("GetAlertMessage",
151 base::Bind(&ExecuteAlertCommand,
152 base::Bind(&ExecuteGetAlertText)))),
153 CommandMapping(
154 kPost,
155 "session/:sessionId/alert_text",
156 WrapToCommand("SetAlertPrompt",
157 base::Bind(&ExecuteAlertCommand,
158 base::Bind(&ExecuteSetAlertValue)))),
159 CommandMapping(kPost,
160 "session/:sessionId/forward",
161 WrapToCommand("GoForward", base::Bind(&ExecuteGoForward))),
162 CommandMapping(kPost,
163 "session/:sessionId/back",
164 WrapToCommand("GoBack", base::Bind(&ExecuteGoBack))),
165 CommandMapping(kPost,
166 "session/:sessionId/refresh",
167 WrapToCommand("Refresh", base::Bind(&ExecuteRefresh))),
168 CommandMapping(
169 kPost,
170 "session/:sessionId/execute",
171 WrapToCommand("ExecuteScript", base::Bind(&ExecuteExecuteScript))),
172 CommandMapping(kPost,
173 "session/:sessionId/execute_async",
174 WrapToCommand("ExecuteAsyncScript",
175 base::Bind(&ExecuteExecuteAsyncScript))),
176 CommandMapping(
177 kGet,
178 "session/:sessionId/url",
179 WrapToCommand("GetUrl", base::Bind(&ExecuteGetCurrentUrl))),
180 CommandMapping(kGet,
181 "session/:sessionId/title",
182 WrapToCommand("GetTitle", base::Bind(&ExecuteGetTitle))),
183 CommandMapping(
184 kGet,
185 "session/:sessionId/source",
186 WrapToCommand("GetSource", base::Bind(&ExecuteGetPageSource))),
187 CommandMapping(
188 kGet,
189 "session/:sessionId/screenshot",
190 WrapToCommand("Screenshot", base::Bind(&ExecuteScreenshot))),
191 CommandMapping(
192 kGet,
193 "session/:sessionId/chromium/heap_snapshot",
194 WrapToCommand("HeapSnapshot", base::Bind(&ExecuteTakeHeapSnapshot))),
195 CommandMapping(kPost,
196 "session/:sessionId/visible",
197 base::Bind(&UnimplementedCommand)),
198 CommandMapping(kGet,
199 "session/:sessionId/visible",
200 base::Bind(&UnimplementedCommand)),
201 CommandMapping(
202 kPost,
203 "session/:sessionId/element",
204 WrapToCommand("FindElement", base::Bind(&ExecuteFindElement, 50))),
205 CommandMapping(
206 kPost,
207 "session/:sessionId/elements",
208 WrapToCommand("FindElements", base::Bind(&ExecuteFindElements, 50))),
209 CommandMapping(kPost,
210 "session/:sessionId/element/active",
211 WrapToCommand("GetActiveElement",
212 base::Bind(&ExecuteGetActiveElement))),
213 CommandMapping(kPost,
214 "session/:sessionId/element/:id/element",
215 WrapToCommand("FindChildElement",
216 base::Bind(&ExecuteFindChildElement, 50))),
217 CommandMapping(kPost,
218 "session/:sessionId/element/:id/elements",
219 WrapToCommand("FindChildElements",
220 base::Bind(&ExecuteFindChildElements, 50))),
221 CommandMapping(
222 kPost,
223 "session/:sessionId/element/:id/click",
224 WrapToCommand("ClickElement", base::Bind(&ExecuteClickElement))),
225 CommandMapping(
226 kPost,
227 "session/:sessionId/element/:id/clear",
228 WrapToCommand("ClearElement", base::Bind(&ExecuteClearElement))),
229 CommandMapping(
230 kPost,
231 "session/:sessionId/element/:id/submit",
232 WrapToCommand("SubmitElement", base::Bind(&ExecuteSubmitElement))),
233 CommandMapping(
234 kGet,
235 "session/:sessionId/element/:id/text",
236 WrapToCommand("GetElementText", base::Bind(&ExecuteGetElementText))),
237 CommandMapping(
238 kPost,
239 "session/:sessionId/element/:id/value",
240 WrapToCommand("TypeElement", base::Bind(&ExecuteSendKeysToElement))),
241 CommandMapping(
242 kPost,
243 "session/:sessionId/file",
244 WrapToCommand("UploadFile", base::Bind(&ExecuteUploadFile))),
245 CommandMapping(kGet,
246 "session/:sessionId/element/:id/value",
247 WrapToCommand("GetElementValue",
248 base::Bind(&ExecuteGetElementValue))),
249 CommandMapping(kGet,
250 "session/:sessionId/element/:id/name",
251 WrapToCommand("GetElementTagName",
252 base::Bind(&ExecuteGetElementTagName))),
253 CommandMapping(kGet,
254 "session/:sessionId/element/:id/selected",
255 WrapToCommand("IsElementSelected",
256 base::Bind(&ExecuteIsElementSelected))),
257 CommandMapping(kGet,
258 "session/:sessionId/element/:id/enabled",
259 WrapToCommand("IsElementEnabled",
260 base::Bind(&ExecuteIsElementEnabled))),
261 CommandMapping(kGet,
262 "session/:sessionId/element/:id/displayed",
263 WrapToCommand("IsElementDisplayed",
264 base::Bind(&ExecuteIsElementDisplayed))),
265 CommandMapping(
266 kPost,
267 "session/:sessionId/element/:id/hover",
268 WrapToCommand("HoverElement", base::Bind(&ExecuteHoverOverElement))),
269 CommandMapping(kGet,
270 "session/:sessionId/element/:id/location",
271 WrapToCommand("GetElementLocation",
272 base::Bind(&ExecuteGetElementLocation))),
273 CommandMapping(
274 kGet,
275 "session/:sessionId/element/:id/location_in_view",
276 WrapToCommand(
277 "GetElementLocationInView",
278 base::Bind(&ExecuteGetElementLocationOnceScrolledIntoView))),
279 CommandMapping(
280 kGet,
281 "session/:sessionId/element/:id/size",
282 WrapToCommand("GetElementSize", base::Bind(&ExecuteGetElementSize))),
283 CommandMapping(kGet,
284 "session/:sessionId/element/:id/attribute/:name",
285 WrapToCommand("GetElementAttribute",
286 base::Bind(&ExecuteGetElementAttribute))),
287 CommandMapping(
288 kGet,
289 "session/:sessionId/element/:id/equals/:other",
290 WrapToCommand("IsElementEqual", base::Bind(&ExecuteElementEquals))),
291 CommandMapping(
292 kGet,
293 "session/:sessionId/cookie",
294 WrapToCommand("GetCookies", base::Bind(&ExecuteGetCookies))),
295 CommandMapping(kPost,
296 "session/:sessionId/cookie",
297 WrapToCommand("AddCookie", base::Bind(&ExecuteAddCookie))),
298 CommandMapping(kDelete,
299 "session/:sessionId/cookie",
300 WrapToCommand("DeleteAllCookies",
301 base::Bind(&ExecuteDeleteAllCookies))),
302 CommandMapping(
303 kDelete,
304 "session/:sessionId/cookie/:name",
305 WrapToCommand("DeleteCookie", base::Bind(&ExecuteDeleteCookie))),
306 CommandMapping(
307 kPost,
308 "session/:sessionId/frame",
309 WrapToCommand("SwitchToFrame", base::Bind(&ExecuteSwitchToFrame))),
310 CommandMapping(
311 kPost,
312 "session/:sessionId/frame/parent",
313 WrapToCommand("SwitchToParentFrame",
314 base::Bind(&ExecuteSwitchToParentFrame))),
315 CommandMapping(
316 kPost,
317 "session/:sessionId/window",
318 WrapToCommand("SwitchToWindow", base::Bind(&ExecuteSwitchToWindow))),
319 CommandMapping(
320 kGet,
321 "session/:sessionId/window/:windowHandle/size",
322 WrapToCommand("GetWindowSize", base::Bind(&ExecuteGetWindowSize))),
323 CommandMapping(kGet,
324 "session/:sessionId/window/:windowHandle/position",
325 WrapToCommand("GetWindowPosition",
326 base::Bind(&ExecuteGetWindowPosition))),
327 CommandMapping(
328 kPost,
329 "session/:sessionId/window/:windowHandle/size",
330 WrapToCommand("SetWindowSize", base::Bind(&ExecuteSetWindowSize))),
331 CommandMapping(kPost,
332 "session/:sessionId/window/:windowHandle/position",
333 WrapToCommand("SetWindowPosition",
334 base::Bind(&ExecuteSetWindowPosition))),
335 CommandMapping(
336 kPost,
337 "session/:sessionId/window/:windowHandle/maximize",
338 WrapToCommand("MaximizeWindow", base::Bind(&ExecuteMaximizeWindow))),
339 CommandMapping(kDelete,
340 "session/:sessionId/window",
341 WrapToCommand("CloseWindow", base::Bind(&ExecuteClose))),
342 CommandMapping(kPost,
343 "session/:sessionId/element/:id/drag",
344 base::Bind(&UnimplementedCommand)),
345 CommandMapping(
346 kGet,
347 "session/:sessionId/element/:id/css/:propertyName",
348 WrapToCommand("GetElementCSSProperty",
349 base::Bind(&ExecuteGetElementValueOfCSSProperty))),
350 CommandMapping(
351 kPost,
352 "session/:sessionId/timeouts/implicit_wait",
353 WrapToCommand("SetImplicitWait", base::Bind(&ExecuteImplicitlyWait))),
354 CommandMapping(kPost,
355 "session/:sessionId/timeouts/async_script",
356 WrapToCommand("SetScriptTimeout",
357 base::Bind(&ExecuteSetScriptTimeout))),
358 CommandMapping(
359 kPost,
360 "session/:sessionId/timeouts",
361 WrapToCommand("SetTimeout", base::Bind(&ExecuteSetTimeout))),
362 CommandMapping(kPost,
363 "session/:sessionId/execute_sql",
364 base::Bind(&UnimplementedCommand)),
365 CommandMapping(
366 kGet,
367 "session/:sessionId/location",
368 WrapToCommand("GetGeolocation", base::Bind(&ExecuteGetLocation))),
369 CommandMapping(
370 kPost,
371 "session/:sessionId/location",
372 WrapToCommand("SetGeolocation", base::Bind(&ExecuteSetLocation))),
373 CommandMapping(
374 kGet,
375 "session/:sessionId/chromium/network_conditions",
376 WrapToCommand("GetNetworkConditions",
377 base::Bind(&ExecuteGetNetworkConditions))),
378 CommandMapping(
379 kPost,
380 "session/:sessionId/chromium/network_conditions",
381 WrapToCommand("SetNetworkConditions",
382 base::Bind(&ExecuteSetNetworkConditions))),
383 CommandMapping(
384 kDelete,
385 "session/:sessionId/chromium/network_conditions",
386 WrapToCommand("DeleteNetworkConditions",
387 base::Bind(&ExecuteDeleteNetworkConditions))),
388 CommandMapping(kGet,
389 "session/:sessionId/application_cache/status",
390 base::Bind(&ExecuteGetStatus)),
391 CommandMapping(kGet,
392 "session/:sessionId/browser_connection",
393 base::Bind(&UnimplementedCommand)),
394 CommandMapping(kPost,
395 "session/:sessionId/browser_connection",
396 base::Bind(&UnimplementedCommand)),
397 CommandMapping(
398 kGet,
399 "session/:sessionId/local_storage/key/:key",
400 WrapToCommand("GetLocalStorageItem",
401 base::Bind(&ExecuteGetStorageItem, kLocalStorage))),
402 CommandMapping(
403 kDelete,
404 "session/:sessionId/local_storage/key/:key",
405 WrapToCommand("RemoveLocalStorageItem",
406 base::Bind(&ExecuteRemoveStorageItem, kLocalStorage))),
407 CommandMapping(
408 kGet,
409 "session/:sessionId/local_storage",
410 WrapToCommand("GetLocalStorageKeys",
411 base::Bind(&ExecuteGetStorageKeys, kLocalStorage))),
412 CommandMapping(
413 kPost,
414 "session/:sessionId/local_storage",
415 WrapToCommand("SetLocalStorageKeys",
416 base::Bind(&ExecuteSetStorageItem, kLocalStorage))),
417 CommandMapping(
418 kDelete,
419 "session/:sessionId/local_storage",
420 WrapToCommand("ClearLocalStorage",
421 base::Bind(&ExecuteClearStorage, kLocalStorage))),
422 CommandMapping(
423 kGet,
424 "session/:sessionId/local_storage/size",
425 WrapToCommand("GetLocalStorageSize",
426 base::Bind(&ExecuteGetStorageSize, kLocalStorage))),
427 CommandMapping(
428 kGet,
429 "session/:sessionId/session_storage/key/:key",
430 WrapToCommand("GetSessionStorageItem",
431 base::Bind(&ExecuteGetStorageItem, kSessionStorage))),
432 CommandMapping(kDelete,
433 "session/:sessionId/session_storage/key/:key",
434 WrapToCommand("RemoveSessionStorageItem",
435 base::Bind(&ExecuteRemoveStorageItem,
436 kSessionStorage))),
437 CommandMapping(
438 kGet,
439 "session/:sessionId/session_storage",
440 WrapToCommand("GetSessionStorageKeys",
441 base::Bind(&ExecuteGetStorageKeys, kSessionStorage))),
442 CommandMapping(
443 kPost,
444 "session/:sessionId/session_storage",
445 WrapToCommand("SetSessionStorageItem",
446 base::Bind(&ExecuteSetStorageItem, kSessionStorage))),
447 CommandMapping(
448 kDelete,
449 "session/:sessionId/session_storage",
450 WrapToCommand("ClearSessionStorage",
451 base::Bind(&ExecuteClearStorage, kSessionStorage))),
452 CommandMapping(
453 kGet,
454 "session/:sessionId/session_storage/size",
455 WrapToCommand("GetSessionStorageSize",
456 base::Bind(&ExecuteGetStorageSize, kSessionStorage))),
457 CommandMapping(kGet,
458 "session/:sessionId/orientation",
459 base::Bind(&UnimplementedCommand)),
460 CommandMapping(kPost,
461 "session/:sessionId/orientation",
462 base::Bind(&UnimplementedCommand)),
463 CommandMapping(kPost,
464 "session/:sessionId/click",
465 WrapToCommand("Click", base::Bind(&ExecuteMouseClick))),
466 CommandMapping(
467 kPost,
468 "session/:sessionId/doubleclick",
469 WrapToCommand("DoubleClick", base::Bind(&ExecuteMouseDoubleClick))),
470 CommandMapping(
471 kPost,
472 "session/:sessionId/buttondown",
473 WrapToCommand("MouseDown", base::Bind(&ExecuteMouseButtonDown))),
474 CommandMapping(
475 kPost,
476 "session/:sessionId/buttonup",
477 WrapToCommand("MouseUp", base::Bind(&ExecuteMouseButtonUp))),
478 CommandMapping(
479 kPost,
480 "session/:sessionId/moveto",
481 WrapToCommand("MouseMove", base::Bind(&ExecuteMouseMoveTo))),
482 CommandMapping(
483 kPost,
484 "session/:sessionId/keys",
485 WrapToCommand("Type", base::Bind(&ExecuteSendKeysToActiveElement))),
486 CommandMapping(kGet,
487 "session/:sessionId/ime/available_engines",
488 base::Bind(&UnimplementedCommand)),
489 CommandMapping(kGet,
490 "session/:sessionId/ime/active_engine",
491 base::Bind(&UnimplementedCommand)),
492 CommandMapping(kGet,
493 "session/:sessionId/ime/activated",
494 base::Bind(&UnimplementedCommand)),
495 CommandMapping(kPost,
496 "session/:sessionId/ime/deactivate",
497 base::Bind(&UnimplementedCommand)),
498 CommandMapping(kPost,
499 "session/:sessionId/ime/activate",
500 base::Bind(&UnimplementedCommand)),
501 CommandMapping(kPost,
502 "session/:sessionId/touch/click",
503 WrapToCommand("Tap", base::Bind(&ExecuteTouchSingleTap))),
504 CommandMapping(kPost,
505 "session/:sessionId/touch/down",
506 WrapToCommand("TouchDown", base::Bind(&ExecuteTouchDown))),
507 CommandMapping(kPost,
508 "session/:sessionId/touch/up",
509 WrapToCommand("TouchUp", base::Bind(&ExecuteTouchUp))),
510 CommandMapping(kPost,
511 "session/:sessionId/touch/move",
512 WrapToCommand("TouchMove", base::Bind(&ExecuteTouchMove))),
513 CommandMapping(kPost,
514 "session/:sessionId/touch/scroll",
515 base::Bind(&UnimplementedCommand)),
516 CommandMapping(kPost,
517 "session/:sessionId/touch/doubleclick",
518 base::Bind(&UnimplementedCommand)),
519 CommandMapping(kPost,
520 "session/:sessionId/touch/longclick",
521 base::Bind(&UnimplementedCommand)),
522 CommandMapping(kPost,
523 "session/:sessionId/touch/flick",
524 WrapToCommand("TouchFlick", base::Bind(&ExecuteFlick))),
525 CommandMapping(kPost,
526 "session/:sessionId/log",
527 WrapToCommand("GetLog", base::Bind(&ExecuteGetLog))),
528 CommandMapping(kGet,
529 "session/:sessionId/log/types",
530 WrapToCommand("GetLogTypes",
531 base::Bind(&ExecuteGetAvailableLogTypes))),
532 CommandMapping(kPost, "logs", base::Bind(&UnimplementedCommand)),
533 CommandMapping(kGet, "status", base::Bind(&ExecuteGetStatus)),
535 // Custom Chrome commands:
536 // Allow quit all to be called with GET or POST.
537 CommandMapping(
538 kGet,
539 kShutdownPath,
540 base::Bind(&ExecuteQuitAll,
541 WrapToCommand("QuitAll", base::Bind(&ExecuteQuit, true)),
542 &session_thread_map_)),
543 CommandMapping(
544 kPost,
545 kShutdownPath,
546 base::Bind(&ExecuteQuitAll,
547 WrapToCommand("QuitAll", base::Bind(&ExecuteQuit, true)),
548 &session_thread_map_)),
549 CommandMapping(kGet,
550 "session/:sessionId/is_loading",
551 WrapToCommand("IsLoading", base::Bind(&ExecuteIsLoading))),
552 CommandMapping(kGet,
553 "session/:sessionId/autoreport",
554 WrapToCommand("IsAutoReporting",
555 base::Bind(&ExecuteIsAutoReporting))),
556 CommandMapping(kPost,
557 "session/:sessionId/autoreport",
558 WrapToCommand(
559 "SetAutoReporting",
560 base::Bind(&ExecuteSetAutoReporting))),
562 command_map_.reset(
563 new CommandMap(commands, commands + arraysize(commands)));
566 HttpHandler::~HttpHandler() {}
568 void HttpHandler::Handle(const net::HttpServerRequestInfo& request,
569 const HttpResponseSenderFunc& send_response_func) {
570 CHECK(thread_checker_.CalledOnValidThread());
572 if (received_shutdown_)
573 return;
575 std::string path = request.path;
576 if (!StartsWithASCII(path, url_base_, true)) {
577 scoped_ptr<net::HttpServerResponseInfo> response(
578 new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
579 response->SetBody("unhandled request", "text/plain");
580 send_response_func.Run(response.Pass());
581 return;
584 path.erase(0, url_base_.length());
586 HandleCommand(request, path, send_response_func);
588 if (path == kShutdownPath)
589 received_shutdown_ = true;
592 Command HttpHandler::WrapToCommand(
593 const char* name,
594 const SessionCommand& session_command) {
595 return base::Bind(&ExecuteSessionCommand,
596 &session_thread_map_,
597 name,
598 session_command,
599 false);
602 Command HttpHandler::WrapToCommand(
603 const char* name,
604 const WindowCommand& window_command) {
605 return WrapToCommand(name, base::Bind(&ExecuteWindowCommand, window_command));
608 Command HttpHandler::WrapToCommand(
609 const char* name,
610 const ElementCommand& element_command) {
611 return WrapToCommand(name,
612 base::Bind(&ExecuteElementCommand, element_command));
615 void HttpHandler::HandleCommand(
616 const net::HttpServerRequestInfo& request,
617 const std::string& trimmed_path,
618 const HttpResponseSenderFunc& send_response_func) {
619 base::DictionaryValue params;
620 std::string session_id;
621 CommandMap::const_iterator iter = command_map_->begin();
622 while (true) {
623 if (iter == command_map_->end()) {
624 scoped_ptr<net::HttpServerResponseInfo> response(
625 new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
626 response->SetBody("unknown command: " + trimmed_path, "text/plain");
627 send_response_func.Run(response.Pass());
628 return;
630 if (internal::MatchesCommand(
631 request.method, trimmed_path, *iter, &session_id, &params)) {
632 break;
634 ++iter;
637 if (request.data.length()) {
638 base::DictionaryValue* body_params;
639 scoped_ptr<base::Value> parsed_body(base::JSONReader::Read(request.data));
640 if (!parsed_body || !parsed_body->GetAsDictionary(&body_params)) {
641 scoped_ptr<net::HttpServerResponseInfo> response(
642 new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
643 response->SetBody("missing command parameters", "text/plain");
644 send_response_func.Run(response.Pass());
645 return;
647 params.MergeDictionary(body_params);
650 iter->command.Run(params,
651 session_id,
652 base::Bind(&HttpHandler::PrepareResponse,
653 weak_ptr_factory_.GetWeakPtr(),
654 trimmed_path,
655 send_response_func));
658 void HttpHandler::PrepareResponse(
659 const std::string& trimmed_path,
660 const HttpResponseSenderFunc& send_response_func,
661 const Status& status,
662 scoped_ptr<base::Value> value,
663 const std::string& session_id) {
664 CHECK(thread_checker_.CalledOnValidThread());
665 scoped_ptr<net::HttpServerResponseInfo> response =
666 PrepareResponseHelper(trimmed_path, status, value.Pass(), session_id);
667 send_response_func.Run(response.Pass());
668 if (trimmed_path == kShutdownPath)
669 quit_func_.Run();
672 scoped_ptr<net::HttpServerResponseInfo> HttpHandler::PrepareResponseHelper(
673 const std::string& trimmed_path,
674 const Status& status,
675 scoped_ptr<base::Value> value,
676 const std::string& session_id) {
677 if (status.code() == kUnknownCommand) {
678 scoped_ptr<net::HttpServerResponseInfo> response(
679 new net::HttpServerResponseInfo(net::HTTP_NOT_IMPLEMENTED));
680 response->SetBody("unimplemented command: " + trimmed_path, "text/plain");
681 return response.Pass();
684 if (status.IsError()) {
685 Status full_status(status);
686 full_status.AddDetails(base::StringPrintf(
687 "Driver info: chromedriver=%s,platform=%s %s %s",
688 kChromeDriverVersion,
689 base::SysInfo::OperatingSystemName().c_str(),
690 base::SysInfo::OperatingSystemVersion().c_str(),
691 base::SysInfo::OperatingSystemArchitecture().c_str()));
692 scoped_ptr<base::DictionaryValue> error(new base::DictionaryValue());
693 error->SetString("message", full_status.message());
694 value.reset(error.release());
696 if (!value)
697 value.reset(base::Value::CreateNullValue());
699 base::DictionaryValue body_params;
700 body_params.SetInteger("status", status.code());
701 body_params.Set("value", value.release());
702 body_params.SetString("sessionId", session_id);
703 std::string body;
704 base::JSONWriter::WriteWithOptions(
705 &body_params, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION,
706 &body);
707 scoped_ptr<net::HttpServerResponseInfo> response(
708 new net::HttpServerResponseInfo(net::HTTP_OK));
709 response->SetBody(body, "application/json; charset=utf-8");
710 return response.Pass();
713 namespace internal {
715 const char kNewSessionPathPattern[] = "session";
717 bool MatchesMethod(HttpMethod command_method, const std::string& method) {
718 std::string lower_method = base::StringToLowerASCII(method);
719 switch (command_method) {
720 case kGet:
721 return lower_method == "get";
722 case kPost:
723 return lower_method == "post" || lower_method == "put";
724 case kDelete:
725 return lower_method == "delete";
727 return false;
730 bool MatchesCommand(const std::string& method,
731 const std::string& path,
732 const CommandMapping& command,
733 std::string* session_id,
734 base::DictionaryValue* out_params) {
735 if (!MatchesMethod(command.method, method))
736 return false;
738 std::vector<std::string> path_parts;
739 base::SplitString(path, '/', &path_parts);
740 std::vector<std::string> command_path_parts;
741 base::SplitString(command.path_pattern, '/', &command_path_parts);
742 if (path_parts.size() != command_path_parts.size())
743 return false;
745 base::DictionaryValue params;
746 for (size_t i = 0; i < path_parts.size(); ++i) {
747 CHECK(command_path_parts[i].length());
748 if (command_path_parts[i][0] == ':') {
749 std::string name = command_path_parts[i];
750 name.erase(0, 1);
751 CHECK(name.length());
752 if (name == "sessionId")
753 *session_id = path_parts[i];
754 else
755 params.SetString(name, path_parts[i]);
756 } else if (command_path_parts[i] != path_parts[i]) {
757 return false;
760 out_params->MergeDictionary(&params);
761 return true;
764 } // namespace internal