chromium/content/web_test/renderer/event_sender.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/342213636): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include "content/web_test/renderer/event_sender.h"

#include <stddef.h>

#include <algorithm>
#include <limits>
#include <memory>
#include <string>

#include "base/check_op.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/render_frame_impl.h"
#include "content/web_test/renderer/test_runner.h"
#include "content/web_test/renderer/web_frame_test_proxy.h"
#include "content/web_test/renderer/web_test_spell_checker.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
#include "net/base/filename_util.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/blink/public/common/context_menu_data/context_menu_data.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/input/web_pointer_properties.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/mojom/input/pointer_lock_result.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_page_popup.h"
#include "third_party/blink/public/web/web_view.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "v8/include/v8.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif

ContextMenuData;
DragOperationsMask;
MenuItemInfo;
WebDragData;
WebGestureEvent;
WebInputEvent;
WebInputEventResult;
WebKeyboardEvent;
WebLocalFrame;
WebMouseEvent;
WebMouseWheelEvent;
WebPagePopup;
WebPointerEvent;
WebPointerProperties;
WebString;
WebTouchEvent;
WebTouchPoint;
WebURL;
WebVector;
WebView;

namespace content {

namespace {

const int kRawMousePointerId =;
const char* const kPointerTypeStringUnknown =;
const char* const kPointerTypeStringMouse =;
const char* const kPointerTypeStringTouch =;
const char* const kPointerTypeStringPen =;
const char* const kPointerTypeStringEraser =;

// Assigns |pointerType| from the provided |args|. Returns false if there was
// any error.
bool GetPointerType(gin::Arguments* args,
                    bool isOnlyMouseAndPenAllowed,
                    WebPointerProperties::PointerType& pointerType) {}

WebInputEvent::Type PointerEventTypeForTouchPointState(
    WebTouchPoint::State state) {}

// Parses |pointerType|, |rawPointerId|, |pressure|, |tiltX| and |tiltY| from
// the provided |args|. Returns false if there was any error, assuming the last
// 3 of the five parsed parameters are optional.
bool getMousePenPointerProperties(
    gin::Arguments* args,
    WebPointerProperties::PointerType& pointerType,
    int& rawPointerId,
    float& pressure,
    int& tiltX,
    int& tiltY) {}

WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {}

int GetWebMouseEventModifierForButton(WebMouseEvent::Button button) {}

const int kButtonsInModifiers =;

int ModifiersWithButtons(int modifiers, int buttons) {}

void InitMouseEventGeneric(WebMouseEvent::Button b,
                           int current_buttons,
                           const gfx::PointF& pos,
                           int click_count,
                           WebPointerProperties::PointerType pointerType,
                           int pointerId,
                           float pressure,
                           int tiltX,
                           int tiltY,
                           WebMouseEvent* e) {}

void InitMouseEvent(WebMouseEvent::Button b,
                    int current_buttons,
                    const gfx::PointF& pos,
                    int click_count,
                    WebMouseEvent* e) {}

int GetKeyModifier(const std::string& modifier_name) {}

int GetKeyModifiers(const std::vector<std::string>& modifier_names) {}

int GetKeyModifiersFromV8(v8::Isolate* isolate, v8::Local<v8::Value> value) {}

WebMouseWheelEvent::Phase GetMouseWheelEventPhase(
    const std::string& phase_name) {}

WebMouseWheelEvent::Phase GetMouseWheelEventPhaseFromV8(
    v8::Isolate* isolate,
    v8::Local<v8::Value> value) {}

// Maximum distance (in space and time) for a mouse click to register as a
// double or triple click.
constexpr base::TimeDelta kMultipleClickTime =;
const int kMultipleClickRadiusPixels =;
const char kSubMenuDepthIdentifier[] =;
const char kSubMenuIdentifier[] =;
const char kSeparatorIdentifier[] =;
const char kDisabledIdentifier[] =;
const char kCheckedIdentifier[] =;

bool OutsideRadius(const gfx::PointF& a, const gfx::PointF& b, float radius) {}

void PopulateCustomItems(const WebVector<MenuItemInfo>& customItems,
                         const std::string& prefix,
                         std::vector<std::string>* strings) {}

// Because actual context menu is implemented by the browser side,
// this function does only what web_tests are expecting:
// - Many test checks the count of items. So returning non-zero value makes
// sense.
// - Some test compares the count before and after some action. So changing the
// count based on flags also makes sense. This function is doing such for some
// flags.
// - Some test even checks actual string content. So providing it would be also
// helpful.
std::vector<std::string> MakeMenuItemStringsFor(ContextMenuData* context_menu) {}

// How much we should scroll per event - the value here is chosen to match the
// WebKit impl and web test results.
const float kScrollbarPixelsPerTick =;

// Get the edit command corresponding to a keyboard event.
// Returns true if the specified event corresponds to an edit command, the name
// of the edit command will be stored in |*name|.
bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {}

bool IsSystemKeyEvent(const WebKeyboardEvent& event) {}

const char* kSourceDeviceStringTouchpad =;
const char* kSourceDeviceStringTouchscreen =;

}  // namespace

class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {};

gin::WrapperInfo EventSenderBindings::kWrapperInfo =;

EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender,
                                         WebFrameTestProxy* frame)
    :{}

