// 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_);
  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::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());
  }

  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
