// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/webdriver/window_driver.h"

#include <memory>
#include <utility>

#include "base/synchronization/waitable_event.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_rect.h"
#include "cobalt/dom/location.h"
#include "cobalt/dom/pointer_event.h"
#include "cobalt/dom/pointer_event_init.h"
#include "cobalt/math/clamp.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/logging_exception_state.h"
#include "cobalt/webdriver/keyboard.h"
#include "cobalt/webdriver/search.h"
#include "cobalt/webdriver/util/call_on_message_loop.h"

namespace cobalt {
namespace webdriver {
namespace {

const int kWebDriverMousePointerId = 0x12345678;

class SyncExecuteResultHandler : public ScriptExecutorResult::ResultHandler {
 public:
  void OnResult(const std::string& result) override {
    DCHECK(!result_);
    result_ = result;
  }
  void OnTimeout() override { NOTREACHED(); }
  std::string result() const {
    DCHECK(result_);
    return result_.value_or(std::string());
  }

 private:
  base::Optional<std::string> result_;
};

class AsyncExecuteResultHandler : public ScriptExecutorResult::ResultHandler {
 public:
  AsyncExecuteResultHandler()
      : timed_out_(false),
        event_(base::WaitableEvent::ResetPolicy::MANUAL,
               base::WaitableEvent::InitialState::NOT_SIGNALED) {}

  void WaitForResult() { event_.Wait(); }
  bool timed_out() const { return timed_out_; }
  const std::string& result() const { return result_; }

 private:
  void OnResult(const std::string& result) override {
    result_ = result;
    event_.Signal();
  }
  void OnTimeout() override {
    timed_out_ = true;
    event_.Signal();
  }

  std::string result_;
  bool timed_out_;
  base::WaitableEvent event_;
};

std::string GetCurrentUrl(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->location());
  return window->location()->href();
}

std::string GetTitle(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->document());
  return window->document()->title();
}

protocol::Size GetWindowSize(dom::Window* window) {
  DCHECK(window);
  float width = window->outer_width();
  float height = window->outer_height();
  return protocol::Size(width, height);
}

std::string GetSource(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->document());
  DCHECK(window->document()->document_element());
  return window->document()->document_element()->outer_html(NULL);
}

std::vector<protocol::Cookie> GetAllCookies(dom::Window* window) {
  DCHECK(window);
  DCHECK(window->document());
  std::string cookies_string = window->document()->cookie();
  std::vector<protocol::Cookie> cookies;
  protocol::Cookie::ToCookieVector(cookies_string, &cookies);
  return cookies;
}

}  // namespace

WindowDriver::WindowDriver(
    const protocol::WindowId& window_id,
    const base::WeakPtr<dom::Window>& window,
    const GetGlobalEnvironmentFunction& get_global_environment_function,
    KeyboardEventInjector keyboard_event_injector,
    PointerEventInjector pointer_event_injector,
    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
    : window_id_(window_id),
      window_(window),
      get_global_environment_(get_global_environment_function),
      keyboard_event_injector_(keyboard_event_injector),
      pointer_event_injector_(pointer_event_injector),
      window_task_runner_(task_runner),
      next_element_id_(0),
      pointer_buttons_(0),
      pointer_x_(0),
      pointer_y_(0) {
  DCHECK(window_task_runner_);
  // The WindowDriver may have been created on some arbitrary thread (i.e. the
  // thread that owns the Window). Detach the thread checker so it can be
  // re-bound to the next thread that calls a webdriver API, which should be
  // the WebDriver thread.
  DETACH_FROM_THREAD(thread_checker_);
}

WindowDriver::~WindowDriver() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Ensure ElementDrivers that this WindowDriver owns are deleted on
  // destruction of the WindowDriver.
  for (auto i : element_drivers_) {
    delete i.second;
  }
}

