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 "LinkHighlight.h" 28 29 #include <gtest/gtest.h> 30 #include "FrameTestHelpers.h" 31 #include "URLTestHelpers.h" 32 #include "WebFrame.h" 33 #include "WebFrameClient.h" 34 #include "WebFrameImpl.h" 35 #include "WebInputEvent.h" 36 #include "WebInputEventConversion.h" 37 #include "WebViewClient.h" 38 #include "WebViewImpl.h" 39 #include "bindings/v8/ExceptionStatePlaceholder.h" 40 #include "core/dom/Node.h" 41 #include "core/frame/FrameView.h" 42 #include "core/page/TouchDisambiguation.h" 43 #include "platform/geometry/IntRect.h" 44 #include "public/platform/Platform.h" 45 #include "public/platform/WebContentLayer.h" 46 #include "public/platform/WebFloatPoint.h" 47 #include "public/platform/WebSize.h" 48 #include "public/platform/WebUnitTestSupport.h" 49 #include "wtf/PassOwnPtr.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 WebViewClient { 134 public: 135 virtual ~FakeCompositingWebViewClient() 136 { 137 } 138 139 virtual void initializeLayerTreeView() OVERRIDE 140 { 141 m_layerTreeView = adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting(WebUnitTestSupport::TestViewTypeUnitTest)); 142 ASSERT(m_layerTreeView); 143 } 144 145 virtual WebLayerTreeView* layerTreeView() OVERRIDE 146 { 147 return m_layerTreeView.get(); 148 } 149 150 FakeWebFrameClient m_fakeWebFrameClient; 151 152 private: 153 OwnPtr<WebLayerTreeView> m_layerTreeView; 154 }; 155 156 static WebViewClient* compositingWebViewClient() 157 { 158 DEFINE_STATIC_LOCAL(FakeCompositingWebViewClient, client, ()); 159 return &client; 160 } 161 162 TEST(LinkHighlightTest, resetDuringNodeRemoval) 163 { 164 const std::string baseURL("http://www.test.com/"); 165 const std::string fileName("test_touch_link_highlight.html"); 166 167 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8("test_touch_link_highlight.html")); 168 FrameTestHelpers::WebViewHelper webViewHelper; 169 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(baseURL + fileName, true, 0, compositingWebViewClient()); 170 171 int pageWidth = 640; 172 int pageHeight = 480; 173 webViewImpl->resize(WebSize(pageWidth, pageHeight)); 174 webViewImpl->layout(); 175 176 WebGestureEvent touchEvent; 177 touchEvent.type = WebInputEvent::GestureShowPress; 178 touchEvent.x = 20; 179 touchEvent.y = 20; 180 181 PlatformGestureEventBuilder platformEvent(webViewImpl->mainFrameImpl()->frameView(), touchEvent); 182 Node* touchNode = webViewImpl->bestTapNode(platformEvent); 183 ASSERT_TRUE(touchNode); 184 185 webViewImpl->enableTapHighlightAtPoint(platformEvent); 186 ASSERT_TRUE(webViewImpl->linkHighlight(0)); 187 188 GraphicsLayer* highlightLayer = webViewImpl->linkHighlight(0)->currentGraphicsLayerForTesting(); 189 ASSERT_TRUE(highlightLayer); 190 EXPECT_TRUE(highlightLayer->linkHighlight(0)); 191 192 touchNode->remove(IGNORE_EXCEPTION); 193 webViewImpl->layout(); 194 ASSERT_EQ(0U, highlightLayer->numLinkHighlights()); 195 196 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 197 } 198 199 TEST(LinkHighlightTest, multipleHighlights) 200 { 201 const std::string baseURL("http://www.test.com/"); 202 const std::string fileName("test_touch_link_highlight.html"); 203 204 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8("test_touch_link_highlight.html")); 205 FrameTestHelpers::WebViewHelper webViewHelper; 206 WebViewImpl* webViewImpl = webViewHelper.initializeAndLoad(baseURL + fileName, true, 0, compositingWebViewClient()); 207 208 int pageWidth = 640; 209 int pageHeight = 480; 210 webViewImpl->resize(WebSize(pageWidth, pageHeight)); 211 webViewImpl->layout(); 212 213 WebGestureEvent touchEvent; 214 touchEvent.x = 50; 215 touchEvent.y = 310; 216 touchEvent.data.tap.width = 30; 217 touchEvent.data.tap.height = 30; 218 219 Vector<IntRect> goodTargets; 220 Vector<Node*> highlightNodes; 221 IntRect boundingBox(touchEvent.x - touchEvent.data.tap.width / 2, touchEvent.y - touchEvent.data.tap.height / 2, touchEvent.data.tap.width, touchEvent.data.tap.height); 222 findGoodTouchTargets(boundingBox, webViewImpl->mainFrameImpl()->frame(), goodTargets, highlightNodes); 223 224 webViewImpl->enableTapHighlights(highlightNodes); 225 EXPECT_EQ(2U, webViewImpl->numLinkHighlights()); 226 227 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 228 } 229 230 } // namespace 231