EventSenderBindings::~EventSenderBindings() = default;

// static
void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
                                  WebFrameTestProxy* frame) {}

gin::ObjectTemplateBuilder EventSenderBindings::GetObjectTemplateBuilder(
    v8::Isolate* isolate) {}

void EventSenderBindings::EnableDOMUIEventLogging() {}

void EventSenderBindings::FireKeyboardEventsToElement() {}

void EventSenderBindings::ClearKillRing() {}

std::vector<std::string> EventSenderBindings::ContextClick() {}

void EventSenderBindings::ClearTouchPoints() {}

void EventSenderBindings::ReleaseTouchPoint(unsigned index) {}

void EventSenderBindings::UpdateTouchPoint(unsigned index,
                                           double x,
                                           double y,
                                           gin::Arguments* args) {}

void EventSenderBindings::CancelTouchPoint(unsigned index) {}

void EventSenderBindings::SetTouchModifier(const std::string& key_name,
                                           bool set_mask) {}

void EventSenderBindings::SetTouchCancelable(bool cancelable) {}

void EventSenderBindings::DumpFilenameBeingDragged() {}

void EventSenderBindings::TouchStart(gin::Arguments* args) {}

void EventSenderBindings::TouchMove(gin::Arguments* args) {}

void EventSenderBindings::TouchCancel(gin::Arguments* args) {}

void EventSenderBindings::TouchEnd(gin::Arguments* args) {}

void EventSenderBindings::NotifyStartOfTouchScroll() {}

void EventSenderBindings::LeapForward(int milliseconds) {}

double EventSenderBindings::LastEventTimestamp() {}

void EventSenderBindings::BeginDragWithFiles(
    const std::vector<std::string>& files) {}

void EventSenderBindings::BeginDragWithStringData(
    const std::string& data,
    const std::string& mime_type) {}

void EventSenderBindings::AddTouchPoint(double x,
                                        double y,
                                        gin::Arguments* args) {}

void EventSenderBindings::GestureScrollPopup(gin::Arguments* args) {}

void EventSenderBindings::GestureTap(gin::Arguments* args) {}

void EventSenderBindings::GestureTapDown(gin::Arguments* args) {}

void EventSenderBindings::GestureShowPress(gin::Arguments* args) {}

void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {}

void EventSenderBindings::GestureLongPress(gin::Arguments* args) {}

void EventSenderBindings::GestureLongTap(gin::Arguments* args) {}

void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {}

void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {}

void EventSenderBindings::MouseLeave(gin::Arguments* args) {}

void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {}

void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {}

void EventSenderBindings::ConsumeUserActivation() {}

void EventSenderBindings::MouseDown(gin::Arguments* args) {}

void EventSenderBindings::MouseUp(gin::Arguments* args) {}

void EventSenderBindings::SetMouseButtonState(gin::Arguments* args) {}

// `KeyDown` sends both `KeyDown` and `KeyUp` events. It's similar to `KeyPress`
// in other APIs.
void EventSenderBindings::KeyDown(gin::Arguments* args) {}

// `KeyDownAsync` sends both `KeyDown` and `KeyUp` events. It's similar to
// `KeyPress` in other APIs. It sends those events asynchronously, outside of a
// JS task.
void EventSenderBindings::KeyDownAsync(gin::Arguments* args) {}

// `KeyDownOnly` sends `KeyDown` without `KeyUp`.
void EventSenderBindings::KeyDownOnly(gin::Arguments* args) {}

void EventSenderBindings::KeyUp(gin::Arguments* args) {}

void EventSenderBindings::KeyEvent(EventSender::KeyEventType event_type,
                                   gin::Arguments* args,
                                   bool async) {}

bool EventSenderBindings::ForceLayoutOnEvents() const {}

void EventSenderBindings::SetForceLayoutOnEvents(bool force) {}

bool EventSenderBindings::IsDragMode() const {}

void EventSenderBindings::SetIsDragMode(bool drag_mode) {}