ElementDriver* WindowDriver::GetElementDriver(
    const protocol::ElementId& element_id) {
  if (!window_task_runner_->BelongsToCurrentThread()) {
    // It's expected that the WebDriver thread is the only other thread to call
    // this function.
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    ElementDriver* result;
    bool success = util::TryCallOnMessageLoop(
        window_task_runner_,
        base::Bind(&WindowDriver::GetElementDriver, base::Unretained(this),
                   element_id),
        &result);
    return success ? result : NULL;
  }
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  ElementDriverMap::iterator it = element_drivers_.find(element_id.id());
  if (it != element_drivers_.end()) {
    return it->second;
  }
  return NULL;
}

util::CommandResult<protocol::Size> WindowDriver::GetWindowSize() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_task_runner_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetWindowSize),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::Navigate(const GURL& url) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::NavigateInternal, base::Unretained(this), url),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<std::string> WindowDriver::GetCurrentUrl() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_task_runner_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetCurrentUrl),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<std::string> WindowDriver::GetTitle() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_task_runner_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetTitle),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<protocol::ElementId> WindowDriver::FindElement(
    const protocol::SearchStrategy& strategy) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::FindElementsInternal<protocol::ElementId>,
                 base::Unretained(this), strategy),
      protocol::Response::kNoSuchElement);
}

util::CommandResult<std::vector<protocol::ElementId> >
WindowDriver::FindElements(const protocol::SearchStrategy& strategy) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::FindElementsInternal<ElementIdVector>,
                 base::Unretained(this), strategy),
      protocol::Response::kNoSuchElement);
}

util::CommandResult<std::string> WindowDriver::GetSource() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_task_runner_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetSource),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<protocol::ScriptResult> WindowDriver::Execute(
    const protocol::Script& script) {
  typedef util::CommandResult<protocol::ScriptResult> CommandResult;
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Pre-load the ScriptExecutor source so we don't hit the disk on
  // window_task_runner_.
  ScriptExecutor::LoadExecutorSourceCode();

  SyncExecuteResultHandler result_handler;

  CommandResult result = util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::ExecuteScriptInternal, base::Unretained(this),
                 script, base::nullopt, &result_handler),
      protocol::Response::kNoSuchWindow);
  if (result.is_success()) {
    return CommandResult(protocol::ScriptResult(result_handler.result()));
  } else {
    return result;
  }
}

util::CommandResult<protocol::ScriptResult> WindowDriver::ExecuteAsync(
    const protocol::Script& script) {
  typedef util::CommandResult<protocol::ScriptResult> CommandResult;
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Pre-load the ScriptExecutor source so we don't hit the disk on
  // window_task_runner_.
  ScriptExecutor::LoadExecutorSourceCode();

  const base::TimeDelta kDefaultAsyncTimeout =
      base::TimeDelta::FromMilliseconds(0);
  AsyncExecuteResultHandler result_handler;
  CommandResult result = util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::ExecuteScriptInternal, base::Unretained(this),
                 script, kDefaultAsyncTimeout, &result_handler),
      protocol::Response::kNoSuchWindow);

  if (!result.is_success()) {
    return result;
  }

  result_handler.WaitForResult();
  if (result_handler.timed_out()) {
    return CommandResult(protocol::Response::kTimeOut);
  } else {
    return CommandResult(protocol::ScriptResult(result_handler.result()));
  }
}

util::CommandResult<void> WindowDriver::SendKeys(const protocol::Keys& keys) {
  // Translate the keys into KeyboardEvents. Don't reset modifiers.
  std::unique_ptr<Keyboard::KeyboardEventVector> events(
      new Keyboard::KeyboardEventVector());
  Keyboard::TranslateToKeyEvents(keys.utf8_keys(), Keyboard::kKeepModifiers,
                                 events.get());
  // Dispatch the keyboard events.
  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::SendKeysInternal, base::Unretained(this),
                 base::Passed(&events)),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<protocol::ElementId> WindowDriver::GetActiveElement() {
  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::GetActiveElementInternal,
                 base::Unretained(this)),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::SwitchFrame(
    const protocol::FrameId& frame_id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Cobalt doesn't support frames, but if a WebDriver client requests to
  // switch to the top-level browsing context, trivially return success.
  if (frame_id.is_top_level_browsing_context()) {
    return util::CommandResult<void>(protocol::Response::kSuccess);
  } else {
    return util::CommandResult<void>(protocol::Response::kNoSuchFrame);
  }
}

