// 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 "base/threading/thread_task_runner_handle.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::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), window_task_runner_);
  for (auto i : element_drivers_) {
    // Note: The element_task_runner_ is the same as the window_task_runner_.
    auto weak_element = i.second->GetWeakElement();
    if (element == weak_element) {
      return i.second->element_id();
    }
  }

  return CreateNewElementDriver(base::AsWeakPtr(element.get()));
}

scoped_refptr<dom::Element> WindowDriver::IdToElement(
    const protocol::ElementId& id) {
  DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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());
  }

  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::ThreadTaskRunnerHandle::Get(), window_task_runner_);
  if (!window_) {
    return CommandResult(protocol::Response::kNoSuchWindow);
  }

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

util::CommandResult<void> WindowDriver::NavigateInternal(const GURL& url) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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(base::Token type,
                                      const dom::PointerEventInit& event,
                                      scoped_refptr<dom::Element> element) {
  pointer_x_ = event.screen_x();
  pointer_y_ = event.screen_y();
  pointer_event_injector_.Run(type, event, element);
}

util::CommandResult<void> WindowDriver::MouseMoveToInternal(
    const protocol::Moveto& moveto) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), 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://www.selenium.dev/documentation/legacy/json_wire_protocol/#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(base::Tokens::pointermove(), event,
                              scoped_refptr<dom::Element>());

  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(base::Tokens::pointerup(), event,
                              scoped_refptr<dom::Element>());
}

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(base::Tokens::pointerdown(), event,
                              scoped_refptr<dom::Element>());
}

util::CommandResult<void> WindowDriver::MouseButtonDownInternal(
    const protocol::Button& button) {
  typedef util::CommandResult<void> CommandResult;
  DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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::ThreadTaskRunnerHandle::Get(), 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