#if BUILDFLAG(IS_WIN)
int EventSenderBindings::WmKeyDown() const {
  if (sender_)
    return sender_->wm_key_down();
  return 0;
}

void EventSenderBindings::SetWmKeyDown(int key_down) {
  if (sender_)
    sender_->set_wm_key_down(key_down);
}

int EventSenderBindings::WmKeyUp() const {
  if (sender_)
    return sender_->wm_key_up();
  return 0;
}

void EventSenderBindings::SetWmKeyUp(int key_up) {
  if (sender_)
    sender_->set_wm_key_up(key_up);
}

int EventSenderBindings::WmChar() const {
  if (sender_)
    return sender_->wm_char();
  return 0;
}

void EventSenderBindings::SetWmChar(int wm_char) {
  if (sender_)
    sender_->set_wm_char(wm_char);
}

int EventSenderBindings::WmDeadChar() const {
  if (sender_)
    return sender_->wm_dead_char();
  return 0;
}

void EventSenderBindings::SetWmDeadChar(int dead_char) {
  if (sender_)
    sender_->set_wm_dead_char(dead_char);
}

int EventSenderBindings::WmSysKeyDown() const {
  if (sender_)
    return sender_->wm_sys_key_down();
  return 0;
}

void EventSenderBindings::SetWmSysKeyDown(int key_down) {
  if (sender_)
    sender_->set_wm_sys_key_down(key_down);
}

int EventSenderBindings::WmSysKeyUp() const {
  if (sender_)
    return sender_->wm_sys_key_up();
  return 0;
}

void EventSenderBindings::SetWmSysKeyUp(int key_up) {
  if (sender_)
    sender_->set_wm_sys_key_up(key_up);
}

int EventSenderBindings::WmSysChar() const {
  if (sender_)
    return sender_->wm_sys_char();
  return 0;
}

void EventSenderBindings::SetWmSysChar(int sys_char) {
  if (sender_)
    sender_->set_wm_sys_char(sys_char);
}

int EventSenderBindings::WmSysDeadChar() const {
  if (sender_)
    return sender_->wm_sys_dead_char();
  return 0;
}

void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
  if (sender_)
    sender_->set_wm_sys_dead_char(sys_dead_char);
}
#endif

// EventSender -----------------------------------------------------------------

WebMouseEvent::Button EventSender::last_button_type_ =;

EventSender::SavedEvent::SavedEvent()
    :{}

EventSender::EventSender(blink::WebFrameWidget* web_frame_widget,
                         content::TestRunner* test_runner)
    :{}

EventSender::~EventSender() {}

void EventSender::Reset() {}

void EventSender::Install(WebFrameTestProxy* frame) {}

void EventSender::SetContextMenuData(const ContextMenuData& data) {}

int EventSender::ModifiersForPointer(int pointer_id) {}

void EventSender::DoDragDrop(const WebDragData& drag_data,
                             DragOperationsMask mask) {}

void EventSender::MouseDown(int button_number, int modifiers) {}

void EventSender::MouseUp(int button_number, int modifiers) {}

void EventSender::PointerDown(int button_number,
                              int modifiers,
                              WebPointerProperties::PointerType pointerType,
                              int pointerId,
                              float pressure,
                              int tiltX,
                              int tiltY) {}

void EventSender::PointerUp(int button_number,
                            int modifiers,
                            WebPointerProperties::PointerType pointerType,
                            int pointerId,
                            float pressure,
                            int tiltX,
                            int tiltY) {}

void EventSender::SetMouseButtonState(int button_number, int modifiers) {}

// `KeyDown` sends both `KeyDown` and `KeyUp` events. It's similar to `KeyPress`
// in other APIs.
void EventSender::KeyDown(const std::string& code_str,
                          int modifiers,
                          KeyLocationCode location) {}

void EventSender::KeyEvent(KeyEventType event_type,
                           const std::string& code_str,
                           int modifiers,
                           KeyLocationCode location,
                           bool async) {}

void EventSender::EnableDOMUIEventLogging() {}

void EventSender::FireKeyboardEventsToElement() {}

void EventSender::ClearKillRing() {}

std::vector<std::string> EventSender::ContextClick() {}

void EventSender::ClearTouchPoints() {}

void EventSender::ThrowTouchPointError() {}

void EventSender::ReleaseTouchPoint(unsigned index) {}

void EventSender::UpdateTouchPoint(unsigned index,
                                   float x,
                                   float y,
                                   gin::Arguments* args) {}

void EventSender::CancelTouchPoint(unsigned index) {}

void EventSender::SetTouchModifier(const std::string& key_name, bool set_mask) {}