util::CommandResult<std::vector<protocol::Cookie> >
WindowDriver::GetAllCookies() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallWeakOnMessageLoopAndReturnResult(
      window_task_runner_,
      base::Bind(&WindowDriver::GetWeak, base::Unretained(this)),
      base::Bind(&::cobalt::webdriver::GetAllCookies),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<std::vector<protocol::Cookie> > WindowDriver::GetCookie(
    const std::string& name) {
  typedef util::CommandResult<std::vector<protocol::Cookie> > CommandResult;
  CommandResult command_result = GetAllCookies();
  if (command_result.is_success()) {
    std::vector<protocol::Cookie> filtered_cookies;
    for (size_t i = 0; i < command_result.result().size(); ++i) {
      if (command_result.result()[i].name() == name) {
        filtered_cookies.push_back(command_result.result()[i]);
        break;
      }
    }
    command_result = CommandResult(filtered_cookies);
  }
  return command_result;
}

util::CommandResult<void> WindowDriver::AddCookie(
    const protocol::Cookie& cookie) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(window_task_runner_,
                                 base::Bind(&WindowDriver::AddCookieInternal,
                                            base::Unretained(this), cookie),
                                 protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::MouseMoveTo(
    const protocol::Moveto& moveto) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(window_task_runner_,
                                 base::Bind(&WindowDriver::MouseMoveToInternal,
                                            base::Unretained(this), moveto),
                                 protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::MouseButtonDown(
    const protocol::Button& button) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::MouseButtonDownInternal, base::Unretained(this),
                 button),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::MouseButtonUp(
    const protocol::Button& button) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(
      window_task_runner_,
      base::Bind(&WindowDriver::MouseButtonUpInternal, base::Unretained(this),
                 button),
      protocol::Response::kNoSuchWindow);
}

util::CommandResult<void> WindowDriver::SendClick(
    const protocol::Button& button) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return util::CallOnMessageLoop(window_task_runner_,
                                 base::Bind(&WindowDriver::SendClickInternal,
                                            base::Unretained(this), button),
                                 protocol::Response::kNoSuchWindow);
}

protocol::ElementId WindowDriver::ElementToId(
    const scoped_refptr<dom::Element>& element) {
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  return CreateNewElementDriver(base::AsWeakPtr(element.get()));
}

scoped_refptr<dom::Element> WindowDriver::IdToElement(
    const protocol::ElementId& id) {
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  return base::WrapRefCounted(
      GetElementDriver(protocol::ElementId(id))->GetWeakElement());
}

protocol::ElementId WindowDriver::CreateNewElementDriver(
    const base::WeakPtr<dom::Element>& weak_element) {
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);

  protocol::ElementId element_id(
      base::StringPrintf("element-%d", next_element_id_++));
  std::pair<ElementDriverMapIt, bool> pair_it =
      element_drivers_.insert(std::make_pair(
          element_id.id(),
          new ElementDriver(element_id, weak_element, this,
                            keyboard_event_injector_,
                            base::Bind(&WindowDriver::InjectPointerEvent,
                                       base::Unretained(this)),
                            window_task_runner_)));
  DCHECK(pair_it.second)
      << "An ElementDriver was already mapped to the element id: "
      << element_id.id();
  return element_id;
}

// Internal logic for FindElement and FindElements that must be run on the
// Window's message loop.
template <typename T>
util::CommandResult<T> WindowDriver::FindElementsInternal(
    const protocol::SearchStrategy& strategy) {
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  typedef util::CommandResult<T> CommandResult;
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  return Search::FindElementsUnderNode<T>(strategy, window_->document().get(),
                                          this);
}

