http_handler.cc revision 868fa2fe829687343ffae624259930155e16dbd8
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/server/http_handler.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_reader.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/log.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/command_executor.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/command_names.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/server/http_response.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kShutdownPath[] = "shutdown";
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpRequest::HttpRequest(HttpMethod method,
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& path,
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& body)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : method(method), path(path), body(body) {}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpRequest::~HttpRequest() {}
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CommandMapping::CommandMapping(HttpMethod method,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const std::string& path_pattern,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const std::string& name)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : method(method), path_pattern(path_pattern), name(name) {}
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CommandMapping::~CommandMapping() {}
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<HttpHandler::CommandMap> HttpHandler::CreateCommandMap() {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CommandMapping commands[] = {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session", CommandNames::kNewSession),
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId",
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetSessionCapabilities),
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId", CommandNames::kQuit),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/window_handle",
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetCurrentWindowHandle),
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/window_handles",
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetWindowHandles),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/url", CommandNames::kGet),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/alert", CommandNames::kGetAlert),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/dismiss_alert",
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kDismissAlert),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/accept_alert",
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kAcceptAlert),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/alert_text",
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetAlertText),
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/alert_text",
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetAlertValue),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/forward",
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGoForward),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/back", CommandNames::kGoBack),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/refresh",
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kRefresh),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/execute",
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kExecuteScript),
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/execute_async",
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kExecuteAsyncScript),
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/url",
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetCurrentUrl),
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/title", CommandNames::kGetTitle),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/source",
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetPageSource),
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/screenshot",
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kScreenshot),
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/visible",
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetBrowserVisible),
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/visible",
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kIsBrowserVisible),
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element",
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kFindElement),
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/elements",
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kFindElements),
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/active",
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetActiveElement),
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/element",
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kFindChildElement),
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/elements",
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kFindChildElements),
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/click",
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kClickElement),
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/clear",
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kClearElement),
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/submit",
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSubmitElement),
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/text",
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementText),
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/value",
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSendKeysToElement),
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/file",
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kUploadFile),
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/value",
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementValue),
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/name",
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementTagName),
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/selected",
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kIsElementSelected),
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/enabled",
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kIsElementEnabled),
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/displayed",
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kIsElementDisplayed),
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/hover",
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kHoverOverElement),
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/location",
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementLocation),
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/location_in_view",
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementLocationOnceScrolledIntoView),
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/size",
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementSize),
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/attribute/:name",
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementAttribute),
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/equals/:other",
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kElementEquals),
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/cookie",
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetCookies),
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/cookie",
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kAddCookie),
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/cookie",
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kDeleteAllCookies),
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/cookie/:name",
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kDeleteCookie),
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/frame",
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSwitchToFrame),
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/window",
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSwitchToWindow),
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/window/:windowHandle/size",
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetWindowSize),
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/window/:windowHandle/position",
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetWindowPosition),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/window/:windowHandle/size",
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetWindowSize),
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/window/:windowHandle/position",
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetWindowPosition),
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/window/:windowHandle/maximize",
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kMaximizeWindow),
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/window",
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kClose),
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/element/:id/drag",
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kDragElement),
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/element/:id/css/:propertyName",
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetElementValueOfCssProperty),
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/timeouts/implicit_wait",
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kImplicitlyWait),
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/timeouts/async_script",
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetScriptTimeout),
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/timeouts",
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetTimeout),
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/execute_sql",
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kExecuteSQL),
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/location",
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetLocation),
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/location",
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetLocation),
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/application_cache/status",
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetStatus),
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/browser_connection",
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kIsBrowserOnline),
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/browser_connection",
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetBrowserOnline),
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/local_storage/key/:key",
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetLocalStorageItem),
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/local_storage/key/:key",
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kRemoveLocalStorageItem),
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/local_storage",
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetLocalStorageKeys),
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/local_storage",
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetLocalStorageItem),
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/local_storage",
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kClearLocalStorage),
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/local_storage/size",
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetLocalStorageSize),
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/session_storage/key/:key",
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetSessionStorageItem),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/session_storage/key/:key",
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kRemoveSessionStorageItem),
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/session_storage",
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetSessionStorageKey),
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/session_storage",
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetSessionStorageItem),
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kDelete, "session/:sessionId/session_storage",
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kClearSessionStorage),
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/session_storage/size",
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetSessionStorageSize),
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/orientation",
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetScreenOrientation),
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/orientation",
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSetScreenOrientation),
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/click",
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kMouseClick),
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/doubleclick",
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kMouseDoubleClick),
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/buttondown",
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kMouseButtonDown),
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/buttonup",
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kMouseButtonUp),
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/moveto",
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kMouseMoveTo),
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/keys",
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kSendKeysToActiveElement),
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/ime/available_engines",
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kImeGetAvailableEngines),
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/ime/active_engine",
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kImeGetActiveEngine),
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/ime/activated",
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kImeIsActivated),
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/ime/deactivate",
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kImeDeactivate),
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/ime/activate",
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kImeActivateEngine),
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/click",
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchSingleTap),
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/down",
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchDown),
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/up",
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchUp),
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/move",
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchMove),
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/scroll",
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchScroll),
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/doubleclick",
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchDoubleTap),
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/longclick",
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchLongPress),
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/touch/flick",
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kTouchFlick),
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "session/:sessionId/log", CommandNames::kGetLog),
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/log/types",
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     CommandNames::kGetAvailableLogTypes),
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, "logs", CommandNames::kGetSessionLogs),
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, "status", CommandNames::kStatus),
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Custom Chrome commands:
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Allow quit all to be called with GET or POST.
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kGet, kShutdownPath, CommandNames::kQuitAll),
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandMapping(kPost, kShutdownPath, CommandNames::kQuitAll),
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      CommandMapping(kGet, "session/:sessionId/is_loading",
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     CommandNames::kIsLoading),
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return scoped_ptr<CommandMap>(
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new CommandMap(commands, commands + arraysize(commands)));
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)HttpHandler::HttpHandler(Log* log,
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         scoped_ptr<CommandExecutor> executor,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         scoped_ptr<CommandMap> command_map,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const std::string& url_base)
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : log_(log),
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      executor_(executor.Pass()),
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      command_map_(command_map.Pass()),
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_base_(url_base) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  executor_->Init();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpHandler::~HttpHandler() {}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpHandler::Handle(const HttpRequest& request,
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         HttpResponse* response) {
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char* method = "GET";
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (request.method == kPost)
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    method = "POST";
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else if (request.method == kDelete)
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    method = "DELETE";
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  log_->AddEntry(
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Log::kLog,
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("received WebDriver request: %s %s %s",
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         method,
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         request.path.c_str(),
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         request.body.c_str()));
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HandleInternal(request, response);
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  log_->AddEntry(
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Log::kLog,
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("sending WebDriver response: %d %s",
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         response->status(),
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         response->body().c_str()));
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool HttpHandler::ShouldShutdown(const HttpRequest& request) {
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return request.path == url_base_ + kShutdownPath;
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HttpHandler::HandleInternal(const HttpRequest& request,
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                 HttpResponse* response) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string path = request.path;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!StartsWithASCII(path, url_base_, true)) {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *response = HttpResponse(HttpResponse::kBadRequest);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response->set_body("unhandled request");
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  path.erase(0, url_base_.length());
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!HandleWebDriverCommand(request, path, response)) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *response = HttpResponse(HttpResponse::kNotFound);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response->set_body("unknown command: " + path);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HttpHandler::HandleWebDriverCommand(
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const HttpRequest& request,
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& trimmed_path,
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    HttpResponse* response) {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string session_id;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CommandMap::const_iterator iter = command_map_->begin();
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (true) {
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (iter == command_map_->end()) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (internal::MatchesCommand(
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            request.method, trimmed_path, *iter, &session_id, &params)) {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++iter;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request.method == kPost && request.body.length()) {
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue* body_params;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value> parsed_body(base::JSONReader::Read(request.body));
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!parsed_body || !parsed_body->GetAsDictionary(&body_params)) {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *response = HttpResponse(HttpResponse::kBadRequest);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      response->set_body("missing command parameters");
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.MergeDictionary(body_params);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StatusCode status = kOk;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string out_session_id;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  executor_->ExecuteCommand(
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iter->name, params, session_id, &status, &value, &out_session_id);
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status == kUnknownCommand) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *response = HttpResponse(HttpResponse::kNotImplemented);
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response->set_body("unimplemented command: " + iter->name);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter->name == CommandNames::kNewSession && status == kOk) {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Creating a session involves a HTTP request to /session, which is
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // supposed to redirect to /session/:sessionId, which returns the
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // session info.
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *response = HttpResponse(HttpResponse::kSeeOther);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response->AddHeader("Location", url_base_ + "session/" + out_session_id);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue body_params;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  body_params.SetInteger("status", status);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  body_params.Set("value", value.release());
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  body_params.SetString("sessionId", out_session_id);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string body;
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::JSONWriter::WriteWithOptions(
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &body_params, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION,
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &body);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *response = HttpResponse(HttpResponse::kOk);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  response->SetMimeType("application/json; charset=utf-8");
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  response->set_body(body);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MatchesCommand(HttpMethod method,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& path,
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const CommandMapping& command,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    std::string* session_id,
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    base::DictionaryValue* out_params) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (method != command.method)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> path_parts;
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SplitString(path, '/', &path_parts);
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> command_path_parts;
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SplitString(command.path_pattern, '/', &command_path_parts);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (path_parts.size() != command_path_parts.size())
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < path_parts.size(); ++i) {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(command_path_parts[i].length());
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (command_path_parts[i][0] == ':') {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string name = command_path_parts[i];
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      name.erase(0, 1);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK(name.length());
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (name == "sessionId")
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *session_id = path_parts[i];
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        params.SetString(name, path_parts[i]);
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (command_path_parts[i] != path_parts[i]) {
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  out_params->MergeDictionary(&params);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
414