// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/webdriver/webdriver_session.h"

#include <sstream>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/automation_json_requests.h"
#include "chrome/test/automation/value_conversion_util.h"
#include "chrome/test/webdriver/webdriver_capabilities_parser.h"
#include "chrome/test/webdriver/webdriver_error.h"
#include "chrome/test/webdriver/webdriver_key_converter.h"
#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
#include "chrome/test/webdriver/webdriver_util.h"
#include "third_party/webdriver/atoms.h"

using automation::kLeftButton;
using automation::kMouseDown;
using automation::kMouseMove;
using automation::kMouseUp;
using automation::kNoButton;

namespace webdriver {

namespace {
// This is the minimum version of chrome that supports the new mouse API.
const int kNewMouseAPIMinVersion = 1002;
}

FrameId::FrameId() {}

FrameId::FrameId(const WebViewId& view_id, const FramePath& frame_path)
    : view_id(view_id),
      frame_path(frame_path) {
}

Session::Session()
    : session_log_(new InMemoryLog()),
      logger_(kAllLogLevel),
      id_(GenerateRandomID()),
      current_target_(FrameId(WebViewId(), FramePath())),
      thread_(id_.c_str()),
      async_script_timeout_(0),
      implicit_wait_(0),
      has_alert_prompt_text_(false),
      sticky_modifiers_(0),
      build_no_(0) {
  SessionManager::GetInstance()->Add(this);
  logger_.AddHandler(session_log_.get());
  if (FileLog::Get())
    logger_.AddHandler(FileLog::Get());
}

Session::~Session() {
  SessionManager::GetInstance()->Remove(id_);
}

Error* Session::Init(const base::DictionaryValue* capabilities_dict) {
  if (!thread_.Start()) {
    delete this;
    return new Error(kUnknownError, "Cannot start session thread");
  }
  if (!temp_dir_.CreateUniqueTempDir()) {
    delete this;
    return new Error(
        kUnknownError, "Unable to create temp directory for unpacking");
  }
  logger_.Log(kFineLogLevel,
              "Initializing session with capabilities " +
                  JsonStringifyForDisplay(capabilities_dict));
  CapabilitiesParser parser(
      capabilities_dict, temp_dir_.path(), logger_, &capabilities_);
  Error* error = parser.Parse();
  if (error) {
    delete this;
    return error;
  }
  logger_.set_min_log_level(capabilities_.log_levels[LogType::kDriver]);

  Automation::BrowserOptions browser_options;
  browser_options.command = capabilities_.command;
  browser_options.channel_id = capabilities_.channel;
  browser_options.detach_process = capabilities_.detach;
  browser_options.user_data_dir = capabilities_.profile;
  browser_options.exclude_switches = capabilities_.exclude_switches;
  if (!capabilities_.no_website_testing_defaults) {
    browser_options.ignore_certificate_errors = true;
  }
  RunSessionTask(base::Bind(
      &Session::InitOnSessionThread,
      base::Unretained(this),
      browser_options,
      &build_no_,
      &error));
  if (!error)
    error = PostBrowserStartInit();

  if (error)
    Terminate();
  return error;
}

Error* Session::BeforeExecuteCommand() {
  Error* error = AfterExecuteCommand();
  if (!error) {
    scoped_ptr<Error> switch_error(SwitchToTopFrameIfCurrentFrameInvalid());
    if (switch_error.get()) {
      std::string text;
      scoped_ptr<Error> alert_error(GetAlertMessage(&text));
      if (alert_error.get()) {
        // Only return a frame checking error if a modal dialog is not present.
        // TODO(kkania): This is ugly. Fix.
        return switch_error.release();
      }
    }
  }
  return error;
}

Error* Session::AfterExecuteCommand() {
  Error* error = NULL;
  if (!capabilities_.load_async) {
    error = WaitForAllViewsToStopLoading();
  }
  return error;
}

void Session::Terminate() {
  RunSessionTask(base::Bind(
      &Session::TerminateOnSessionThread,
      base::Unretained(this)));
  delete this;
}

Error* Session::ExecuteScript(const FrameId& frame_id,
                              const std::string& script,
                              const base::ListValue* const args,
                              base::Value** value) {
  std::string args_as_json;
  base::JSONWriter::Write(static_cast<const base::Value* const>(args),
                          &args_as_json);

  // Every injected script is fed through the executeScript atom. This atom
  // will catch any errors that are thrown and convert them to the
  // appropriate JSON structure.
  std::string jscript = base::StringPrintf(
      "window.domAutomationController.send((%s).apply(null,"
      "[function(){%s\n},%s,true]));",
      atoms::asString(atoms::EXECUTE_SCRIPT).c_str(), script.c_str(),
      args_as_json.c_str());

  return ExecuteScriptAndParseValue(frame_id, jscript, value);
}

Error* Session::ExecuteScript(const std::string& script,
                              const base::ListValue* const args,
                              base::Value** value) {
  return ExecuteScript(current_target_, script, args, value);
}

Error* Session::ExecuteScriptAndParse(const FrameId& frame_id,
                                      const std::string& anonymous_func_script,
                                      const std::string& script_name,
                                      const base::ListValue* args,
                                      const ValueParser* parser) {
  scoped_ptr<const base::ListValue> scoped_args(args);
  scoped_ptr<const ValueParser> scoped_parser(parser);
  std::string called_script = base::StringPrintf(
      "return (%s).apply(null, arguments);", anonymous_func_script.c_str());
  base::Value* unscoped_value = NULL;
  Error* error = ExecuteScript(frame_id, called_script, args, &unscoped_value);
  if (error) {
    error->AddDetails(script_name + " execution failed");
    return error;
  }

  scoped_ptr<base::Value> value(unscoped_value);
  std::string error_msg;
  if (!parser->Parse(value.get())) {
    error_msg = base::StringPrintf("%s returned invalid value: %s",
        script_name.c_str(), JsonStringify(value.get()).c_str());
    return new Error(kUnknownError, error_msg);
  }
  return NULL;
}

Error* Session::ExecuteAsyncScript(const FrameId& frame_id,
                                   const std::string& script,
                                   const base::ListValue* const args,
                                   base::Value** value) {
  std::string args_as_json;
  base::JSONWriter::Write(static_cast<const base::Value* const>(args),
                          &args_as_json);

  int timeout_ms = async_script_timeout();

  // Every injected script is fed through the executeScript atom. This atom
  // will catch any errors that are thrown and convert them to the
  // appropriate JSON structure.
  std::string jscript = base::StringPrintf(
      "(%s).apply(null, [function(){%s},%s,%d,%s,true]);",
      atoms::asString(atoms::EXECUTE_ASYNC_SCRIPT).c_str(),
      script.c_str(),
      args_as_json.c_str(),
      timeout_ms,
      "function(result) {window.domAutomationController.send(result);}");

  return ExecuteScriptAndParseValue(frame_id, jscript, value);
}

Error* Session::SendKeys(const ElementId& element, const string16& keys) {
  bool is_displayed = false;
  Error* error = IsElementDisplayed(
      current_target_, element, true /* ignore_opacity */, &is_displayed);
  if (error)
    return error;
  if (!is_displayed)
    return new Error(kElementNotVisible);

  bool is_enabled = false;
  error = IsElementEnabled(current_target_, element, &is_enabled);
  if (error)
    return error;
  if (!is_enabled)
    return new Error(kInvalidElementState);

  // Focus the target element in order to send keys to it.
  // First, the currently active element is blurred, if it is different from
  // the target element. We do not want to blur an element unnecessarily,
  // because this may cause us to lose the current cursor position in the
  // element.
  // Secondly, we focus the target element.
  // Thirdly, if the target element is newly focused and is a text input, we
  // set the cursor position at the end.
  // Fourthly, we check if the new active element is the target element. If not,
  // we throw an error.
  // Additional notes:
  //   - |document.activeElement| is the currently focused element, or body if
  //     no element is focused
  //   - Even if |document.hasFocus()| returns true and the active element is
  //     the body, sometimes we still need to focus the body element for send
  //     keys to work. Not sure why
  //   - You cannot focus a descendant of a content editable node
  //   - V8 throws a TypeError when calling setSelectionRange for a non-text
  //     input, which still have setSelectionRange defined.
  // TODO(jleyba): Update this to use the correct atom.
  const char* kFocusScript =
      "function(elem) {"
      "  var doc = elem.ownerDocument || elem;"
      "  var prevActiveElem = doc.activeElement;"
      "  if (elem != prevActiveElem && prevActiveElem)"
      "    prevActiveElem.blur();"
      "  elem.focus();"
      "  if (elem != prevActiveElem && elem.value && elem.value.length &&"
      "      elem.setSelectionRange) {"
      "    try {"
      "      elem.setSelectionRange(elem.value.length, elem.value.length);"
      "    } catch (error) {"
      "      if (!(error instanceof TypeError)) {"
      "        throw error;"
      "      }"
      "    }"
      "  }"
      "  if (elem != doc.activeElement)"
      "    throw new Error('Failed to send keys because cannot focus element');"
      "}";
  error = ExecuteScriptAndParse(current_target_,
                                kFocusScript,
                                "focusElement",
                                CreateListValueFrom(element),
                                CreateDirectValueParser(kSkipParsing));
  if (error)
    return error;

  RunSessionTask(base::Bind(
      &Session::SendKeysOnSessionThread,
      base::Unretained(this),
      keys,
      true /* release_modifiers */,
      &error));
  return error;
}

Error* Session::SendKeys(const string16& keys) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Session::SendKeysOnSessionThread,
      base::Unretained(this),
      keys,
      false /* release_modifiers */,
      &error));
  return error;
}