util::CommandResult<protocol::ScriptResult> WindowDriver::ExecuteScriptInternal(
    const protocol::Script& script,
    base::Optional<base::TimeDelta> async_timeout,
    ScriptExecutorResult::ResultHandler* async_handler) {
  typedef util::CommandResult<protocol::ScriptResult> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  scoped_refptr<script::GlobalEnvironment> global_environment =
      get_global_environment_.Run();
  DCHECK(global_environment);

  // Lazily initialize this the first time we need to run a script. It must be
  // initialized on window_task_runner_. It can persist across multiple calls
  // to execute script, but must be destroyed along with the associated
  // global object, thus with the WindowDriver.
  if (!script_executor_) {
    scoped_refptr<ScriptExecutor> script_executor =
        ScriptExecutor::Create(this, global_environment);
    if (!script_executor) {
      DLOG(INFO) << "Failed to create ScriptExecutor.";
      return CommandResult(protocol::Response::kUnknownError);
    }
    script_executor_ = base::AsWeakPtr(script_executor.get());
  }

  DLOG(INFO) << "Executing: " << script.function_body();
  DLOG(INFO) << "Arguments: " << script.argument_array();

  auto gc_prevented_params =
      ScriptExecutorParams::Create(global_environment, script.function_body(),
                                   script.argument_array(), async_timeout);

  if (gc_prevented_params.params->function_object()) {
    if (script_executor_->Execute(gc_prevented_params.params, async_handler)) {
      return CommandResult(protocol::Response::kSuccess);
    }
  }
  return CommandResult(protocol::Response::kJavaScriptError);
}

util::CommandResult<void> WindowDriver::SendKeysInternal(
    std::unique_ptr<Keyboard::KeyboardEventVector> events) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  for (size_t i = 0; i < events->size(); ++i) {
    keyboard_event_injector_.Run(scoped_refptr<dom::Element>(),
                                 (*events)[i].first, (*events)[i].second);
  }
  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<void> WindowDriver::NavigateInternal(const GURL& url) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  window_->location()->Replace(url.spec());
  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<void> WindowDriver::AddCookieInternal(
    const protocol::Cookie& cookie) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  // If the domain was set, ensure that it is valid with respect to the
  // the document's domain.
  std::string document_domain = window_->document()->location()->host();

  if (cookie.domain()) {
    // This is the same way the domain is checked in FirefoxDriver.
    if (document_domain.find(cookie.domain().value()) == std::string::npos) {
      return CommandResult(protocol::Response::kInvalidCookieDomain);
    }
  }

  std::string cookie_string = cookie.ToCookieString(document_domain);
  window_->document()->set_cookie(cookie_string);
  return CommandResult(protocol::Response::kSuccess);
}

void WindowDriver::InitPointerEvent(dom::PointerEventInit* event) {
  event->set_buttons(pointer_buttons_);

  event->set_screen_x(pointer_x_);
  event->set_screen_y(pointer_y_);
  event->set_client_x(pointer_x_);
  event->set_client_y(pointer_y_);

  event->set_pointer_type("mouse");
  event->set_pointer_id(kWebDriverMousePointerId);
  event->set_width(0.0f);
  event->set_height(0.0f);
  event->set_pressure(pointer_buttons_ ? 0.5f : 0.0f);
  event->set_tilt_x(0.0f);
  event->set_tilt_y(0.0f);
  event->set_is_primary(true);
}

void WindowDriver::InjectPointerEvent(scoped_refptr<dom::Element> element,
                                      base::Token type,
                                      const dom::PointerEventInit& event) {
  pointer_x_ = event.screen_x();
  pointer_y_ = event.screen_y();
  pointer_event_injector_.Run(element, type, event);
}

