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/element_commands.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_split.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/platform_thread.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/basic_types.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/chrome.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/js.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/ui_events.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/web_view.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/element_util.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/session.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/chromedriver/util.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/webdriver/atoms.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status SendKeysToElement(
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ListValue* key_list) {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_displayed = false;
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool is_focused = false;
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::TimeTicks start_time = base::TimeTicks::Now();
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (true) {
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Status status = IsElementDisplayed(
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session, web_view, element_id, true, &is_displayed);
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status.IsError())
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return status;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (is_displayed)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    status = IsElementFocused(session, web_view, element_id, &is_focused);
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (status.IsError())
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return status;
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (is_focused)
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (base::TimeTicks::Now() - start_time >= session->implicit_wait) {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kElementNotVisible);
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_enabled = false;
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = IsElementEnabled(session, web_view, element_id, &is_enabled);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_enabled)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kInvalidElementState);
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!is_focused) {
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::ListValue args;
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    args.Append(CreateElement(element_id));
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<base::Value> result;
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    status = web_view->CallFunction(
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        session->GetCurrentFrameId(), kFocusScript, args, &result);
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (status.IsError())
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return status;
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SendKeysOnWindow(web_view, key_list, true, &session->sticky_modifiers);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochStatus ExecuteTouchSingleTapAtom(
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    Session* session,
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    WebView* web_view,
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const std::string& element_id,
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const base::DictionaryValue& params,
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<base::Value>* value) {
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::ListValue args;
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  args.Append(CreateElement(element_id));
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return web_view->CallFunction(
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      session->GetCurrentFrameId(),
86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      webdriver::atoms::asString(webdriver::atoms::TOUCH_SINGLE_TAP),
87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      args,
88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      value);
89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteElementCommand(
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ElementCommand& command,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string id;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (params.GetString("id", &id) || params.GetString("element", &id))
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return command.Run(session, web_view, id, params, value);
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Status(kUnknownError, "element identifier must be a string");
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteFindChildElement(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int interval_ms,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return FindElement(
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      interval_ms, true, &element_id, session, web_view, params, value);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteFindChildElements(
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int interval_ms,
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return FindElement(
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      interval_ms, false, &element_id, session, web_view, params, value);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteHoverOverElement(
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebPoint location;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetElementClickableLocation(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session, web_view, element_id, &location);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MouseEvent move_event(
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kMovedMouseEventType, kNoneMouseButton, location.x, location.y,
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session->sticky_modifiers, 0);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<MouseEvent> events;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  events.push_back(move_event);
144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  status = web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsOk())
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session->mouse_position = location;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return status;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteClickElement(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string tag_name;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetElementTagName(session, web_view, element_id, &tag_name);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tag_name == "option") {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_toggleable;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = IsOptionElementTogglable(
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        session, web_view, element_id, &is_toggleable);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (is_toggleable)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return ToggleOptionElement(session, web_view, element_id);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SetOptionElementSelected(session, web_view, element_id, true);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebPoint location;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = GetElementClickableLocation(
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        session, web_view, element_id, &location);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::list<MouseEvent> events;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    events.push_back(
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        MouseEvent(kMovedMouseEventType, kNoneMouseButton,
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   location.x, location.y, session->sticky_modifiers, 0));
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    events.push_back(
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        MouseEvent(kPressedMouseEventType, kLeftMouseButton,
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   location.x, location.y, session->sticky_modifiers, 1));
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    events.push_back(
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        MouseEvent(kReleasedMouseEventType, kLeftMouseButton,
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   location.x, location.y, session->sticky_modifiers, 1));
187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    status =
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsOk())
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->mouse_position = location;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status ExecuteTouchSingleTap(
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Session* session,
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebView* web_view,
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& element_id,
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& params,
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Fall back to javascript atom for pre-m30 Chrome.
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (session->chrome->GetBuildNo() < 1576)
203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteTouchSingleTapAtom(
204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        session, web_view, element_id, params, value);
205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  WebPoint location;
207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Status status = GetElementClickableLocation(
208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      session, web_view, element_id, &location);
209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (status.IsError())
210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return status;
211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::list<TouchEvent> events;
213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  events.push_back(
214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      TouchEvent(kTouchStart, location.x, location.y));
215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  events.push_back(
216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      TouchEvent(kTouchEnd, location.x, location.y));
217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return web_view->DispatchTouchEvents(events);
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteClearElement(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> result;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::CLEAR),
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args, &result);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteSendKeysToElement(
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::ListValue* key_list;
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.GetList("value", &key_list))
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'value' must be a list");
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_input = false;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = IsElementAttributeEqualToIgnoreCase(
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session, web_view, element_id, "tagName", "input", &is_input);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_file = false;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = IsElementAttributeEqualToIgnoreCase(
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session, web_view, element_id, "type", "file", &is_file);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_input && is_file) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Compress array into a single string.
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath::StringType paths_string;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t i = 0; i < key_list->GetSize(); ++i) {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath::StringType path_part;
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!key_list->GetString(i, &path_part))
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return Status(kUnknownError, "'value' is invalid");
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paths_string.append(path_part);
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Separate the string into separate paths, delimited by '\n'.
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<base::FilePath::StringType> path_strings;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::SplitString(paths_string, '\n', &path_strings);
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<base::FilePath> paths;
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t i = 0; i < path_strings.size(); ++i)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paths.push_back(base::FilePath(path_strings[i]));
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool multiple = false;
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    status = IsElementAttributeEqualToIgnoreCase(
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session, web_view, element_id, "multiple", "true", &multiple);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!multiple && paths.size() > 1)
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "the element can not hold multiple files");
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> element(CreateElement(element_id));
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return web_view->SetFileInputFiles(
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session->GetCurrentFrameId(), *element, paths);
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SendKeysToElement(session, web_view, element_id, key_list);
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteSubmitElement(
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::SUBMIT),
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementText(
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::GET_TEXT),
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementValue(
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "function(elem) { return elem['value'] }",
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementTagName(
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "function(elem) { return elem.tagName.toLowerCase() }",
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteIsElementSelected(
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::IS_SELECTED),
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteIsElementEnabled(
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::IS_ENABLED),
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteIsElementDisplayed(
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::IS_DISPLAYED),
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementLocation(
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::GET_LOCATION),
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementLocationOnceScrolledIntoView(
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  WebPoint location;
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = ScrollElementIntoView(
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session, web_view, element_id, &location);
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  value->reset(CreateValueFrom(location));
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Status(kOk);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementSize(
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue args;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  args.Append(CreateElement(element_id));
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_view->CallFunction(
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session->GetCurrentFrameId(),
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      webdriver::atoms::asString(webdriver::atoms::GET_SIZE),
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      args,
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementAttribute(
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string name;
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("name", &name))
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "missing 'name'");
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetElementAttribute(session, web_view, element_id, name, value);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteGetElementValueOfCSSProperty(
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string property_name;
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.GetString("propertyName", &property_name))
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "missing 'propertyName'");
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string property_value;
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = GetElementEffectiveStyle(
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session, web_view, element_id, property_name, &property_value);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  value->reset(new base::StringValue(property_value));
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Status(kOk);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ExecuteElementEquals(
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Session* session,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebView* web_view,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& element_id,
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& params,
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::Value>* value) {
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string other_element_id;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!params.GetString("other", &other_element_id))
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "'other' must be a string");
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  value->reset(new base::FundamentalValue(element_id == other_element_id));
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
480