Error* Session::DragAndDropFilePaths(
    const Point& location,
    const std::vector<base::FilePath::StringType>& paths) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::DragAndDropFilePaths,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      location,
      paths,
      &error));
  return error;
}

Error* Session::NavigateToURL(const std::string& url) {
  if (!current_target_.view_id.IsTab()) {
    return new Error(kUnknownError,
                     "The current target does not support navigation");
  }
  Error* error = NULL;
  if (capabilities_.load_async) {
    RunSessionTask(base::Bind(
        &Automation::NavigateToURLAsync,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        url,
        &error));
  } else {
    RunSessionTask(base::Bind(
        &Automation::NavigateToURL,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        url,
        &error));
  }
  return error;
}

Error* Session::GoForward() {
  if (!current_target_.view_id.IsTab()) {
    return new Error(kUnknownError,
                     "The current target does not support navigation");
  }
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GoForward,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      &error));
  return error;
}

Error* Session::GoBack() {
  if (!current_target_.view_id.IsTab()) {
    return new Error(kUnknownError,
                     "The current target does not support navigation");
  }
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GoBack,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      &error));
  return error;
}

Error* Session::Reload() {
  if (!current_target_.view_id.IsTab()) {
    return new Error(kUnknownError,
                     "The current target does not support navigation");
  }
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::Reload,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      &error));
  return error;
}

Error* Session::GetURL(std::string* url) {
  return ExecuteScriptAndParse(current_target_,
                               "function() { return document.URL }",
                               "getUrl",
                               new base::ListValue(),
                               CreateDirectValueParser(url));
}

Error* Session::GetTitle(std::string* tab_title) {
  const char* kGetTitleScript =
      "function() {"
      "  if (document.title)"
      "    return document.title;"
      "  else"
      "    return document.URL;"
      "}";
  return ExecuteScriptAndParse(FrameId(current_target_.view_id, FramePath()),
                               kGetTitleScript,
                               "getTitle",
                               new base::ListValue(),
                               CreateDirectValueParser(tab_title));
}

Error* Session::MouseMoveAndClick(const Point& location,
                                  automation::MouseButton button) {
  Error* error = NULL;
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(kMouseMove, kNoButton, location, 0));
    events.push_back(CreateWebMouseEvent(kMouseDown, button, location, 1));
    events.push_back(CreateWebMouseEvent(kMouseUp, button, location, 1));
    error = ProcessWebMouseEvents(events);
  } else {
    RunSessionTask(base::Bind(
        &Automation::MouseClickDeprecated,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        location,
        button,
        &error));
  }
  if (!error)
    mouse_position_ = location;
  return error;
}

Error* Session::MouseMove(const Point& location) {
  Error* error = NULL;
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(kMouseMove, kNoButton, location, 0));
    error = ProcessWebMouseEvents(events);
  } else {
    RunSessionTask(base::Bind(
        &Automation::MouseMoveDeprecated,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        location,
        &error));
  }
  if (!error)
    mouse_position_ = location;
  return error;
}

Error* Session::MouseDrag(const Point& start,
                          const Point& end) {
  Error* error = NULL;
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(kMouseMove, kNoButton, start, 0));
    events.push_back(CreateWebMouseEvent(kMouseDown, kLeftButton, start, 1));
    events.push_back(CreateWebMouseEvent(kMouseMove, kLeftButton, end, 0));
    events.push_back(CreateWebMouseEvent(kMouseUp, kLeftButton, end, 1));
    error = ProcessWebMouseEvents(events);
  } else {
    RunSessionTask(base::Bind(
        &Automation::MouseDragDeprecated,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        start,
        end,
        &error));
  }
  if (!error)
    mouse_position_ = end;
  return error;
}

Error* Session::MouseClick(automation::MouseButton button) {
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(
        kMouseDown, button, mouse_position_, 1));
    events.push_back(CreateWebMouseEvent(
        kMouseUp, button, mouse_position_, 1));
    return ProcessWebMouseEvents(events);
  } else {
    return MouseMoveAndClick(mouse_position_, button);
  }
}

