Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: third_party/WebKit/Source/web/tests/LinkSelectionTest.cpp

Issue 1774123006: Implement link selection on alt+mouse drag. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/dom/Range.h"
6 #include "core/frame/FrameView.h"
7 #include "core/input/EventHandler.h"
8 #include "core/page/ChromeClient.h"
9 #include "core/page/ContextMenuController.h"
10 #include "core/page/FocusController.h"
11 #include "core/page/Page.h"
12 #include "platform/Cursor.h"
13 #include "platform/testing/URLTestHelpers.h"
14 #include "platform/testing/UnitTestHelpers.h"
15 #include "public/web/WebSettings.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "web/WebLocalFrameImpl.h"
19 #include "web/tests/SelectionTestBase.h"
20
21 using ::testing::_;
22
23 namespace blink {
24
25 class TestFrameClient : public FrameTestHelpers::TestWebFrameClient {
26 public:
27 MOCK_METHOD4(loadURLExternally,
28 void(const WebURLRequest&, WebNavigationPolicy, const WebString& downloa dName, bool shouldReplaceCurrentEntry));
29 };
30
31 class LinkSelectionTest : public SelectionTestBase {
32 protected:
33 void SetUp() override
34 {
35 const char* const kHTMLString =
36 "<a id='link' href='foo.com' style='font-size:20pt'>Text to select f oobar</a>"
37 "<div id='page_text'>Lorem ipsum dolor sit amet</div>";
38
39 // We need to set deviceSupportsMouse setting to true and page's focus c ontroller to active
40 // so that FrameView can set the mouse cursor.
41 m_webView = m_helper.initialize(false, &m_testFrameClient, nullptr,
42 [](WebSettings* settings) { settings->setDeviceSupportsMouse(true); });
43 m_mainFrame = m_webView->mainFrameImpl();
44 FrameTestHelpers::loadHTMLString(m_mainFrame, kHTMLString, URLTestHelper s::toKURL("http://foobar.com"));
45 m_webView->resize(WebSize(800, 600));
46 m_webView->page()->focusController().setActive(true);
47
48 auto* document = m_mainFrame->frame()->document();
49 ASSERT_NE(nullptr, document);
50 auto* linkToSelect = document->getElementById("link")->firstChild();
51 ASSERT_NE(nullptr, linkToSelect);
52 // We get larger range that we actually want to select, because we need a slightly larger
53 // rect to include the last character to the selection.
54 const auto rangeToSelect = Range::create(*document, linkToSelect, 5, lin kToSelect, 16);
55
56 const auto& selectionRect = rangeToSelect->boundingBox();
57 const auto& selectionRectCenterY = selectionRect.center().y();
58 m_leftPointInLink = selectionRect.minXMinYCorner();
59 m_leftPointInLink.setY(selectionRectCenterY);
60
61 m_rightPointInLink = selectionRect.maxXMinYCorner();
62 m_rightPointInLink.setY(selectionRectCenterY);
63 m_rightPointInLink.move(-2, 0);
64 }
65
66 TestFrameClient m_testFrameClient;
67 IntPoint m_leftPointInLink;
68 IntPoint m_rightPointInLink;
69 };
70
71 TEST_F(LinkSelectionTest, MouseDragWithoutAltAllowNoLinkSelection)
72 {
73 emulateMouseDrag(m_leftPointInLink, m_rightPointInLink, 0);
74 EXPECT_EQ(std::string(), getSelectionText());
75 }
76
77 TEST_F(LinkSelectionTest, MouseDragWithAltAllowSelection)
78 {
79 emulateMouseDrag(m_leftPointInLink, m_rightPointInLink, WebInputEvent::AltKe y);
80 EXPECT_EQ("to select", getSelectionText());
81 }
82
83 TEST_F(LinkSelectionTest, HandCursorDuringLinkDrag)
84 {
85 emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, 0, SendDownEvent);
86 m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate( );
87 testing::runDelayedTasks(50);
88 const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTe sting();
89 EXPECT_EQ(Cursor::Hand, cursor.getType());
90 }
91
92 TEST_F(LinkSelectionTest, CaretCursorOverLinkDuringSelection)
93 {
94 emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, WebInputEvent::AltKe y, SendDownEvent);
95 m_mainFrame->frame()->localFrameRoot()->eventHandler().scheduleCursorUpdate( );
96 testing::runDelayedTasks(50);
97 const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTe sting();
98 EXPECT_EQ(Cursor::IBeam, cursor.getType());
99 }
100
101 TEST_F(LinkSelectionTest, HandCursorOverLinkAfterContextMenu)
102 {
103 // Move mouse.
104 emulateMouseDrag(m_rightPointInLink, m_leftPointInLink, 0, 0);
105
106 // Show context menu. We don't send mouseup event here since in browser it d oesn't reach
107 // blink because of shown context menu.
108 emulateMouseDown(m_leftPointInLink, WebMouseEvent::ButtonRight, 0, 1);
109
110 LocalFrame* frame = m_mainFrame->frame();
111 // Hide context menu.
112 frame->page()->contextMenuController().clearContextMenu();
113
114 frame->localFrameRoot()->eventHandler().scheduleCursorUpdate();
115 testing::runDelayedTasks(50);
116 const auto& cursor = m_mainFrame->frame()->chromeClient().lastSetCursorForTe sting();
117 EXPECT_EQ(Cursor::Hand, cursor.getType());
118 }
119
120 TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownload)
121 {
122 EXPECT_CALL(m_testFrameClient, loadURLExternally(_, WebNavigationPolicy::Web NavigationPolicyDownload, WebString(), _));
123 emulateMouseClick(m_leftPointInLink, WebMouseEvent::ButtonLeft, WebInputEven t::AltKey);
124 }
125
126 TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownloadWhenTextSelected)
127 {
128 auto* document = m_mainFrame->frame()->document();
129 auto* textToSelect = document->getElementById("page_text")->firstChild();
130 ASSERT_NE(nullptr, textToSelect);
131
132 // Select some page text outside the link element.
133 const RefPtrWillBeRawPtr<Range> rangeToSelect = Range::create(*document, tex tToSelect, 1, textToSelect, 20);
134 const auto& selectionRect = rangeToSelect->boundingBox();
135 m_mainFrame->moveRangeSelection(selectionRect.minXMinYCorner(), selectionRec t.maxXMaxYCorner());
136 EXPECT_FALSE(getSelectionText().empty());
137
138 EXPECT_CALL(m_testFrameClient, loadURLExternally(_, WebNavigationPolicy::Web NavigationPolicyDownload, WebString(), _));
139 emulateMouseClick(m_leftPointInLink, WebMouseEvent::ButtonLeft, WebInputEven t::AltKey);
140 }
141
142 class LinkSelectionClickEventsTest : public SelectionTestBase {
143 protected:
144 class MockEventListener final : public EventListener {
145 public:
146 static PassRefPtrWillBeRawPtr<MockEventListener> create()
147 {
148 return adoptRefWillBeNoop(new MockEventListener());
149 }
150
151 bool operator==(const EventListener& other) const final
152 {
153 return this == &other;
154 }
155
156 MOCK_METHOD2(handleEvent, void(ExecutionContext* executionContext, Event *));
157
158 private:
159 MockEventListener() : EventListener(CPPEventListenerType)
160 {
161 }
162 };
163
164 void SetUp() override
165 {
166 const char* const kHTMLString =
167 "<div id='empty_div' style='width: 100px; height: 100px;'></div>"
168 "<span id='text_div'>Sometexttoshow</span>";
169
170 m_webView = m_helper.initialize(false);
171 m_mainFrame = m_webView->mainFrameImpl();
172 FrameTestHelpers::loadHTMLString(m_mainFrame, kHTMLString, URLTestHelper s::toKURL("http://foobar.com"));
173 m_webView->resize(WebSize(800, 600));
174 m_webView->page()->focusController().setActive(true);
175
176 auto* document = m_mainFrame->frame()->document();
177 ASSERT_NE(nullptr, document);
178
179 auto* emptyDiv = document->getElementById("empty_div");
180 auto* textDiv = document->getElementById("text_div");
181 ASSERT_NE(nullptr, emptyDiv);
182 ASSERT_NE(nullptr, textDiv);
183 }
184
185 void checkMouseClicks(Element& element, bool doubleClickEvent)
186 {
187 struct ScopedListenersCleaner {
188 ScopedListenersCleaner(Element* element) : m_element(element) {}
189
190 ~ScopedListenersCleaner()
191 {
192 m_element->removeAllEventListeners();
193 }
194
195 RawPtrWillBePersistent<Element> m_element;
196 } const listenersCleaner(&element);
197
198 RefPtrWillBeRawPtr<MockEventListener> eventHandler = MockEventListener:: create();
199 element.addEventListener(
200 doubleClickEvent ? EventTypeNames::dblclick : EventTypeNames::click,
201 eventHandler);
202
203 ::testing::InSequence s;
204 EXPECT_CALL(*eventHandler, handleEvent(_, _)).Times(1);
205
206 const auto& elemBounds = element.boundsInViewport();
207 const int clickCount = doubleClickEvent ? 2 : 1;
208 emulateMouseClick(elemBounds.center(), WebMouseEvent::ButtonLeft, 0, cli ckCount);
209
210 if (doubleClickEvent) {
211 EXPECT_EQ(element.innerText().isEmpty(), getSelectionText().empty()) ;
212 }
213 }
214 };
215
216 TEST_F(LinkSelectionClickEventsTest, SingleAndDoubleClickWillBeHandled)
217 {
218 auto* document = m_mainFrame->frame()->document();
219 auto* element = document->getElementById("empty_div");
220
221 {
222 SCOPED_TRACE("Empty div, single click");
223 checkMouseClicks(*element, false);
224 }
225
226 {
227 SCOPED_TRACE("Empty div, double click");
228 checkMouseClicks(*element, true);
229 }
230
231 element = document->getElementById("text_div");
232
233 {
234 SCOPED_TRACE("Text div, single click");
235 checkMouseClicks(*element, false);
236 }
237
238 {
239 SCOPED_TRACE("Text div, double click");
240 checkMouseClicks(*element, true);
241 }
242 }
243
244 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698