void EventSender::SetTouchCancelable(bool cancelable) {}

void EventSender::DumpFilenameBeingDragged(blink::WebLocalFrame* frame) {}

void EventSender::TouchStart(gin::Arguments* args) {}

void EventSender::TouchMove(gin::Arguments* args) {}

void EventSender::TouchCancel(gin::Arguments* args) {}

void EventSender::TouchEnd(gin::Arguments* args) {}

void EventSender::NotifyStartOfTouchScroll() {}

void EventSender::LeapForward(int milliseconds) {}

void EventSender::BeginDragWithItems(
    blink::WebLocalFrame* frame,
    const WebVector<WebDragData::Item>& items) {}

void EventSender::BeginDragWithFiles(blink::WebLocalFrame* frame,
                                     const std::vector<std::string>& files) {}

void EventSender::BeginDragWithStringData(blink::WebLocalFrame* frame,
                                          const std::string& data,
                                          const std::string& mime_type) {}

void EventSender::AddTouchPoint(float x, float y, gin::Arguments* args) {}

void EventSender::GestureScrollPopup(blink::WebLocalFrame* frame,
                                     gin::Arguments* args) {}

void EventSender::GestureTap(blink::WebLocalFrame* frame,
                             gin::Arguments* args) {}

void EventSender::GestureTapDown(blink::WebLocalFrame* frame,
                                 gin::Arguments* args) {}

void EventSender::GestureShowPress(blink::WebLocalFrame* frame,
                                   gin::Arguments* args) {}

void EventSender::GestureTapCancel(blink::WebLocalFrame* frame,
                                   gin::Arguments* args) {}

void EventSender::GestureLongPress(blink::WebLocalFrame* frame,
                                   gin::Arguments* args) {}

void EventSender::GestureLongTap(blink::WebLocalFrame* frame,
                                 gin::Arguments* args) {}

void EventSender::GestureTwoFingerTap(blink::WebLocalFrame* frame,
                                      gin::Arguments* args) {}

void EventSender::MouseMoveTo(blink::WebLocalFrame* frame,
                              gin::Arguments* args) {}

void EventSender::MouseLeave(
    blink::WebPointerProperties::PointerType pointerType,
    int pointerId) {}

void EventSender::ScheduleAsynchronousClick(WebLocalFrame* frame,
                                            int button_number,
                                            int modifiers) {}

void EventSender::ScheduleAsynchronousKeyDown(blink::WebLocalFrame* frame,
                                              const std::string& code_str,
                                              int modifiers,
                                              KeyLocationCode location) {}

void EventSender::ConsumeUserActivation() {}

base::TimeTicks EventSender::GetCurrentEventTime() const {}

void EventSender::DoLeapForward(int milliseconds) {}

uint32_t EventSender::GetUniqueTouchEventId(gin::Arguments* args) {}

void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type,
                                        gin::Arguments* args) {}

void EventSender::GestureEvent(WebInputEvent::Type type,
                               blink::WebLocalFrame* frame,
                               gin::Arguments* args) {}

void EventSender::UpdateClickCountForButton(WebMouseEvent::Button button_type) {}

WebMouseWheelEvent EventSender::GetMouseWheelEvent(gin::Arguments* args,
                                                   MouseScrollType scroll_type,
                                                   bool* send_gestures) {}

// Radius fields radius_x and radius_y should eventually be moved to
// WebPointerProperties.
// TODO(e_hakkinen): Drop radius_{x,y}_pointer parameters once that happens.
void EventSender::InitPointerProperties(gin::Arguments* args,
                                        WebPointerProperties* e,
                                        float* radius_x_pointer,
                                        float* radius_y_pointer) {}

void EventSender::FinishDragAndDrop(const WebMouseEvent& event,
                                    ui::mojom::DragOperation drag_effect,
                                    bool document_is_handling_drag) {}

void EventSender::DoDragAfterMouseUp(const WebMouseEvent& event) {}

void EventSender::DoDragAfterMouseMove(const WebMouseEvent& event) {}

void EventSender::ReplaySavedEvents() {}
std::optional<blink::WebInputEventResult>
EventSender::HandleInputEventOnViewOrPopup(const WebInputEvent& event,
                                           bool async) {}

const blink::WebView* EventSender::view() const {}

blink::WebView* EventSender::view() {}

blink::WebWidget* EventSender::widget() {}

blink::WebFrameWidget* EventSender::MainFrameWidget() {}

void EventSender::UpdateLifecycleToPrePaint() {}

float EventSender::DeviceScaleFactorForEvents() {}

}  // namespace content