Error* Session::MouseButtonDown() {
  Error* error = NULL;
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(
        kMouseDown, kLeftButton, mouse_position_, 1));
    error = ProcessWebMouseEvents(events);
  } else {
    RunSessionTask(base::Bind(
        &Automation::MouseButtonDownDeprecated,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        mouse_position_,
        &error));
  }
  return error;
}

Error* Session::MouseButtonUp() {
  Error* error = NULL;
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(
        kMouseUp, kLeftButton, mouse_position_, 1));
    error = ProcessWebMouseEvents(events);
  } else {
    RunSessionTask(base::Bind(
        &Automation::MouseButtonUpDeprecated,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        mouse_position_,
        &error));
  }
  return error;
}

Error* Session::MouseDoubleClick() {
  Error* error = NULL;
  if (build_no_ >= kNewMouseAPIMinVersion) {
    std::vector<WebMouseEvent> events;
    events.push_back(CreateWebMouseEvent(
        kMouseDown, kLeftButton, mouse_position_, 1));
    events.push_back(CreateWebMouseEvent(
        kMouseUp, kLeftButton, mouse_position_, 1));
    events.push_back(CreateWebMouseEvent(
        kMouseDown, kLeftButton, mouse_position_, 2));
    events.push_back(CreateWebMouseEvent(
        kMouseUp, kLeftButton, mouse_position_, 2));
    error = ProcessWebMouseEvents(events);
  } else {
    RunSessionTask(base::Bind(
        &Automation::MouseDoubleClickDeprecated,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        mouse_position_,
        &error));
  }
  return error;
}

Error* Session::GetCookies(const std::string& url, base::ListValue** cookies) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GetCookies,
      base::Unretained(automation_.get()),
      url,
      cookies,
      &error));
  return error;
}

Error* Session::DeleteCookie(const std::string& url,
                           const std::string& cookie_name) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::DeleteCookie,
      base::Unretained(automation_.get()),
      url,
      cookie_name,
      &error));
  return error;
}

// Note that when this is called from CookieCommand::ExecutePost then
// |cookie_dict| is destroyed as soon as the caller finishes. Therefore
// it is essential that RunSessionTask executes synchronously.
Error* Session::SetCookie(const std::string& url,
                          base::DictionaryValue* cookie_dict) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::SetCookie,
      base::Unretained(automation_.get()),
      url,
      cookie_dict,
      &error));
  return error;
}

Error* Session::GetViews(std::vector<WebViewInfo>* views) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GetViews,
      base::Unretained(automation_.get()),
      views,
      &error));
  return error;
}

Error* Session::SwitchToView(const std::string& id_or_name) {
  Error* error = NULL;
  bool does_exist = false;

  WebViewId new_view;
  StringToWebViewId(id_or_name, &new_view);
  if (new_view.IsValid()) {
    RunSessionTask(base::Bind(
        &Automation::DoesViewExist,
        base::Unretained(automation_.get()),
        new_view,
        &does_exist,
        &error));
    if (error)
      return error;
  }

  if (!does_exist) {
    // See if any of the tab window names match |name|.
    std::vector<WebViewInfo> views;
    Error* error = GetViews(&views);
    if (error)
      return error;
    for (size_t i = 0; i < views.size(); ++i) {
      if (!views[i].view_id.IsTab())
        continue;
      std::string window_name;
      Error* error = ExecuteScriptAndParse(
          FrameId(views[i].view_id, FramePath()),
          "function() { return window.name; }",
          "getWindowName",
          new base::ListValue(),
          CreateDirectValueParser(&window_name));
      if (error)
        return error;
      if (id_or_name == window_name) {
        new_view = views[i].view_id;
        does_exist = true;
        break;
      }
    }
  }

  if (!does_exist)
    return new Error(kNoSuchWindow);
  frame_elements_.clear();
  current_target_ = FrameId(new_view, FramePath());
  return NULL;
}

Error* Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) {
  std::string script =
      "function(arg) {"
      "  var xpath = '(/html/body//iframe|/html/frameset/frame)';"
      "  var sub = function(s) { return s.replace(/\\$/g, arg); };"
      "  xpath += sub('[@name=\"$\" or @id=\"$\"]');"
      "  return document.evaluate(xpath, document, null, "
      "      XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
      "}";
  return SwitchToFrameWithJavaScriptLocatedFrame(
      script, CreateListValueFrom(name_or_id));
}

Error* Session::SwitchToFrameWithIndex(int index) {
  // We cannot simply index into window.frames because we need to know the
  // tagName of the frameElement. If child frame N is from another domain, then
  // the following will run afoul of the same origin policy:
  //   window.frames[N].frameElement;
  // Instead of indexing window.frames, we use an XPath expression to index
  // into the list of all IFRAME and FRAME elements on the page - if we find
  // something, then that XPath expression can be used as the new frame's XPath.
  std::string script =
      "function(index) {"
      "  var xpathIndex = '[' + (index + 1) + ']';"
      "  var xpath = '(/html/body//iframe|/html/frameset/frame)' + "
      "              xpathIndex;"
      "  return document.evaluate(xpath, document, null, "
      "      XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
      "}";
  return SwitchToFrameWithJavaScriptLocatedFrame(
      script, CreateListValueFrom(index));
}

Error* Session::SwitchToFrameWithElement(const ElementId& element) {
  // TODO(jleyba): Extract this, and the other frame switch methods to an atom.
  std::string script =
      "function(elem) {"
      "  if (elem.nodeType != 1 || !/^i?frame$/i.test(elem.tagName)) {"
      "    console.error('Element is not a frame');"
      "    return null;"
      "  }"
      "  for (var i = 0; i < window.frames.length; i++) {"
      "    if (elem.contentWindow == window.frames[i]) {"
      "      return elem;"
      "    }"
      "  }"
      "  console.info('Frame is not connected to this DOM tree');"
      "  return null;"
      "}";
  return SwitchToFrameWithJavaScriptLocatedFrame(
      script, CreateListValueFrom(element));
}

void Session::SwitchToTopFrame() {
  frame_elements_.clear();
  current_target_.frame_path = FramePath();
}

Error* Session::SwitchToTopFrameIfCurrentFrameInvalid() {
  std::vector<std::string> components;
  current_target_.frame_path.GetComponents(&components);
  if (frame_elements_.size() != components.size()) {
    return new Error(kUnknownError,
                     "Frame element vector out of sync with frame path");
  }
  FramePath frame_path;
  // Start from the root path and check that each frame element that makes
  // up the current frame target is valid by executing an empty script.
  // This code should not execute script in any frame before making sure the
  // frame element is valid, otherwise the automation hangs until a timeout.
  for (size_t i = 0; i < frame_elements_.size(); ++i) {
    FrameId frame_id(current_target_.view_id, frame_path);
    scoped_ptr<Error> error(ExecuteScriptAndParse(
        frame_id,
        "function(){ }",
        "emptyScript",
        CreateListValueFrom(frame_elements_[i]),
        CreateDirectValueParser(kSkipParsing)));
    if (error.get() && error->code() == kStaleElementReference) {
      SwitchToTopFrame();
    } else if (error.get()) {
      return error.release();
    }
    frame_path = frame_path.Append(components[i]);
  }
  return NULL;
}

