OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (C) 2013 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 are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 | |
33 #include "FrameTestHelpers.h" | |
34 #include "RuntimeEnabledFeatures.h" | |
35 #include "URLTestHelpers.h" | |
36 #include "WebDocument.h" | |
37 #include "WebFrame.h" | |
38 #include "WebInputEvent.h" | |
39 #include "WebView.h" | |
40 #include "WebViewClient.h" | |
41 #include "WebViewImpl.h" | |
42 #include "core/dom/ClientRect.h" | |
43 #include "core/dom/ClientRectList.h" | |
44 #include "core/dom/Document.h" | |
45 #include "core/dom/Element.h" | |
46 #include "core/frame/Frame.h" | |
47 #include "core/frame/FrameView.h" | |
48 #include "core/rendering/HitTestResult.h" | |
49 #include "core/rendering/RenderTreeAsText.h" | |
50 #include "public/platform/Platform.h" | |
51 #include "public/platform/WebUnitTestSupport.h" | |
52 #include "public/web/WebHitTestResult.h" | |
53 #include "public/web/WebTouchAction.h" | |
54 #include "public/web/WebWidgetClient.h" | |
55 | |
56 #include <gtest/gtest.h> | |
57 | |
58 using namespace blink; | |
59 using blink::FrameTestHelpers::runPendingTasks; | |
60 | |
61 namespace { | |
62 | |
63 class TouchActionTrackingWebViewClient : public WebViewClient { | |
64 public: | |
65 TouchActionTrackingWebViewClient() : | |
66 m_actionSetCount(0), | |
67 m_action(WebTouchActionAuto) | |
68 { | |
69 } | |
70 | |
71 // WebWidgetClient methods | |
72 virtual void setTouchAction(WebTouchAction touchAction) | |
73 { | |
74 m_actionSetCount++; | |
75 m_action = touchAction; | |
76 } | |
77 | |
78 // Local methods | |
79 void reset() | |
80 { | |
81 m_actionSetCount = 0; | |
82 m_action = WebTouchActionAuto; | |
83 } | |
84 | |
85 int touchActionSetCount() | |
86 { | |
87 return m_actionSetCount; | |
88 } | |
89 | |
90 WebTouchAction lastTouchAction() | |
91 { | |
92 return m_action; | |
93 } | |
94 | |
95 private: | |
96 int m_actionSetCount; | |
97 WebTouchAction m_action; | |
98 }; | |
99 | |
100 const int kfakeTouchId = 7; | |
101 | |
102 class TouchActionTest : public testing::Test { | |
103 public: | |
104 TouchActionTest() | |
105 : m_baseURL("http://www.test.com/") | |
106 { | |
107 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseU RL), "touch-action-tests.css"); | |
108 WebCore::RuntimeEnabledFeatures::setCSSTouchActionEnabled(true); | |
109 } | |
110 | |
111 virtual void TearDown() | |
112 { | |
113 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); | |
114 } | |
115 | |
116 protected: | |
117 void runTouchActionTest(std::string file) | |
esprehn
2013/11/21 16:26:29
It would be nicer to put this method outside the c
Rick Byers
2013/11/21 22:09:29
Done.
| |
118 { | |
119 TouchActionTrackingWebViewClient client; | |
120 URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseU RL), WebString::fromUTF8(file)); | |
121 WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + file, f alse, 0, &client); | |
122 | |
123 // Set size to enable hit testing, and avoid line wrapping for consisten cy with browser. | |
124 webView->resize(WebSize(700, 1000)); | |
125 | |
126 // Get the document and bypass the no-touch-handler optimization. | |
127 RefPtr<WebCore::Document> document = static_cast<PassRefPtr<WebCore::Doc ument> >(webView->mainFrame()->document()); | |
128 document->didAddTouchEventHandler(document.get()); | |
129 | |
130 // Scroll to verify the code properly transforms windows to client co-or ds. | |
131 const int kScrollOffset = 100; | |
132 document->frame()->view()->setScrollOffset(WebCore::IntPoint(0, kScrollO ffset)); | |
133 | |
134 // Find all elements to test the touch-action of in the document. | |
135 WebCore::TrackExceptionState es; | |
136 RefPtr<WebCore::NodeList> nodes = document->querySelectorAll("[expected- action]", es); | |
137 ASSERT_FALSE(es.hadException()); | |
138 ASSERT_GE(nodes->length(), 1u); | |
139 | |
140 for (unsigned index = 0; index < nodes->length(); index++) { | |
141 WebCore::Element* element = toElement(nodes->item(index)); | |
142 element->scrollIntoViewIfNeeded(); | |
143 ASSERT_TRUE(nodes->item(index)->isElementNode()); | |
144 | |
145 std::string failureContext("Test case: "); | |
146 if (element->hasID()) { | |
147 failureContext.append(element->getIdAttribute().string().ascii() .data()); | |
148 } else if (element->firstChild()) { | |
149 failureContext.append("\""); | |
150 failureContext.append(element->firstChild()->textContent(false). stripWhiteSpace().ascii().data()); | |
151 failureContext.append("\""); | |
152 } else { | |
153 failureContext += "<missing ID>"; | |
154 } | |
155 | |
156 // Run each test three times at different positions in the element. | |
157 // Note that we don't want the bounding box because our tests someti mes have elements with | |
158 // multiple border boxes with other elements in between. Use the fir st border box (which | |
159 // we can easily visualize in a browser for debugging). | |
160 RefPtr<WebCore::ClientRectList> rects = element->getClientRects(); | |
161 ASSERT_GE(rects->length(), 0u) << failureContext; | |
162 RefPtr<WebCore::ClientRect> r = rects->item(0); | |
163 WebCore::FloatRect clientFloatRect = WebCore::FloatRect(r->left(), r ->top(), r->width(), r->height()); | |
164 WebCore::IntRect clientRect = enclosedIntRect(clientFloatRect); | |
165 for (int locIdx = 0; locIdx < 3; locIdx++) { | |
166 WebCore::IntPoint clientPoint; | |
167 std::stringstream contextStream; | |
168 contextStream << failureContext << " ("; | |
169 switch (locIdx) { | |
170 case 0: | |
171 clientPoint = clientRect.center(); | |
172 contextStream << "center"; | |
173 break; | |
174 case 1: | |
175 clientPoint = clientRect.location(); | |
176 contextStream << "top-left"; | |
177 break; | |
178 case 2: | |
179 clientPoint = clientRect.maxXMaxYCorner(); | |
180 clientPoint.move(-1, -1); | |
181 contextStream << "bottom-right"; | |
182 break; | |
183 default: | |
184 FAIL() << "Invalid location index."; | |
185 } | |
186 contextStream << "=" << clientPoint.x() << "," << clientPoint.y( ) << ")."; | |
187 std::string failureContextPos = contextStream.str(); | |
188 | |
189 WebCore::IntRect visibleRect = document->frame()->view()->window ClipRect(); | |
190 ASSERT_TRUE(visibleRect.contains(clientPoint)) << failureContext Pos | |
191 << " Test point not contained in visible area: " << visibleR ect.x() << "," << visibleRect.y() | |
192 << "-" << visibleRect.maxX() << "," << visibleRect.maxY(); | |
193 | |
194 // First validate that a hit test at this point will really hit the element | |
195 // we intended. This is the easiest way for a test to be broken, but has nothing really | |
196 // to do with touch action. | |
197 WebCore::HitTestResult result = static_cast<WebCore::HitTestResu lt>(webView->hitTestResultAt(clientPoint)); | |
198 ASSERT_EQ(element, result.innerElement()) << "Unexpected hit tes t result " << failureContextPos | |
199 << " Got element: \"" << result.innerElement()->outerHTML() .stripWhiteSpace().left(80).ascii().data() << "\"" | |
200 << std::endl << "Document render tree:" << std::endl << exte rnalRepresentation(document->frame()).utf8().data(); | |
201 | |
202 // Now send the touch event and check any touch action result. | |
203 sendTouchEvent(webView, WebInputEvent::TouchStart, clientPoint); | |
204 | |
205 AtomicString expectedAction = element->getAttribute("expected-ac tion"); | |
206 if (expectedAction == "auto") { | |
207 // Auto is the default - no action set. | |
208 EXPECT_EQ(0, client.touchActionSetCount()) << failureContext Pos; | |
209 EXPECT_EQ(WebTouchActionAuto, client.lastTouchAction()) << f ailureContextPos; | |
210 } else { | |
211 // Should have received exactly one touch action. | |
212 EXPECT_EQ(1, client.touchActionSetCount()) << failureContext Pos; | |
213 if (client.touchActionSetCount()) { | |
214 if (expectedAction == "none") { | |
215 EXPECT_EQ(WebTouchActionNone, client.lastTouchAction ()) << failureContextPos; | |
216 } else { | |
217 FAIL() << "Unrecognized expected-action \"" << expec tedAction.string().ascii().data() | |
218 << "\" " << failureContextPos; | |
219 } | |
220 } | |
221 } | |
222 | |
223 // Reset webview touch state. | |
224 client.reset(); | |
225 sendTouchEvent(webView, WebInputEvent::TouchCancel, clientPoint) ; | |
226 EXPECT_EQ(0, client.touchActionSetCount()); | |
227 } | |
228 } | |
229 } | |
230 | |
231 void sendTouchEvent(WebView* webView, WebInputEvent::Type type, WebCore::Int Point clientPoint) | |
esprehn
2013/11/21 16:26:29
Same.
Rick Byers
2013/11/21 22:09:29
Done.
| |
232 { | |
233 ASSERT_TRUE(type == WebInputEvent::TouchStart || type == WebInputEvent:: TouchCancel); | |
234 | |
235 WebTouchEvent webTouchEvent; | |
236 webTouchEvent.type = type; | |
237 webTouchEvent.touchesLength = 1; | |
238 webTouchEvent.touches[0].state = (type == WebInputEvent::TouchStart ? | |
239 WebTouchPoint::StatePressed : | |
240 WebTouchPoint::StateCancelled); | |
241 webTouchEvent.touches[0].id = kfakeTouchId; | |
242 webTouchEvent.touches[0].screenPosition.x = clientPoint.x(); | |
243 webTouchEvent.touches[0].screenPosition.y = clientPoint.y(); | |
244 webTouchEvent.touches[0].position.x = clientPoint.x(); | |
245 webTouchEvent.touches[0].position.y = clientPoint.y(); | |
246 webTouchEvent.touches[0].radiusX = 10; | |
247 webTouchEvent.touches[0].radiusY = 10; | |
248 | |
249 webView->handleInputEvent(webTouchEvent); | |
250 runPendingTasks(); | |
251 } | |
252 | |
253 std::string m_baseURL; | |
254 FrameTestHelpers::WebViewHelper m_webViewHelper; | |
255 }; | |
256 | |
257 TEST_F(TouchActionTest, Simple) | |
258 { | |
259 runTouchActionTest("touch-action-simple.html"); | |
260 } | |
261 | |
262 TEST_F(TouchActionTest, Overflow) | |
263 { | |
264 runTouchActionTest("touch-action-overflow.html"); | |
265 } | |
266 | |
267 } | |
OLD | NEW |