blob: b37fb927bdf7cf7dd669d673edaf8317cd4d9753 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/public/web/web_link_preview_triggerer.h"
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "ui/events/keycodes/dom/dom_code.h"
namespace blink {
class MockWebLinkPreviewTriggerer : public WebLinkPreviewTriggerer {
public:
MockWebLinkPreviewTriggerer() = default;
~MockWebLinkPreviewTriggerer() override = default;
int LastKeyEventModifiers() const { return last_key_event_modifiers_; }
const WebElement& HoverElement() const { return hover_element_; }
const WebElement& MouseEventElement() const { return mouse_event_element_; }
const std::optional<blink::WebMouseEvent::Button>& MouseEventButton() const {
return mouse_event_button_;
}
const std::optional<int>& MouseEventClickCount() const {
return mouse_event_click_count_;
}
void MaybeChangedKeyEventModifier(int modifiers) override {
last_key_event_modifiers_ = modifiers;
}
void DidChangeHoverElement(blink::WebElement element) override {
hover_element_ = element;
}
void DidAnchorElementReceiveMouseDownEvent(
blink::WebElement anchor_element,
blink::WebMouseEvent::Button button,
int click_count) override {
mouse_event_element_ = anchor_element;
mouse_event_button_ = button;
mouse_event_click_count_ = click_count;
}
private:
int last_key_event_modifiers_ = blink::WebInputEvent::kNoModifiers;
WebElement hover_element_;
WebElement mouse_event_element_;
std::optional<blink::WebMouseEvent::Button> mouse_event_button_;
std::optional<int> mouse_event_click_count_;
};
class WebLinkPreviewTriggererTest : public PageTestBase {
protected:
void Initialize() {
LocalFrame* local_frame = GetDocument().GetFrame();
CHECK(local_frame);
local_frame->SetLinkPreviewTriggererForTesting(
std::make_unique<MockWebLinkPreviewTriggerer>());
}
void SetInnerHTML(const String& html) {
GetDocument().documentElement()->setInnerHTML(html);
}
};
TEST_F(WebLinkPreviewTriggererTest, MaybeChangedKeyEventModifierCalled) {
Initialize();
SetHtmlInnerHTML("<div></div>");
MockWebLinkPreviewTriggerer* triggerer =
static_cast<MockWebLinkPreviewTriggerer*>(
GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
WebKeyboardEvent e0{WebInputEvent::Type::kRawKeyDown, WebInputEvent::kAltKey,
WebInputEvent::GetStaticTimeStampForTests()};
e0.dom_code = static_cast<int>(ui::DomCode::ALT_LEFT);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e0);
EXPECT_EQ(WebInputEvent::kAltKey, triggerer->LastKeyEventModifiers());
WebKeyboardEvent e1{WebInputEvent::Type::kKeyUp, WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests()};
e1.dom_code = static_cast<int>(ui::DomCode::ALT_LEFT);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e1);
EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
}
TEST_F(WebLinkPreviewTriggererTest,
MaybeChangedKeyEventModifierCalledWithNoModifiersOnMouseLeave) {
Initialize();
SetHtmlInnerHTML("<div></div>");
MockWebLinkPreviewTriggerer* triggerer =
static_cast<MockWebLinkPreviewTriggerer*>(
GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
WebKeyboardEvent e0{WebInputEvent::Type::kRawKeyDown, WebInputEvent::kAltKey,
WebInputEvent::GetStaticTimeStampForTests()};
e0.dom_code = static_cast<int>(ui::DomCode::ALT_LEFT);
GetDocument().GetFrame()->GetEventHandler().KeyEvent(e0);
EXPECT_EQ(WebInputEvent::kAltKey, triggerer->LastKeyEventModifiers());
WebMouseEvent e1(WebMouseEvent::Type::kMouseLeave, gfx::PointF(262, 29),
gfx::PointF(329, 67),
WebPointerProperties::Button::kNoButton, 1,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent(e1);
EXPECT_EQ(WebInputEvent::kNoModifiers, triggerer->LastKeyEventModifiers());
}
TEST_F(WebLinkPreviewTriggererTest, DidChangeHoverElementCalledOnHoverChanged) {
Initialize();
SetHtmlInnerHTML(
"<style>"
" body { margin:0px; }"
" a { display:block; width:100px; height:100px; }"
"</style>"
"<body>"
" <a href=\"https://example.com\">anchor</a>"
"</body>");
MockWebLinkPreviewTriggerer* triggerer =
static_cast<MockWebLinkPreviewTriggerer*>(
GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
{
gfx::PointF point(50, 50);
WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove, point,
point,
WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
EXPECT_FALSE(triggerer->HoverElement().IsNull());
EXPECT_EQ("A", triggerer->HoverElement().TagName());
EXPECT_EQ("https://example.com",
triggerer->HoverElement().GetAttribute("href"));
}
{
gfx::PointF point(200, 200);
WebMouseEvent mouse_move_event(WebInputEvent::Type::kMouseMove, point,
point,
WebPointerProperties::Button::kNoButton, 0,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
EXPECT_FALSE(triggerer->HoverElement().IsNull());
EXPECT_EQ("HTML", triggerer->HoverElement().TagName());
}
}
TEST_F(WebLinkPreviewTriggererTest,
DidAnchorElementReceiveMouseDownEventCalledOnMousePress) {
Initialize();
SetHtmlInnerHTML(
"<style>"
" body { margin:0px; }"
" a { display:block; width:100px; height:100px; }"
"</style>"
"<body>"
" <a href=\"https://example.com\">anchor</a>"
"</body>");
MockWebLinkPreviewTriggerer* triggerer =
static_cast<MockWebLinkPreviewTriggerer*>(
GetDocument().GetFrame()->GetOrCreateLinkPreviewTriggerer());
gfx::PointF point(50, 50);
WebMouseEvent mouse_down_event(WebInputEvent::Type::kMouseDown, point, point,
WebPointerProperties::Button::kLeft, 1,
WebInputEvent::Modifiers::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests());
GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
mouse_down_event);
EXPECT_FALSE(triggerer->MouseEventElement().IsNull());
EXPECT_EQ("https://example.com",
triggerer->MouseEventElement().GetAttribute("href"));
EXPECT_EQ(WebMouseEvent::Button::kLeft, triggerer->MouseEventButton());
EXPECT_EQ(1, triggerer->MouseEventClickCount());
}
} // namespace blink