Error* Session::CloseWindow() {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::CloseView,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      &error));

  if (!error) {
    std::vector<WebViewInfo> views;
    scoped_ptr<Error> error(GetViews(&views));
    if (error.get() || views.empty()) {
      // The automation connection will soon be closed, if not already,
      // because we supposedly just closed the last window. Terminate the
      // session.
      // TODO(kkania): This will cause us problems if GetWindowIds fails for a
      // reason other than the channel is disconnected. Look into having
      // |GetWindowIds| tell us if it just closed the last window.
      Terminate();
    }
  }
  return error;
}

Error* Session::GetWindowBounds(const WebViewId& window, Rect* bounds) {
  const char* kGetWindowBoundsScript =
      "function() {"
      "  return {"
      "    'left': window.screenX,"
      "    'top': window.screenY,"
      "    'width': window.outerWidth,"
      "    'height': window.outerHeight"
      "  }"
      "}";
  return ExecuteScriptAndParse(
      FrameId(window, FramePath()),
      kGetWindowBoundsScript,
      "getWindowBoundsScript",
      new base::ListValue(),
      CreateDirectValueParser(bounds));
}

Error* Session::SetWindowBounds(
    const WebViewId& window,
    const Rect& bounds) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::SetViewBounds,
      base::Unretained(automation_.get()),
      window,
      bounds,
      &error));
  return error;
}

Error* Session::MaximizeWindow(const WebViewId& window) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
        &Automation::MaximizeView,
        base::Unretained(automation_.get()),
        window,
        &error));
  return error;
}

Error* Session::GetAlertMessage(std::string* text) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GetAppModalDialogMessage,
      base::Unretained(automation_.get()),
      text,
      &error));
  return error;
}

Error* Session::SetAlertPromptText(const std::string& alert_prompt_text) {
  std::string message_text;
  // Only set the alert prompt text if an alert is actually active.
  Error* error = GetAlertMessage(&message_text);
  if (!error) {
    has_alert_prompt_text_ = true;
    alert_prompt_text_ = alert_prompt_text;
  }
  return error;
}

Error* Session::AcceptOrDismissAlert(bool accept) {
  Error* error = NULL;
  if (accept && has_alert_prompt_text_) {
    RunSessionTask(base::Bind(
        &Automation::AcceptPromptAppModalDialog,
        base::Unretained(automation_.get()),
        alert_prompt_text_,
        &error));
  } else {
    RunSessionTask(base::Bind(
        &Automation::AcceptOrDismissAppModalDialog,
        base::Unretained(automation_.get()),
        accept,
        &error));
  }
  has_alert_prompt_text_ = false;
  return error;
}

std::string Session::GetBrowserVersion() {
  std::string version;
  RunSessionTask(base::Bind(
      &Automation::GetBrowserVersion,
      base::Unretained(automation_.get()),
      &version));
  return version;
}

Error* Session::CompareBrowserVersion(int client_build_no,
                                      int client_patch_no,
                                      bool* is_newer_or_equal) {
  std::string version = GetBrowserVersion();
  std::vector<std::string> split_version;
  base::SplitString(version, '.', &split_version);
  if (split_version.size() != 4) {
    return new Error(
        kUnknownError, "Browser version has unrecognized format: " + version);
  }
  int build_no, patch_no;
  if (!base::StringToInt(split_version[2], &build_no) ||
      !base::StringToInt(split_version[3], &patch_no)) {
    return new Error(
        kUnknownError, "Browser version has unrecognized format: " + version);
  }
  if (build_no < client_build_no)
    *is_newer_or_equal = false;
  else if (build_no > client_build_no)
    *is_newer_or_equal = true;
  else
    *is_newer_or_equal = patch_no >= client_patch_no;
  return NULL;
}

Error* Session::FindElement(const FrameId& frame_id,
                            const ElementId& root_element,
                            const std::string& locator,
                            const std::string& query,
                            ElementId* element) {
  std::vector<ElementId> elements;
  Error* error = FindElementsHelper(
      frame_id, root_element, locator, query, true, &elements);
  if (!error)
    *element = elements[0];
  return error;
}

Error* Session::FindElements(const FrameId& frame_id,
                             const ElementId& root_element,
                             const std::string& locator,
                             const std::string& query,
                             std::vector<ElementId>* elements) {
  return FindElementsHelper(
      frame_id, root_element, locator, query, false, elements);
}

Error* Session::GetElementLocationInView(
    const ElementId& element,
    Point* location) {
  Size size;
  Error* error = GetElementSize(current_target_, element, &size);
  if (error)
    return error;
  return GetElementRegionInView(
      element, Rect(Point(0, 0), size),
      false /* center */, false /* verify_clickable_at_middle */, location);
}

Error* Session::GetElementRegionInView(
    const ElementId& element,
    const Rect& region,
    bool center,
    bool verify_clickable_at_middle,
    Point* location) {
  CHECK(element.is_valid());

  Point region_offset = region.origin();
  Size region_size = region.size();
  Error* error = GetElementRegionInViewHelper(
      current_target_, element, region, center, verify_clickable_at_middle,
      &region_offset);
  if (error)
    return error;

  for (FramePath frame_path = current_target_.frame_path;
       frame_path.IsSubframe();
       frame_path = frame_path.Parent()) {
    // Find the frame element for the current frame path.
    FrameId frame_id(current_target_.view_id, frame_path.Parent());
    ElementId frame_element;
    error = FindElement(frame_id,
                        ElementId(std::string()),
                        LocatorType::kXpath,
                        frame_path.BaseName().value(),
                        &frame_element);
    if (error) {
      std::string context = base::StringPrintf(
          "Could not find frame element (%s) in frame (%s)",
          frame_path.BaseName().value().c_str(),
          frame_path.Parent().value().c_str());
      error->AddDetails(context);
      return error;
    }
    // Modify |region_offset| by the frame's border.
    int border_left, border_top;
    error = GetElementBorder(
        frame_id, frame_element, &border_left, &border_top);
    if (error)
      return error;
    region_offset.Offset(border_left, border_top);

    error = GetElementRegionInViewHelper(
        frame_id, frame_element, Rect(region_offset, region_size),
        center, verify_clickable_at_middle, &region_offset);
    if (error)
      return error;
  }
  *location = region_offset;
  return NULL;
}

Error* Session::GetElementSize(const FrameId& frame_id,
                               const ElementId& element,
                               Size* size) {
  return ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::GET_SIZE),
      "getSize",
      CreateListValueFrom(element),
      CreateDirectValueParser(size));
}

Error* Session::GetElementFirstClientRect(const FrameId& frame_id,
                                          const ElementId& element,
                                          Rect* rect) {
  return ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::GET_FIRST_CLIENT_RECT),
      "getFirstClientRect",
      CreateListValueFrom(element),
      CreateDirectValueParser(rect));
}