util::CommandResult<void> WindowDriver::MouseMoveToInternal(
    const protocol::Moveto& moveto) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  // Move the mouse by an offset of the specified element. If no element is
  // specified, the move is relative to the current mouse cursor. If an element
  // is provided but no offset, the mouse will be moved to the center of the
  // element.
  //   https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidmoveto
  float x = 0;
  float y = 0;
  scoped_refptr<dom::Element> element;
  const base::Optional<protocol::ElementId>& element_id = moveto.element();
  if (element_id) {
    // The element to move to.
    element = IdToElement(*element_id);
  }
  if (element) {
    scoped_refptr<dom::DOMRect> rect = element->GetBoundingClientRect();
    if (rect) {
      if (moveto.xoffset()) {
        // X offset to move to, relative to the top-left corner of the element.
        x = rect->left() + *moveto.xoffset();
      } else {
        // If not specified, the mouse will move to the middle of the element.
        x = rect->left() + rect->width() / 2;
      }

      if (moveto.yoffset()) {
        // Y offset to move to, relative to the top-left corner of the element.
        y = rect->top() + *moveto.yoffset();
      } else {
        // If not specified, the mouse will move to the middle of the element.
        y = rect->top() + rect->height() / 2;
      }
    }
  } else {
    // If the element not specified or is null, the offset is relative to
    // current position of the mouse.
    x = pointer_x_;
    y = pointer_y_;
    if (moveto.xoffset()) {
      x += *moveto.xoffset();
    }
    if (moveto.yoffset()) {
      y += *moveto.yoffset();
    }
  }

  pointer_x_ = math::Clamp(x, 0.0f, GetWeak()->inner_width());
  pointer_y_ = math::Clamp(y, 0.0f, GetWeak()->inner_height());

  dom::PointerEventInit event;
  InitPointerEvent(&event);
  pointer_event_injector_.Run(scoped_refptr<dom::Element>(),
                              base::Tokens::pointermove(), event);

  return CommandResult(protocol::Response::kSuccess);
}

void WindowDriver::InjectMouseButtonUp(const protocol::Button& button) {
  dom::PointerEventInit event;
  event.set_button(button.button());

  // The buttons attribute reflects the state of the mouse's buttons for any
  // MouseEvent object (while it is being dispatched).
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#ref-for-dom-mouseevent-buttons-2
  // Clear the buttons state bit corresponding to the button that has just been
  // released.
  pointer_buttons_ &= ~(1 << event.button());

  InitPointerEvent(&event);

  pointer_event_injector_.Run(scoped_refptr<dom::Element>(),
                              base::Tokens::pointerup(), event);
}

void WindowDriver::InjectMouseButtonDown(const protocol::Button& button) {
  dom::PointerEventInit event;
  event.set_button(button.button());

  // The buttons attribute reflects the state of the mouse's buttons for any
  // MouseEvent object (while it is being dispatched).
  //   https://www.w3.org/TR/2016/WD-uievents-20160804/#ref-for-dom-mouseevent-buttons-2
  // Set the buttons state bit corresponding to the button that has just been
  // pressed.
  pointer_buttons_ |= 1 << event.button();

  InitPointerEvent(&event);

  pointer_event_injector_.Run(scoped_refptr<dom::Element>(),
                              base::Tokens::pointerdown(), event);
}

util::CommandResult<void> WindowDriver::MouseButtonDownInternal(
    const protocol::Button& button) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  InjectMouseButtonDown(button);

  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<void> WindowDriver::MouseButtonUpInternal(
    const protocol::Button& button) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  InjectMouseButtonUp(button);

  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<void> WindowDriver::SendClickInternal(
    const protocol::Button& button) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

  InjectMouseButtonDown(button);
  InjectMouseButtonUp(button);

  return CommandResult(protocol::Response::kSuccess);
}

util::CommandResult<protocol::ElementId>
WindowDriver::GetActiveElementInternal() {
  typedef util::CommandResult<protocol::ElementId> CommandResult;
  DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }
  scoped_refptr<dom::Element> active = window_->document()->active_element();
  if (active) {
    return CommandResult(ElementToId(active));
  } else {
    return CommandResult(protocol::Response::kUnknownError);
  }
}

}  // namespace webdriver
}  // namespace cobalt
