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/window_commands.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list>
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <string>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/basic_types.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/automation_extension.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/chrome.h"
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/geoposition.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/js.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/ui_events.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/web_view.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/element_util.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/session.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/util.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetMouseButton(const base::DictionaryValue& params,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      MouseButton* button) {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int button_num;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetInteger("button", &button_num)) {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    button_num = 0;  // Default to left mouse button.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (button_num < 0 || button_num > 2) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  base::StringPrintf("invalid button: %d", button_num));
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *button = static_cast<MouseButton>(button_num);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetUrl(WebView* web_view, const std::string& frame, std::string* url) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = web_view->CallFunction(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame, "function() { return document.URL; }", args, &value);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!value->GetAsString(url))
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "javascript failed to return the url");
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct Cookie {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Cookie(const std::string& name,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         const std::string& value,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         const std::string& domain,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         const std::string& path,
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         double expiry,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         bool secure,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         bool session)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : name(name), value(value), domain(domain), path(path), expiry(expiry),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        secure(secure), session(session) {}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string name;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string value;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string domain;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string path;
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  double expiry;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool secure;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool session;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::DictionaryValue* CreateDictionaryFrom(const Cookie& cookie) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("name", cookie.name);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("value", cookie.value);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cookie.domain.empty())
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetString("domain", cookie.domain);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cookie.path.empty())
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->SetString("path", cookie.path);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cookie.session)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    dict->SetDouble("expiry", cookie.expiry);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetBoolean("secure", cookie.secure);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dict;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetVisibleCookies(WebView* web_view,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         std::list<Cookie>* cookies) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> internal_cookies;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = web_view->GetCookies(&internal_cookies);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<Cookie> cookies_tmp;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < internal_cookies->GetSize(); ++i) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue* cookie_dict;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!internal_cookies->GetDictionary(i, &cookie_dict))
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kUnknownError, "DevTools returns a non-dictionary cookie");
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string name;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_dict->GetString("name", &name);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string value;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_dict->GetString("value", &value);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string domain;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_dict->GetString("domain", &domain);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string path;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_dict->GetString("path", &path);
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    double expiry = 0;
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cookie_dict->GetDouble("expires", &expiry);
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    expiry /= 1000;  // Convert from millisecond to second.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool session = false;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_dict->GetBoolean("session", &session);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool secure = false;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_dict->GetBoolean("secure", &secure);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookies_tmp.push_back(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Cookie(name, value, domain, path, expiry, secure, session));
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cookies->swap(cookies_tmp);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Status ScrollCoordinateInToView(
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Session* session, WebView* web_view, int x, int y, int* offset_x,
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int* offset_y) {
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<base::Value> value;
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::ListValue args;
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  args.AppendInteger(x);
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  args.AppendInteger(y);
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Status status = web_view->CallFunction(
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      std::string(),
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "function(x, y) {"
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "  if (x < window.pageXOffset ||"
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "      x >= window.pageXOffset + window.innerWidth ||"
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "      y < window.pageYOffset ||"
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "      y >= window.pageYOffset + window.innerHeight) {"
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "    window.scrollTo(x - window.innerWidth/2, y - window.innerHeight/2);"
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "  }"
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "  return {"
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "    view_x: Math.floor(window.pageXOffset),"
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "    view_y: Math.floor(window.pageYOffset),"
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "    view_width: Math.floor(window.innerWidth),"
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "    view_height: Math.floor(window.innerHeight)};"
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "}",
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      args,
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &value);
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!status.IsOk())
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return status;
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::DictionaryValue* view_attrib;
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  value->GetAsDictionary(&view_attrib);
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int view_x, view_y, view_width, view_height;
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  view_attrib->GetInteger("view_x", &view_x);
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  view_attrib->GetInteger("view_y", &view_y);
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  view_attrib->GetInteger("view_width", &view_width);
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  view_attrib->GetInteger("view_height", &view_height);
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *offset_x = x - view_x;
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *offset_y = y - view_y;
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (*offset_x < 0 || *offset_x >= view_width || *offset_y < 0 ||
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *offset_y >= view_height)
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Status(kUnknownError, "Failed to scroll coordinate into view");
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Status(kOk);
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Status ExecuteTouchEvent(
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Session* session, WebView* web_view, TouchEventType type,
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::DictionaryValue& params) {
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int x, y;
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!params.GetInteger("x", &x))
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Status(kUnknownError, "'x' must be an integer");
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!params.GetInteger("y", &y))
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Status(kUnknownError, "'y' must be an integer");
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int relative_x = x;
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int relative_y = y;
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Status status = ScrollCoordinateInToView(
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      session, web_view, x, y, &relative_x, &relative_y);
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!status.IsOk())
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return status;
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::list<TouchEvent> events;
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  events.push_back(
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      TouchEvent(type, relative_x, relative_y));
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return web_view->DispatchTouchEvents(events);
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteWindowCommand(
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const WindowCommand& command,
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WebView* web_view = NULL;
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status = session->GetTargetWindow(&web_view);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  status = web_view->ConnectIfNecessary();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  status = web_view->HandleReceivedEvents();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (web_view->GetJavaScriptDialogManager()->IsDialogOpen())
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnexpectedAlertOpen);
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status nav_status(kOk);
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (int attempt = 0; attempt < 2; attempt++) {
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (attempt == 1) {
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (status.code() == kNoSuchExecutionContext)
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // Switch to main frame and retry command if subframe no longer exists.
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        session->SwitchToTopFrame();
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      else
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    nav_status = web_view->WaitForPendingNavigations(
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        session->GetCurrentFrameId(), session->page_load_timeout, true);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (nav_status.IsError())
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return nav_status;
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = command.Run(session, web_view, params, value);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  nav_status = web_view->WaitForPendingNavigations(
229424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      session->GetCurrentFrameId(), session->page_load_timeout, true);
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsOk() && nav_status.IsError() &&
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      nav_status.code() != kUnexpectedAlertOpen)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return nav_status;
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status.code() == kUnexpectedAlertOpen)
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kOk);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return status;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGet(
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string url;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("url", &url))
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'url' must be a string");
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->Load(url);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteExecuteScript(
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string script;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("script", &script))
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'script' must be a string");
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (script == ":takeHeapSnapshot") {
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return web_view->TakeHeapSnapshot(value);
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (script == ":startProfile") {
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return web_view->StartProfile();
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (script == ":endProfile") {
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return web_view->EndProfile(value);
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } else {
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::ListValue* args;
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!params.GetList("args", &args))
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return Status(kUnknownError, "'args' must be a list");
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return web_view->CallFunction(session->GetCurrentFrameId(),
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                  "function(){" + script + "}", *args, value);
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteExecuteAsyncScript(
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string script;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("script", &script))
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'script' must be a string");
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::ListValue* args;
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.GetList("args", &args))
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'args' must be a list");
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return web_view->CallUserAsyncFunction(
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session->GetCurrentFrameId(), "function(){" + script + "}", *args,
288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      session->script_timeout, value);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteSwitchToFrame(
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Value* id;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.Get("id", &id))
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "missing 'id'");
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id->IsType(base::Value::TYPE_NULL)) {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session->SwitchToTopFrame();
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kOk);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string script;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* id_dict;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id->GetAsDictionary(&id_dict)) {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    script = "function(elem) { return elem; }";
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    args.Append(id_dict->DeepCopy());
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    script =
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "function(xpath) {"
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "  return document.evaluate(xpath, document, null, "
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "      XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "}";
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string xpath = "(/html/body//iframe|/html/frameset/frame)";
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string id_string;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int id_int;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (id->GetAsString(&id_string)) {
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xpath += base::StringPrintf(
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "[@name=\"%s\" or @id=\"%s\"]", id_string.c_str(), id_string.c_str());
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (id->GetAsInteger(&id_int)) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      xpath += base::StringPrintf("[%d]", id_int + 1);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kUnknownError, "invalid 'id'");
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    args.Append(new base::StringValue(xpath));
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string frame;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = web_view->GetFrameByFunction(
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(), script, args, &frame);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> result;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = web_view->CallFunction(
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(), script, args, &result);
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* element;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetAsDictionary(&element))
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "fail to locate the sub frame element");
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string chrome_driver_id = GenerateId();
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kSetFrameIdentifier =
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "function(frame, id) {"
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  frame.setAttribute('cd_frame_id_', id);"
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}";
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue new_args;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_args.Append(element->DeepCopy());
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_args.AppendString(chrome_driver_id);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result.reset(NULL);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = web_view->CallFunction(
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(), kSetFrameIdentifier, new_args, &result);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session->SwitchToSubFrame(frame, chrome_driver_id);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochStatus ExecuteSwitchToParentFrame(
363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Session* session,
364a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    WebView* web_view,
365a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const base::DictionaryValue& params,
366a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    scoped_ptr<base::Value>* value) {
367a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  session->SwitchToParentFrame();
368a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return Status(kOk);
369a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
370a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetTitle(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kGetTitleScript =
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "function() {"
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  if (document.title)"
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "    return document.title;"
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  else"
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "    return document.URL;"
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}";
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return web_view->CallFunction(std::string(), kGetTitleScript, args, value);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetPageSource(
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* kGetPageSource =
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "function() {"
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  return new XMLSerializer().serializeToString(document);"
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}";
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(), kGetPageSource, args, value);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteFindElement(
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int interval_ms,
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return FindElement(interval_ms, true, NULL, session, web_view, params, value);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteFindElements(
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int interval_ms,
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return FindElement(
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      interval_ms, false, NULL, session, web_view, params, value);
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetCurrentUrl(
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string url;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetUrl(web_view, session->GetCurrentFrameId(), &url);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  value->reset(new base::StringValue(url));
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGoBack(
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return web_view->EvaluateScript(
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string(), "window.history.back();", value);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGoForward(
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return web_view->EvaluateScript(
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string(), "window.history.forward();", value);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteRefresh(
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->Reload();
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteMouseMoveTo(
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string element_id;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_element = params.GetString("element", &element_id);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x_offset = 0;
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int y_offset = 0;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_offset = params.GetInteger("xoffset", &x_offset) &&
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.GetInteger("yoffset", &y_offset);
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!has_element && !has_offset)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "at least an element or offset should be set");
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebPoint location;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_element) {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = ScrollElementIntoView(
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        session, web_view, element_id, &location);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    location = session->mouse_position;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_offset) {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    location.Offset(x_offset, y_offset);
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebSize size;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = GetElementSize(session, web_view, element_id, &size);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    location.Offset(size.width / 2, size.height / 2);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<MouseEvent> events;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kMovedMouseEventType, kNoneMouseButton,
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 location.x, location.y, session->sticky_modifiers, 0));
497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Status status =
498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsOk())
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session->mouse_position = location;
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return status;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteMouseClick(
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MouseButton button;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetMouseButton(params, &button);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<MouseEvent> events;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kPressedMouseEventType, button,
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->mouse_position.x, session->mouse_position.y,
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->sticky_modifiers, 1));
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kReleasedMouseEventType, button,
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->mouse_position.x, session->mouse_position.y,
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->sticky_modifiers, 1));
522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteMouseButtonDown(
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MouseButton button;
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetMouseButton(params, &button);
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<MouseEvent> events;
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kPressedMouseEventType, button,
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->mouse_position.x, session->mouse_position.y,
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->sticky_modifiers, 1));
539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteMouseButtonUp(
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MouseButton button;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetMouseButton(params, &button);
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<MouseEvent> events;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kReleasedMouseEventType, button,
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->mouse_position.x, session->mouse_position.y,
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->sticky_modifiers, 1));
556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteMouseDoubleClick(
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MouseButton button;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetMouseButton(params, &button);
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<MouseEvent> events;
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kPressedMouseEventType, button,
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->mouse_position.x, session->mouse_position.y,
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->sticky_modifiers, 2));
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseEvent(kReleasedMouseEventType, button,
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->mouse_position.x, session->mouse_position.y,
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 session->sticky_modifiers, 2));
577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Status ExecuteTouchDown(
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Session* session,
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    WebView* web_view,
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::DictionaryValue& params,
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<base::Value>* value) {
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return ExecuteTouchEvent(session, web_view, kTouchStart, params);
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Status ExecuteTouchUp(
5893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Session* session,
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    WebView* web_view,
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::DictionaryValue& params,
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<base::Value>* value) {
5933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return ExecuteTouchEvent(session, web_view, kTouchEnd, params);
5943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Status ExecuteTouchMove(
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Session* session,
5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    WebView* web_view,
5993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::DictionaryValue& params,
6003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<base::Value>* value) {
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return ExecuteTouchEvent(session, web_view, kTouchMove, params);
6023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetActiveElement(
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return GetActiveElement(session, web_view, value);
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status ExecuteSendKeysToActiveElement(
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Session* session,
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebView* web_view,
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& params,
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::ListValue* key_list;
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.GetList("value", &key_list))
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "'value' must be a list");
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SendKeysOnWindow(
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      web_view, key_list, false, &session->sticky_modifiers);
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetAppCacheStatus(
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->EvaluateScript(
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "applicationCache.status",
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteIsBrowserOnline(
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->EvaluateScript(
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "navigator.onLine",
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetStorageItem(
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* storage,
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string key;
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("key", &key))
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'key' must be a string");
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(new base::StringValue(key));
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("function(key) { return %s[key]; }", storage),
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetStorageKeys(
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* storage,
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char script[] =
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "var keys = [];"
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "for (var key in %s) {"
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  keys.push(key);"
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "}"
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "keys";
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->EvaluateScript(
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf(script, storage),
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteSetStorageItem(
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* storage,
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string key;
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("key", &key))
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'key' must be a string");
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string storage_value;
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("value", &storage_value))
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'value' must be a string");
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(new base::StringValue(key));
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(new base::StringValue(storage_value));
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("function(key, value) { %s[key] = value; }", storage),
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteRemoveStorageItem(
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* storage,
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string key;
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("key", &key))
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'key' must be a string");
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(new base::StringValue(key));
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("function(key) { %s.removeItem(key) }", storage),
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteClearStorage(
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* storage,
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->EvaluateScript(
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%s.clear()", storage),
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetStorageSize(
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* storage,
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->EvaluateScript(
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%s.length", storage),
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteScreenshot(
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
751424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Status status = session->chrome->ActivateWebView(web_view->GetId());
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
754424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
755424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string screenshot;
7561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (session->chrome->GetAsDesktop() && !session->force_devtools_screenshot) {
757424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    AutomationExtension* extension = NULL;
7581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    status =
7591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        session->chrome->GetAsDesktop()->GetAutomationExtension(&extension);
760424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (status.IsError())
761424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return status;
762424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    status = extension->CaptureScreenshot(&screenshot);
76358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // If the screenshot was forbidden, fallback to DevTools.
76458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (status.code() == kForbidden)
76558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      status = web_view->CaptureScreenshot(&screenshot);
766424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else {
76758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    status = web_view->CaptureScreenshot(&screenshot);
768424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
76958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (status.IsError())
77058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return status;
77158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  value->reset(new base::StringValue(screenshot));
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetCookies(
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<Cookie> cookies;
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetVisibleCookies(web_view, &cookies);
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> cookie_list(new base::ListValue());
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<Cookie>::const_iterator it = cookies.begin();
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != cookies.end(); ++it) {
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cookie_list->Append(CreateDictionaryFrom(*it));
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  value->reset(cookie_list.release());
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteAddCookie(
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* cookie;
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetDictionary("cookie", &cookie))
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "missing 'cookie'");
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(cookie->DeepCopy());
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> result;
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(), kAddCookieScript, args, &result);
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteDeleteCookie(
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string name;
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("name", &name))
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "missing 'name'");
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params_url;
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> value_url;
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string url;
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetUrl(web_view, session->GetCurrentFrameId(), &url);
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->DeleteCookie(name, url);
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteDeleteAllCookies(
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<Cookie> cookies;
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetVisibleCookies(web_view, &cookies);
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cookies.empty()) {
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params_url;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value> value_url;
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string url;
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = GetUrl(web_view, session->GetCurrentFrameId(), &url);
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (std::list<Cookie>::const_iterator it = cookies.begin();
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         it != cookies.end(); ++it) {
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      status = web_view->DeleteCookie(it->name, url);
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (status.IsError())
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return status;
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status ExecuteSetLocation(
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Session* session,
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebView* web_view,
857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& params,
858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::DictionaryValue* location = NULL;
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Geoposition geoposition;
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.GetDictionary("location", &location) ||
862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !location->GetDouble("latitude", &geoposition.latitude) ||
863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !location->GetDouble("longitude", &geoposition.longitude))
864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "missing or invalid 'location'");
865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (location->HasKey("accuracy") &&
866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !location->GetDouble("accuracy", &geoposition.accuracy)) {
867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "invalid 'accuracy'");
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // |accuracy| is not part of the WebDriver spec yet, so if it is not given
870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // default to 100 meters accuracy.
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    geoposition.accuracy = 100;
872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = web_view->OverrideGeolocation(geoposition);
875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsOk())
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    session->overridden_geoposition.reset(new Geoposition(geoposition));
877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return status;
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
8791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
8801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)Status ExecuteTakeHeapSnapshot(
8811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    Session* session,
8821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    WebView* web_view,
8831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const base::DictionaryValue& params,
8841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<base::Value>* value) {
8851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return web_view->TakeHeapSnapshot(value);
8861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
887