Error* Session::GetElementEffectiveStyle(
    const FrameId& frame_id,
    const ElementId& element,
    const std::string& prop,
    std::string* value) {
  return ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::GET_EFFECTIVE_STYLE),
      "getEffectiveStyle",
      CreateListValueFrom(element, prop),
      CreateDirectValueParser(value));
}

Error* Session::GetElementBorder(const FrameId& frame_id,
                                 const ElementId& element,
                                 int* border_left,
                                 int* border_top) {
  std::string border_left_str, border_top_str;
  Error* error = GetElementEffectiveStyle(
      frame_id, element, "border-left-width", &border_left_str);
  if (error)
    return error;
  error = GetElementEffectiveStyle(
      frame_id, element, "border-top-width", &border_top_str);
  if (error)
    return error;

  base::StringToInt(border_left_str, border_left);
  base::StringToInt(border_top_str, border_top);
  return NULL;
}

Error* Session::IsElementDisplayed(const FrameId& frame_id,
                                   const ElementId& element,
                                   bool ignore_opacity,
                                   bool* is_displayed) {
  return ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::IS_DISPLAYED),
      "isDisplayed",
      CreateListValueFrom(element, ignore_opacity),
      CreateDirectValueParser(is_displayed));
}

Error* Session::IsElementEnabled(const FrameId& frame_id,
                                 const ElementId& element,
                                 bool* is_enabled) {
  return ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::IS_ENABLED),
      "isEnabled",
      CreateListValueFrom(element),
      CreateDirectValueParser(is_enabled));
}

Error* Session::IsOptionElementSelected(const FrameId& frame_id,
                                        const ElementId& element,
                                        bool* is_selected) {
  return ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::IS_SELECTED),
      "isSelected",
      CreateListValueFrom(element),
      CreateDirectValueParser(is_selected));
}

Error* Session::SetOptionElementSelected(const FrameId& frame_id,
                                         const ElementId& element,
                                         bool selected) {
  // This wrapper ensures the script is started successfully and
  // allows for an alert to happen when the option selection occurs.
  // See selenium bug 2671.
  const char kSetSelectedWrapper[] =
      "var args = [].slice.apply(arguments);"
      "args[args.length - 1]();"
      "return (%s).apply(null, args.slice(0, args.length - 1));";
  base::Value* value = NULL;
  Error* error = ExecuteAsyncScript(
      frame_id,
      base::StringPrintf(kSetSelectedWrapper,
                         atoms::asString(atoms::CLICK).c_str()),
      CreateListValueFrom(element, selected),
      &value);
  scoped_ptr<base::Value> scoped_value(value);
  return error;
}

Error* Session::ToggleOptionElement(const FrameId& frame_id,
                                    const ElementId& element) {
  bool is_selected;
  Error* error = IsOptionElementSelected(frame_id, element, &is_selected);
  if (error)
    return error;

  return SetOptionElementSelected(frame_id, element, !is_selected);
}

Error* Session::GetElementTagName(const FrameId& frame_id,
                                  const ElementId& element,
                                  std::string* tag_name) {
  return ExecuteScriptAndParse(
      frame_id,
      "function(elem) { return elem.tagName.toLowerCase() }",
      "getElementTagName",
      CreateListValueFrom(element),
      CreateDirectValueParser(tag_name));
}

Error* Session::GetClickableLocation(const ElementId& element,
                                     Point* location) {
  bool is_displayed = false;
  Error* error = IsElementDisplayed(
      current_target_, element, true /* ignore_opacity */, &is_displayed);
  if (error)
    return error;
  if (!is_displayed)
    return new Error(kElementNotVisible, "Element must be displayed to click");

  // We try 3 methods to determine clickable location. This mostly follows
  // what FirefoxDriver does. Try the first client rect, then the bounding
  // client rect, and lastly the size of the element (via closure).
  // SVG is one case that doesn't have a first client rect.
  Rect rect;
  scoped_ptr<Error> ignore_error(
      GetElementFirstClientRect(current_target_, element, &rect));
  if (ignore_error.get()) {
    Rect client_rect;
    ignore_error.reset(ExecuteScriptAndParse(
        current_target_,
        "function(elem) { return elem.getBoundingClientRect() }",
        "getBoundingClientRect",
        CreateListValueFrom(element),
        CreateDirectValueParser(&client_rect)));
    rect = Rect(0, 0, client_rect.width(), client_rect.height());
  }
  if (ignore_error.get()) {
    Size size;
    ignore_error.reset(GetElementSize(current_target_, element, &size));
    rect = Rect(0, 0, size.width(), size.height());
  }
  if (ignore_error.get()) {
    return new Error(kUnknownError,
                     "Unable to determine clickable location of element");
  }

  error = GetElementRegionInView(
      element, rect, true /* center */, true /* verify_clickable_at_middle */,
      location);
  if (error)
    return error;
  location->Offset(rect.width() / 2, rect.height() / 2);
  return NULL;
}

Error* Session::GetAttribute(const ElementId& element,
                             const std::string& key,
                             base::Value** value) {
  return ExecuteScriptAndParse(
      current_target_,
      atoms::asString(atoms::GET_ATTRIBUTE),
      "getAttribute",
      CreateListValueFrom(element, key),
      CreateDirectValueParser(value));
}

Error* Session::WaitForAllViewsToStopLoading() {
  if (!automation_.get())
    return NULL;

  logger_.Log(kFinerLogLevel, "Waiting for all views to stop loading...");
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::WaitForAllViewsToStopLoading,
      base::Unretained(automation_.get()),
      &error));
  logger_.Log(kFinerLogLevel, "Done waiting for all views to stop loading");
  return error;
}

Error* Session::InstallExtension(
    const base::FilePath& path, std::string* extension_id) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::InstallExtension,
      base::Unretained(automation_.get()),
      path,
      extension_id,
      &error));
  return error;
}

Error* Session::GetExtensionsInfo(base::ListValue* extensions_list) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GetExtensionsInfo,
      base::Unretained(automation_.get()),
      extensions_list,
      &error));
  return error;
}

Error* Session::IsPageActionVisible(
    const WebViewId& tab_id,
    const std::string& extension_id,
    bool* is_visible) {
  if (!tab_id.IsTab()) {
    return new Error(
        kUnknownError,
        "The current target does not support page actions. Switch to a tab.");
  }
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::IsPageActionVisible,
      base::Unretained(automation_.get()),
      tab_id,
      extension_id,
      is_visible,
      &error));
  return error;
}

Error* Session::SetExtensionState(
    const std::string& extension_id, bool enable) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::SetExtensionState,
      base::Unretained(automation_.get()),
      extension_id,
      enable,
      &error));
  return error;
}

Error* Session::ClickExtensionButton(
    const std::string& extension_id, bool browser_action) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::ClickExtensionButton,
      base::Unretained(automation_.get()),
      extension_id,
      browser_action,
      &error));
  return error;
}

