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