1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "config.h" 26 27 #include "web/LinkHighlight.h" 28 29 #include "bindings/v8/ExceptionStatePlaceholder.h" 30 #include "core/dom/Node.h" 31 #include "core/frame/FrameView.h" 32 #include "core/page/TouchDisambiguation.h" 33 #include "platform/geometry/IntRect.h" 34 #include "public/platform/Platform.h" 35 #include "public/platform/WebContentLayer.h" 36 #include "public/platform/WebFloatPoint.h" 37 #include "public/platform/WebSize.h" 38 #include "public/platform/WebUnitTestSupport.h" 39 #include "public/web/WebFrame.h" 40 #include "public/web/WebFrameClient.h" 41 #include "public/web/WebInputEvent.h" 42 #include "public/web/WebViewClient.h" 43 #include "web/WebInputEventConversion.h" 44 #include "web/WebLocalFrameImpl.h" 45 #include "web/WebViewImpl.h" 46 #include "web/tests/FrameTestHelpers.h" 47 #include "web/tests/URLTestHelpers.h" 48 #include "wtf/PassOwnPtr.h" 49 #include <gtest/gtest.h> 50 51 52 using namespace blink; 53 using namespace WebCore; 54 55 namespace { 56 57 TEST(LinkHighlightTest, verifyWebViewImplIntegration) 58 { 59 const std::string baseURL("http://www.test.com/"); 60 const std::string fileName("test_touch_link_highlight.html"); 61 62 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8("test_touch_link_highlight.html")); 63 FrameTestHelpers::WebViewHelper webViewHelper; 64 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(baseURL + fileName, true); 65 int pageWidth = 640; 66 int pageHeight = 480; 67 webViewImpl->resize(WebSize(pageWidth, pageHeight)); 68 webViewImpl->layout(); 69 70 WebGestureEvent touchEvent; 71 touchEvent.type = WebInputEvent::GestureShowPress; 72 73 // The coordinates below are linked to absolute positions in the referenced .html file. 74 touchEvent.x = 20; 75 touchEvent.y = 20; 76 77 { 78 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 79 Node* touchNode = webViewImpl->bestTapNode(platformEvent); 80 ASSERT_TRUE(touchNode); 81 } 82 83 touchEvent.y = 40; 84 { 85 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 86 EXPECT_FALSE(webViewImpl->bestTapNode(platformEvent)); 87 } 88 89 touchEvent.y = 20; 90 // Shouldn't crash. 91 92 { 93 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 94 webViewImpl->enableTapHighlightAtPoint(platformEvent); 95 } 96 97 EXPECT_TRUE(webViewImpl->linkHighlight(0)); 98 EXPECT_TRUE(webViewImpl->linkHighlight(0)->contentLayer()); 99 EXPECT_TRUE(webViewImpl->linkHighlight(0)->clipLayer()); 100 101 // Find a target inside a scrollable div 102 103 touchEvent.y = 100; 104 { 105 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 106 webViewImpl->enableTapHighlightAtPoint(platformEvent); 107 } 108 109 ASSERT_TRUE(webViewImpl->linkHighlight(0)); 110 111 // Don't highlight if no "hand cursor" 112 touchEvent.y = 220; // An A-link with cross-hair cursor. 113 { 114 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 115 webViewImpl->enableTapHighlightAtPoint(platformEvent); 116 } 117 ASSERT_EQ(0U, webViewImpl->numLinkHighlights()); 118 119 touchEvent.y = 260; // A text input box. 120 { 121 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 122 webViewImpl->enableTapHighlightAtPoint(platformEvent); 123 } 124 ASSERT_EQ(0U, webViewImpl->numLinkHighlights()); 125 126 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 127 } 128 129 class FakeWebFrameClient : public WebFrameClient { 130 // To make the destructor public. 131 }; 132 133 class FakeCompositingWebViewClient : public FrameTestHelpers::TestWebViewClient { 134 public: 135 FakeWebFrameClient m_fakeWebFrameClient; 136 }; 137 138 static WebViewClient* compositingWebViewClient() 139 { 140 DEFINE_STATIC_LOCAL(FakeCompositingWebViewClient, client, ()); 141 return &client; 142 } 143 144 TEST(LinkHighlightTest, resetDuringNodeRemoval) 145 { 146 const std::string baseURL("http://www.test.com/"); 147 const std::string fileName("test_touch_link_highlight.html"); 148 149 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8("test_touch_link_highlight.html")); 150 FrameTestHelpers::WebViewHelper webViewHelper; 151 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(baseURL + fileName, true, 0, compositingWebViewClient()); 152 153 int pageWidth = 640; 154 int pageHeight = 480; 155 webViewImpl->resize(WebSize(pageWidth, pageHeight)); 156 webViewImpl->layout(); 157 158 WebGestureEvent touchEvent; 159 touchEvent.type = WebInputEvent::GestureShowPress; 160 touchEvent.x = 20; 161 touchEvent.y = 20; 162 163 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 164 Node* touchNode = webViewImpl->bestTapNode(platformEvent); 165 ASSERT_TRUE(touchNode); 166 167 webViewImpl->enableTapHighlightAtPoint(platformEvent); 168 ASSERT_TRUE(webViewImpl->linkHighlight(0)); 169 170 GraphicsLayer* highlightLayer = webViewImpl->linkHighlight(0)->currentGraphicsLayerForTesting(); 171 ASSERT_TRUE(highlightLayer); 172 EXPECT_TRUE(highlightLayer->linkHighlight(0)); 173 174 touchNode->remove(IGNORE_EXCEPTION); 175 webViewImpl->layout(); 176 ASSERT_EQ(0U, highlightLayer->numLinkHighlights()); 177 178 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 179 } 180 181 TEST(LinkHighlightTest, multipleHighlights) 182 { 183 const std::string baseURL("http://www.test.com/"); 184 const std::string fileName("test_touch_link_highlight.html"); 185 186 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8("test_touch_link_highlight.html")); 187 FrameTestHelpers::WebViewHelper webViewHelper; 188 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(baseURL + fileName, true, 0, compositingWebViewClient()); 189 190 int pageWidth = 640; 191 int pageHeight = 480; 192 webViewImpl->resize(WebSize(pageWidth, pageHeight)); 193 webViewImpl->layout(); 194 195 WebGestureEvent touchEvent; 196 touchEvent.x = 50; 197 touchEvent.y = 310; 198 touchEvent.data.tap.width = 30; 199 touchEvent.data.tap.height = 30; 200 201 Vector<IntRect> goodTargets; 202 WillBeHeapVector<RawPtrWillBeMember<Node> > highlightNodes; 203 IntRect boundingBox(touchEvent.x - touchEvent.data.tap.width / 2, touchEvent.y - touchEvent.data.tap.height / 2, touchEvent.data.tap.width, touchEvent.data.tap.height); 204 findGoodTouchTargets(boundingBox, webViewImpl->mainFrameImpl()->frame(), goodTargets, highlightNodes); 205 206 webViewImpl->enableTapHighlights(highlightNodes); 207 EXPECT_EQ(2U, webViewImpl->numLinkHighlights()); 208 209 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 210 } 211 212 } // namespace 213