Error* Session::UninstallExtension(const std::string& extension_id) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::UninstallExtension,
      base::Unretained(automation_.get()),
      extension_id,
      &error));
  return error;
}

Error* Session::SetPreference(
    const std::string& pref,
    bool is_user_pref,
    base::Value* value) {
  Error* error = NULL;
  if (is_user_pref) {
    RunSessionTask(base::Bind(
        &Automation::SetPreference,
        base::Unretained(automation_.get()),
        pref,
        value,
        &error));
    if (error)
      error->AddDetails("Failed to set user pref '" + pref + "'");
  } else {
    RunSessionTask(base::Bind(
        &Automation::SetLocalStatePreference,
        base::Unretained(automation_.get()),
        pref,
        value,
        &error));
    if (error)
      error->AddDetails("Failed to set local state pref '" + pref + "'");
  }
  return error;
}

base::ListValue* Session::GetLog() const {
  return session_log_->entries_list()->DeepCopy();
}

Error* Session::GetBrowserConnectionState(bool* online) {
  return ExecuteScriptAndParse(
      current_target_,
      atoms::asString(atoms::IS_ONLINE),
      "isOnline",
      new base::ListValue(),
      CreateDirectValueParser(online));
}

Error* Session::GetAppCacheStatus(int* status) {
  return ExecuteScriptAndParse(
      current_target_,
      atoms::asString(atoms::GET_APPCACHE_STATUS),
      "getAppcacheStatus",
      new base::ListValue(),
      CreateDirectValueParser(status));
}

Error* Session::GetStorageSize(StorageType type, int* size) {
  std::string js = atoms::asString(
      type == kLocalStorageType ? atoms::GET_LOCAL_STORAGE_SIZE
                                : atoms::GET_SESSION_STORAGE_SIZE);
  return ExecuteScriptAndParse(
      current_target_,
      js,
      "getStorageSize",
      new base::ListValue(),
      CreateDirectValueParser(size));
}

Error* Session::SetStorageItem(StorageType type,
                               const std::string& key,
                               const std::string& value) {
  std::string js = atoms::asString(
      type == kLocalStorageType ? atoms::SET_LOCAL_STORAGE_ITEM
                                : atoms::SET_SESSION_STORAGE_ITEM);
  return ExecuteScriptAndParse(
      current_target_,
      js,
      "setStorageItem",
      CreateListValueFrom(key, value),
      CreateDirectValueParser(kSkipParsing));
}

Error* Session::ClearStorage(StorageType type) {
  std::string js = atoms::asString(
      type == kLocalStorageType ? atoms::CLEAR_LOCAL_STORAGE
                                : atoms::CLEAR_SESSION_STORAGE);
  return ExecuteScriptAndParse(
      current_target_,
      js,
      "clearStorage",
      new base::ListValue(),
      CreateDirectValueParser(kSkipParsing));
}

Error* Session::GetStorageKeys(StorageType type, base::ListValue** keys) {
  std::string js = atoms::asString(
      type == kLocalStorageType ? atoms::GET_LOCAL_STORAGE_KEYS
                                : atoms::GET_SESSION_STORAGE_KEYS);
  return ExecuteScriptAndParse(
      current_target_,
      js,
      "getStorageKeys",
      new base::ListValue(),
      CreateDirectValueParser(keys));
}

Error* Session::GetStorageItem(StorageType type,
                               const std::string& key,
                               std::string* value) {
  std::string js = atoms::asString(
      type == kLocalStorageType ? atoms::GET_LOCAL_STORAGE_ITEM
                                : atoms::GET_SESSION_STORAGE_ITEM);
  return ExecuteScriptAndParse(
      current_target_,
      js,
      "getStorageItem",
      CreateListValueFrom(key),
      CreateDirectValueParser(value));
}

Error* Session::RemoveStorageItem(StorageType type,
                                  const std::string& key,
                                  std::string* value) {
  std::string js = atoms::asString(
      type == kLocalStorageType ? atoms::REMOVE_LOCAL_STORAGE_ITEM
                                : atoms::REMOVE_SESSION_STORAGE_ITEM);
  return ExecuteScriptAndParse(
      current_target_,
      js,
      "removeStorageItem",
      CreateListValueFrom(key),
      CreateDirectValueParser(value));
}

Error* Session::GetGeolocation(
    scoped_ptr<base::DictionaryValue>* geolocation) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::GetGeolocation,
      base::Unretained(automation_.get()),
      geolocation,
      &error));
  return error;
}

Error* Session::OverrideGeolocation(const base::DictionaryValue* geolocation) {
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::OverrideGeolocation,
      base::Unretained(automation_.get()),
      geolocation,
      &error));
  return error;
}

const std::string& Session::id() const {
  return id_;
}

const FrameId& Session::current_target() const {
  return current_target_;
}

void Session::set_async_script_timeout(int timeout_ms) {
  async_script_timeout_ = timeout_ms;
}

int Session::async_script_timeout() const {
  return async_script_timeout_;
}

void Session::set_implicit_wait(int timeout_ms) {
  implicit_wait_ = timeout_ms;
}

int Session::implicit_wait() const {
  return implicit_wait_;
}

const Point& Session::get_mouse_position() const {
  return mouse_position_;
}

const Logger& Session::logger() const {
  return logger_;
}

const base::FilePath& Session::temp_dir() const {
  return temp_dir_.path();
}

const Capabilities& Session::capabilities() const {
  return capabilities_;
}

void Session::RunSessionTask(const base::Closure& task) {
  base::WaitableEvent done_event(false, false);
  thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
      &Session::RunClosureOnSessionThread,
      base::Unretained(this),
      task,
      &done_event));
  // See SetCookie for why it is essential that we wait here.
  done_event.Wait();
}

void Session::RunClosureOnSessionThread(const base::Closure& task,
                                        base::WaitableEvent* done_event) {
  task.Run();
  done_event->Signal();
}

void Session::InitOnSessionThread(const Automation::BrowserOptions& options,
                                  int* build_no,
                                  Error** error) {
  automation_.reset(new Automation(logger_));
  automation_->Init(options, build_no, error);
  if (*error)
    return;

  std::vector<WebViewInfo> views;
  automation_->GetViews(&views, error);
  if (*error)
    return;
  if (views.empty()) {
    *error = new Error(kUnknownError, "No view ids after initialization");
    return;
  }
  current_target_ = FrameId(views[0].view_id, FramePath());
}

void Session::TerminateOnSessionThread() {
  if (automation_.get())
    automation_->Terminate();
  automation_.reset();
}

Error* Session::ExecuteScriptAndParseValue(const FrameId& frame_id,
                                           const std::string& script,
                                           base::Value** script_result) {
  std::string response_json;
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::ExecuteScript,
      base::Unretained(automation_.get()),
      frame_id.view_id,
      frame_id.frame_path,
      script,
      &response_json,
      &error));
  if (error)
    return error;

  scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
      response_json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, NULL));
  if (!value.get())
    return new Error(kUnknownError, "Failed to parse script result");
  if (value->GetType() != base::Value::TYPE_DICTIONARY)
    return new Error(kUnknownError, "Execute script returned non-dict: " +
                         JsonStringify(value.get()));
  base::DictionaryValue* result_dict =
      static_cast<base::DictionaryValue*>(value.get());

  int status;
  if (!result_dict->GetInteger("status", &status))
    return new Error(kUnknownError, "Execute script did not return status: " +
                         JsonStringify(result_dict));
  ErrorCode code = static_cast<ErrorCode>(status);
  if (code != kSuccess) {
    base::DictionaryValue* error_dict;
    std::string error_msg;
    if (result_dict->GetDictionary("value", &error_dict))
      error_dict->GetString("message", &error_msg);
    if (error_msg.empty())
      error_msg = "Script failed with error code: " + base::IntToString(code);
    return new Error(code, error_msg);
  }

  base::Value* tmp;
  if (result_dict->Get("value", &tmp)) {
    *script_result= tmp->DeepCopy();
  } else {
    // "value" was not defined in the returned dictionary; set to null.
    *script_result= base::Value::CreateNullValue();
  }
  return NULL;
}

void Session::SendKeysOnSessionThread(const string16& keys,
                                      bool release_modifiers, Error** error) {
  std::vector<WebKeyEvent> key_events;
  std::string error_msg;
  if (!ConvertKeysToWebKeyEvents(keys, logger_, release_modifiers,
                                 &sticky_modifiers_, &key_events, &error_msg)) {
    *error = new Error(kUnknownError, error_msg);
    return;
  }
  for (size_t i = 0; i < key_events.size(); ++i) {
    automation_->SendWebKeyEvent(
        current_target_.view_id,
        key_events[i], error);
    if (*error) {
      std::string details = base::StringPrintf(
          "Failed to send key event. Event details:\n"
              "Type: %d, KeyCode: %d, UnmodifiedText: %s, ModifiedText: %s, "
              "Modifiers: %d",
          key_events[i].type,
          key_events[i].key_code,
          key_events[i].unmodified_text.c_str(),
          key_events[i].modified_text.c_str(),
          key_events[i].modifiers);
      (*error)->AddDetails(details);
      return;
    }
  }
}

Error* Session::ProcessWebMouseEvents(
    const std::vector<WebMouseEvent>& events) {
  for (size_t i = 0; i < events.size(); ++i) {
    Error* error = NULL;
    RunSessionTask(base::Bind(
        &Automation::SendWebMouseEvent,
        base::Unretained(automation_.get()),
        current_target_.view_id,
        events[i],
        &error));
    if (error)
      return error;
    mouse_position_ = Point(events[i].x, events[i].y);
  }
  return NULL;
}

WebMouseEvent Session::CreateWebMouseEvent(
    automation::MouseEventType type,
    automation::MouseButton button,
    const Point& point,
    int click_count) {
  return WebMouseEvent(type, button, point.rounded_x(), point.rounded_y(),
                       click_count, sticky_modifiers_);
}

Error* Session::SwitchToFrameWithJavaScriptLocatedFrame(
    const std::string& script, base::ListValue* args) {
  class SwitchFrameValueParser : public ValueParser {
   public:
    SwitchFrameValueParser(
        bool* found_frame, ElementId* frame)
        : found_frame_(found_frame), frame_(frame) { }

    virtual ~SwitchFrameValueParser() { }

    virtual bool Parse(base::Value* value) const OVERRIDE {
      if (value->IsType(base::Value::TYPE_NULL)) {
        *found_frame_ = false;
        return true;
      }
      ElementId id(value);
      if (!id.is_valid()) {
        return false;
      }
      *frame_ = id;
      *found_frame_ = true;
      return true;
    }

   private:
    bool* found_frame_;
    ElementId* frame_;
  };

  bool found_frame;
  ElementId new_frame_element;
  Error* error = ExecuteScriptAndParse(
      current_target_, script, "switchFrame", args,
      new SwitchFrameValueParser(&found_frame, &new_frame_element));
  if (error)
    return error;

  if (!found_frame)
    return new Error(kNoSuchFrame);

  std::string frame_id = GenerateRandomID();
  error = ExecuteScriptAndParse(
      current_target_,
      "function(elem, id) { elem.setAttribute('wd_frame_id_', id); }",
      "setFrameId",
      CreateListValueFrom(new_frame_element, frame_id),
      CreateDirectValueParser(kSkipParsing));
  if (error)
    return error;

  frame_elements_.push_back(new_frame_element);
  current_target_.frame_path = current_target_.frame_path.Append(
      base::StringPrintf("//*[@wd_frame_id_ = '%s']", frame_id.c_str()));
  return NULL;
}

Error* Session::FindElementsHelper(const FrameId& frame_id,
                                   const ElementId& root_element,
                                   const std::string& locator,
                                   const std::string& query,
                                   bool find_one,
                                   std::vector<ElementId>* elements) {
  CHECK(root_element.is_valid());
  base::Time start_time = base::Time::Now();
  while (true) {
    std::vector<ElementId> temp_elements;
    Error* error = ExecuteFindElementScriptAndParse(
        frame_id, root_element, locator, query, find_one, &temp_elements);
    if (error)
      return error;

    if (temp_elements.size() > 0u) {
      elements->swap(temp_elements);
      break;
    }

    if ((base::Time::Now() - start_time).InMilliseconds() > implicit_wait_) {
      if (find_one)
        return new Error(kNoSuchElement);
      break;
    }
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
  }
  return NULL;
}

Error* Session::ExecuteFindElementScriptAndParse(
    const FrameId& frame_id,
    const ElementId& root_element,
    const std::string& locator,
    const std::string& query,
    bool find_one,
    std::vector<ElementId>* elements) {
  CHECK(root_element.is_valid());

  class FindElementsParser : public ValueParser {
   public:
    explicit FindElementsParser(std::vector<ElementId>* elements)
        : elements_(elements) { }

    virtual ~FindElementsParser() { }

    virtual bool Parse(base::Value* value) const OVERRIDE {
      if (!value->IsType(base::Value::TYPE_LIST))
        return false;
      base::ListValue* list = static_cast<base::ListValue*>(value);
      for (size_t i = 0; i < list->GetSize(); ++i) {
        ElementId element;
        base::Value* element_value = NULL;
        if (!list->Get(i, &element_value))
          return false;
        if (!SetFromValue(element_value, &element))
          return false;
        elements_->push_back(element);
      }
      return true;
    }
   private:
    std::vector<ElementId>* elements_;
  };

  class FindElementParser : public ValueParser {
   public:
    explicit FindElementParser(std::vector<ElementId>* elements)
        : elements_(elements) { }

    virtual ~FindElementParser() { }

    virtual bool Parse(base::Value* value) const OVERRIDE {
      if (value->IsType(base::Value::TYPE_NULL))
        return true;
      ElementId element;
      bool set = SetFromValue(value, &element);
      if (set)
        elements_->push_back(element);
      return set;
    }
   private:
    std::vector<ElementId>* elements_;
  };

  base::DictionaryValue locator_dict;
  locator_dict.SetString(locator, query);
  std::vector<ElementId> temp_elements;
  Error* error = NULL;
  if (find_one) {
    error = ExecuteScriptAndParse(
          frame_id,
          atoms::asString(atoms::FIND_ELEMENT),
          "findElement",
          CreateListValueFrom(&locator_dict, root_element),
          new FindElementParser(&temp_elements));
  } else {
    error = ExecuteScriptAndParse(
          frame_id,
          atoms::asString(atoms::FIND_ELEMENTS),
          "findElements",
          CreateListValueFrom(&locator_dict, root_element),
          new FindElementsParser(&temp_elements));
  }
  if (!error)
    elements->swap(temp_elements);
  return error;
}

Error* Session::VerifyElementIsClickable(
    const FrameId& frame_id,
    const ElementId& element,
    const Point& location) {
  class IsElementClickableParser : public ValueParser {
   public:
    IsElementClickableParser(bool* clickable, std::string* message)
        : clickable_(clickable), message_(message) { }

    virtual ~IsElementClickableParser() { }

    virtual bool Parse(base::Value* value) const OVERRIDE {
      if (!value->IsType(base::Value::TYPE_DICTIONARY))
        return false;
      base::DictionaryValue* dict = static_cast<base::DictionaryValue*>(value);
      dict->GetString("message", message_);
      return dict->GetBoolean("clickable", clickable_);
    }

   private:
    bool* clickable_;
    std::string* message_;
  };

  bool clickable;
  std::string message;
  Error* error = ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::IS_ELEMENT_CLICKABLE),
      "isElementClickable",
      CreateListValueFrom(element, location),
      new IsElementClickableParser(&clickable, &message));
  if (error)
    return error;

  if (!clickable) {
    if (message.empty())
      message = "element is not clickable";
    return new Error(kUnknownError, message);
  }
  if (message.length()) {
    logger_.Log(kWarningLogLevel, message);
  }
  return NULL;
}

Error* Session::GetElementRegionInViewHelper(
    const FrameId& frame_id,
    const ElementId& element,
    const Rect& region,
    bool center,
    bool verify_clickable_at_middle,
    Point* location) {
  Point temp_location;
  Error* error = ExecuteScriptAndParse(
      frame_id,
      atoms::asString(atoms::GET_LOCATION_IN_VIEW),
      "getLocationInView",
      CreateListValueFrom(element, center, region),
      CreateDirectValueParser(&temp_location));

  if (verify_clickable_at_middle) {
    Point middle_point = temp_location;
    middle_point.Offset(region.width() / 2, region.height() / 2);
    error = VerifyElementIsClickable(frame_id, element, middle_point);
    if (error)
      return error;
  }
  *location = temp_location;
  return NULL;
}

Error* Session::GetScreenShot(std::string* png) {
  if (!current_target_.view_id.IsTab()) {
    return new Error(kUnknownError,
                     "The current target does not support screenshot");
  }
  Error* error = NULL;
  base::ScopedTempDir screenshots_dir;
  if (!screenshots_dir.CreateUniqueTempDir()) {
    return new Error(kUnknownError,
                     "Could not create temp directory for screenshot");
  }

  base::FilePath path = screenshots_dir.path().AppendASCII("screen");
  RunSessionTask(base::Bind(
      &Automation::CaptureEntirePageAsPNG,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      path,
      &error));
  if (error)
    return error;
  if (!file_util::ReadFileToString(path, png))
    return new Error(kUnknownError, "Could not read screenshot file");
  return NULL;
}

#if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
Error* Session::HeapProfilerDump(const std::string& reason) {
  // TODO(dmikurube): Support browser processes.
  Error* error = NULL;
  RunSessionTask(base::Bind(
      &Automation::HeapProfilerDump,
      base::Unretained(automation_.get()),
      current_target_.view_id,
      reason,
      &error));
  return error;
}
#endif  // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))

Error* Session::PostBrowserStartInit() {
  Error* error = NULL;
  if (!capabilities_.no_website_testing_defaults)
    error = InitForWebsiteTesting();
  if (!error)
    error = SetPrefs();
  if (error)
    return error;

  // Install extensions.
  for (size_t i = 0; i < capabilities_.extensions.size(); ++i) {
    std::string extension_id;
    error = InstallExtension(capabilities_.extensions[i], &extension_id);
    if (error)
      return error;
  }
  return NULL;
}

Error* Session::InitForWebsiteTesting() {
  bool has_prefs_api = false;
  // Don't set these prefs for Chrome 14 and below.
  // TODO(kkania): Remove this when Chrome 14 is unsupported.
  Error* error = CompareBrowserVersion(874, 0, &has_prefs_api);
  if (error || !has_prefs_api)
    return error;

  // Disable checking for SSL certificate revocation.
  error = SetPreference(
      "ssl.rev_checking.enabled",
      false /* is_user_pref */,
      new base::FundamentalValue(false));
  if (error)
    return error;

  // Allow content by default.
  // Media-stream cannot be enabled by default; we must specify
  // particular host patterns and devices.
  base::DictionaryValue* devices = new base::DictionaryValue();
  devices->SetString("audio", "Default");
  devices->SetString("video", "Default");
  base::DictionaryValue* content_settings = new base::DictionaryValue();
  content_settings->Set("media-stream", devices);
  base::DictionaryValue* pattern_pairs = new base::DictionaryValue();
  pattern_pairs->Set("https://*,*", content_settings);
  error = SetPreference(
      "profile.content_settings.pattern_pairs",
      true /* is_user_pref */,
      pattern_pairs);
  if (error)
    return error;
  const int kAllowContent = 1;
  base::DictionaryValue* default_content_settings = new base::DictionaryValue();
  default_content_settings->SetInteger("geolocation", kAllowContent);
  default_content_settings->SetInteger("mouselock", kAllowContent);
  default_content_settings->SetInteger("notifications", kAllowContent);
  default_content_settings->SetInteger("popups", kAllowContent);
  return SetPreference(
      "profile.default_content_settings",
      true /* is_user_pref */,
      default_content_settings);
}

Error* Session::SetPrefs() {
  for (base::DictionaryValue::Iterator iter(*capabilities_.prefs);
       !iter.IsAtEnd(); iter.Advance()) {
    Error* error = SetPreference(iter.key(), true /* is_user_pref */,
                                 iter.value().DeepCopy());
    if (error)
      return error;
  }
  for (base::DictionaryValue::Iterator iter(*capabilities_.local_state);
       !iter.IsAtEnd(); iter.Advance()) {
    Error* error = SetPreference(iter.key(), false /* is_user_pref */,
                                 iter.value().DeepCopy());
    if (error)
      return error;
  }
  return NULL;
}

}  // namespace webdriver
