Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / ScrollingCoordinatorChromiumTest.cpp
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 "core/page/scrolling/ScrollingCoordinator.h"
28
29 #include "core/rendering/RenderView.h"
30 #include "core/rendering/compositing/CompositedLayerMapping.h"
31 #include "core/rendering/compositing/RenderLayerCompositor.h"
32 #include "platform/graphics/GraphicsLayer.h"
33 #include "public/platform/Platform.h"
34 #include "public/platform/WebLayer.h"
35 #include "public/platform/WebLayerPositionConstraint.h"
36 #include "public/platform/WebLayerTreeView.h"
37 #include "public/platform/WebUnitTestSupport.h"
38 #include "public/web/WebSettings.h"
39 #include "public/web/WebViewClient.h"
40 #include "web/WebLocalFrameImpl.h"
41 #include "web/WebViewImpl.h"
42 #include "web/tests/FrameTestHelpers.h"
43 #include "web/tests/URLTestHelpers.h"
44 #include <gtest/gtest.h>
45
46 using namespace WebCore;
47 using namespace blink;
48
49 namespace {
50
51 class ScrollingCoordinatorChromiumTest : public testing::Test {
52 public:
53     ScrollingCoordinatorChromiumTest()
54         : m_baseURL("http://www.test.com/")
55     {
56         m_helper.initialize(true, 0, &m_mockWebViewClient, &configureSettings);
57         webViewImpl()->resize(IntSize(320, 240));
58     }
59
60     virtual ~ScrollingCoordinatorChromiumTest()
61     {
62         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
63     }
64
65     void navigateTo(const std::string& url)
66     {
67         FrameTestHelpers::loadFrame(webViewImpl()->mainFrame(), url);
68     }
69
70     void forceFullCompositingUpdate()
71     {
72         webViewImpl()->layout();
73     }
74
75     void registerMockedHttpURLLoad(const std::string& fileName)
76     {
77         URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
78     }
79
80     WebLayer* getRootScrollLayer()
81     {
82         RenderLayerCompositor* compositor = frame()->contentRenderer()->compositor();
83         ASSERT(compositor);
84         ASSERT(compositor->scrollLayer());
85
86         WebLayer* webScrollLayer = compositor->scrollLayer()->platformLayer();
87         return webScrollLayer;
88     }
89
90     WebViewImpl* webViewImpl() const { return m_helper.webViewImpl(); }
91     LocalFrame* frame() const { return m_helper.webViewImpl()->mainFrameImpl()->frame(); }
92
93 protected:
94     std::string m_baseURL;
95     FrameTestHelpers::TestWebViewClient m_mockWebViewClient;
96
97 private:
98     static void configureSettings(WebSettings* settings)
99     {
100         settings->setJavaScriptEnabled(true);
101         settings->setAcceleratedCompositingEnabled(true);
102         settings->setAcceleratedCompositingForFixedPositionEnabled(true);
103         settings->setAcceleratedCompositingForOverflowScrollEnabled(true);
104         settings->setCompositedScrollingForFramesEnabled(true);
105     }
106
107     FrameTestHelpers::WebViewHelper m_helper;
108 };
109
110 TEST_F(ScrollingCoordinatorChromiumTest, fastScrollingByDefault)
111 {
112     navigateTo("about:blank");
113     forceFullCompositingUpdate();
114
115     // Make sure the scrolling coordinator is active.
116     FrameView* frameView = frame()->view();
117     Page* page = frame()->page();
118     ASSERT_TRUE(page->scrollingCoordinator());
119     ASSERT_TRUE(page->scrollingCoordinator()->coordinatesScrollingForFrameView(frameView));
120
121     // Fast scrolling should be enabled by default.
122     WebLayer* rootScrollLayer = getRootScrollLayer();
123     ASSERT_TRUE(rootScrollLayer->scrollable());
124     ASSERT_FALSE(rootScrollLayer->shouldScrollOnMainThread());
125     ASSERT_FALSE(rootScrollLayer->haveWheelEventHandlers());
126 }
127
128 static WebLayer* webLayerFromElement(Element* element)
129 {
130     if (!element)
131         return 0;
132     RenderObject* renderer = element->renderer();
133     if (!renderer || !renderer->isBoxModelObject())
134         return 0;
135     RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
136     if (!layer)
137         return 0;
138     if (!layer->hasCompositedLayerMapping())
139         return 0;
140     CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping();
141     GraphicsLayer* graphicsLayer = compositedLayerMapping->mainGraphicsLayer();
142     if (!graphicsLayer)
143         return 0;
144     return graphicsLayer->platformLayer();
145 }
146
147 TEST_F(ScrollingCoordinatorChromiumTest, fastScrollingForFixedPosition)
148 {
149     registerMockedHttpURLLoad("fixed-position.html");
150     navigateTo(m_baseURL + "fixed-position.html");
151     forceFullCompositingUpdate();
152
153     // Fixed position should not fall back to main thread scrolling.
154     WebLayer* rootScrollLayer = getRootScrollLayer();
155     ASSERT_FALSE(rootScrollLayer->shouldScrollOnMainThread());
156
157     Document* document = frame()->document();
158     {
159         Element* element = document->getElementById("div-tl");
160         ASSERT_TRUE(element);
161         WebLayer* layer = webLayerFromElement(element);
162         ASSERT_TRUE(layer);
163         WebLayerPositionConstraint constraint = layer->positionConstraint();
164         ASSERT_TRUE(constraint.isFixedPosition);
165         ASSERT_TRUE(!constraint.isFixedToRightEdge && !constraint.isFixedToBottomEdge);
166     }
167     {
168         Element* element = document->getElementById("div-tr");
169         ASSERT_TRUE(element);
170         WebLayer* layer = webLayerFromElement(element);
171         ASSERT_TRUE(layer);
172         WebLayerPositionConstraint constraint = layer->positionConstraint();
173         ASSERT_TRUE(constraint.isFixedPosition);
174         ASSERT_TRUE(constraint.isFixedToRightEdge && !constraint.isFixedToBottomEdge);
175     }
176     {
177         Element* element = document->getElementById("div-bl");
178         ASSERT_TRUE(element);
179         WebLayer* layer = webLayerFromElement(element);
180         ASSERT_TRUE(layer);
181         WebLayerPositionConstraint constraint = layer->positionConstraint();
182         ASSERT_TRUE(constraint.isFixedPosition);
183         ASSERT_TRUE(!constraint.isFixedToRightEdge && constraint.isFixedToBottomEdge);
184     }
185     {
186         Element* element = document->getElementById("div-br");
187         ASSERT_TRUE(element);
188         WebLayer* layer = webLayerFromElement(element);
189         ASSERT_TRUE(layer);
190         WebLayerPositionConstraint constraint = layer->positionConstraint();
191         ASSERT_TRUE(constraint.isFixedPosition);
192         ASSERT_TRUE(constraint.isFixedToRightEdge && constraint.isFixedToBottomEdge);
193     }
194     {
195         Element* element = document->getElementById("span-tl");
196         ASSERT_TRUE(element);
197         WebLayer* layer = webLayerFromElement(element);
198         ASSERT_TRUE(layer);
199         WebLayerPositionConstraint constraint = layer->positionConstraint();
200         ASSERT_TRUE(constraint.isFixedPosition);
201         ASSERT_TRUE(!constraint.isFixedToRightEdge && !constraint.isFixedToBottomEdge);
202     }
203     {
204         Element* element = document->getElementById("span-tr");
205         ASSERT_TRUE(element);
206         WebLayer* layer = webLayerFromElement(element);
207         ASSERT_TRUE(layer);
208         WebLayerPositionConstraint constraint = layer->positionConstraint();
209         ASSERT_TRUE(constraint.isFixedPosition);
210         ASSERT_TRUE(constraint.isFixedToRightEdge && !constraint.isFixedToBottomEdge);
211     }
212     {
213         Element* element = document->getElementById("span-bl");
214         ASSERT_TRUE(element);
215         WebLayer* layer = webLayerFromElement(element);
216         ASSERT_TRUE(layer);
217         WebLayerPositionConstraint constraint = layer->positionConstraint();
218         ASSERT_TRUE(constraint.isFixedPosition);
219         ASSERT_TRUE(!constraint.isFixedToRightEdge && constraint.isFixedToBottomEdge);
220     }
221     {
222         Element* element = document->getElementById("span-br");
223         ASSERT_TRUE(element);
224         WebLayer* layer = webLayerFromElement(element);
225         ASSERT_TRUE(layer);
226         WebLayerPositionConstraint constraint = layer->positionConstraint();
227         ASSERT_TRUE(constraint.isFixedPosition);
228         ASSERT_TRUE(constraint.isFixedToRightEdge && constraint.isFixedToBottomEdge);
229     }
230 }
231
232 TEST_F(ScrollingCoordinatorChromiumTest, wheelEventHandler)
233 {
234     registerMockedHttpURLLoad("wheel-event-handler.html");
235     navigateTo(m_baseURL + "wheel-event-handler.html");
236     forceFullCompositingUpdate();
237
238     WebLayer* rootScrollLayer = getRootScrollLayer();
239     ASSERT_TRUE(rootScrollLayer->haveWheelEventHandlers());
240 }
241
242 TEST_F(ScrollingCoordinatorChromiumTest, scrollEventHandler)
243 {
244     registerMockedHttpURLLoad("scroll-event-handler.html");
245     navigateTo(m_baseURL + "scroll-event-handler.html");
246     forceFullCompositingUpdate();
247
248     WebLayer* rootScrollLayer = getRootScrollLayer();
249     ASSERT_TRUE(rootScrollLayer->haveScrollEventHandlers());
250 }
251
252 TEST_F(ScrollingCoordinatorChromiumTest, updateEventHandlersDuringTeardown)
253 {
254     registerMockedHttpURLLoad("scroll-event-handler-window.html");
255     navigateTo(m_baseURL + "scroll-event-handler-window.html");
256     forceFullCompositingUpdate();
257
258     // Simulate detaching the document from its DOM window. This should not
259     // cause a crash when the WebViewImpl is closed by the test runner.
260     frame()->document()->prepareForDestruction();
261 }
262
263 TEST_F(ScrollingCoordinatorChromiumTest, clippedBodyTest)
264 {
265     registerMockedHttpURLLoad("clipped-body.html");
266     navigateTo(m_baseURL + "clipped-body.html");
267     forceFullCompositingUpdate();
268
269     WebLayer* rootScrollLayer = getRootScrollLayer();
270     ASSERT_EQ(0u, rootScrollLayer->nonFastScrollableRegion().size());
271 }
272
273 TEST_F(ScrollingCoordinatorChromiumTest, overflowScrolling)
274 {
275     registerMockedHttpURLLoad("overflow-scrolling.html");
276     navigateTo(m_baseURL + "overflow-scrolling.html");
277     forceFullCompositingUpdate();
278
279     // Verify the properties of the accelerated scrolling element starting from the RenderObject
280     // all the way to the WebLayer.
281     Element* scrollableElement = frame()->document()->getElementById("scrollable");
282     ASSERT(scrollableElement);
283
284     RenderObject* renderer = scrollableElement->renderer();
285     ASSERT_TRUE(renderer->isBox());
286     ASSERT_TRUE(renderer->hasLayer());
287
288     RenderBox* box = toRenderBox(renderer);
289     ASSERT_TRUE(box->usesCompositedScrolling());
290     ASSERT_EQ(PaintsIntoOwnBacking, box->layer()->compositingState());
291
292     CompositedLayerMappingPtr compositedLayerMapping = box->layer()->compositedLayerMapping();
293     ASSERT_TRUE(compositedLayerMapping->hasScrollingLayer());
294     ASSERT(compositedLayerMapping->scrollingContentsLayer());
295
296     GraphicsLayer* graphicsLayer = compositedLayerMapping->scrollingContentsLayer();
297     ASSERT_EQ(box->layer()->scrollableArea(), graphicsLayer->scrollableArea());
298
299     WebLayer* webScrollLayer = compositedLayerMapping->scrollingContentsLayer()->platformLayer();
300     ASSERT_TRUE(webScrollLayer->scrollable());
301     ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
302     ASSERT_TRUE(webScrollLayer->userScrollableVertical());
303
304 #if OS(ANDROID)
305     // Now verify we've attached impl-side scrollbars onto the scrollbar layers
306     ASSERT_TRUE(compositedLayerMapping->layerForHorizontalScrollbar());
307     ASSERT_TRUE(compositedLayerMapping->layerForHorizontalScrollbar()->hasContentsLayer());
308     ASSERT_TRUE(compositedLayerMapping->layerForVerticalScrollbar());
309     ASSERT_TRUE(compositedLayerMapping->layerForVerticalScrollbar()->hasContentsLayer());
310 #endif
311 }
312
313 TEST_F(ScrollingCoordinatorChromiumTest, overflowHidden)
314 {
315     registerMockedHttpURLLoad("overflow-hidden.html");
316     navigateTo(m_baseURL + "overflow-hidden.html");
317     forceFullCompositingUpdate();
318
319     // Verify the properties of the accelerated scrolling element starting from the RenderObject
320     // all the way to the WebLayer.
321     Element* overflowElement = frame()->document()->getElementById("unscrollable-y");
322     ASSERT(overflowElement);
323
324     RenderObject* renderer = overflowElement->renderer();
325     ASSERT_TRUE(renderer->isBox());
326     ASSERT_TRUE(renderer->hasLayer());
327
328     RenderBox* box = toRenderBox(renderer);
329     ASSERT_TRUE(box->usesCompositedScrolling());
330     ASSERT_EQ(PaintsIntoOwnBacking, box->layer()->compositingState());
331
332     CompositedLayerMappingPtr compositedLayerMapping = box->layer()->compositedLayerMapping();
333     ASSERT_TRUE(compositedLayerMapping->hasScrollingLayer());
334     ASSERT(compositedLayerMapping->scrollingContentsLayer());
335
336     GraphicsLayer* graphicsLayer = compositedLayerMapping->scrollingContentsLayer();
337     ASSERT_EQ(box->layer()->scrollableArea(), graphicsLayer->scrollableArea());
338
339     WebLayer* webScrollLayer = compositedLayerMapping->scrollingContentsLayer()->platformLayer();
340     ASSERT_TRUE(webScrollLayer->scrollable());
341     ASSERT_TRUE(webScrollLayer->userScrollableHorizontal());
342     ASSERT_FALSE(webScrollLayer->userScrollableVertical());
343
344     overflowElement = frame()->document()->getElementById("unscrollable-x");
345     ASSERT(overflowElement);
346
347     renderer = overflowElement->renderer();
348     ASSERT_TRUE(renderer->isBox());
349     ASSERT_TRUE(renderer->hasLayer());
350
351     box = toRenderBox(renderer);
352     ASSERT_TRUE(box->scrollableArea()->usesCompositedScrolling());
353     ASSERT_EQ(PaintsIntoOwnBacking, box->layer()->compositingState());
354
355     compositedLayerMapping = box->layer()->compositedLayerMapping();
356     ASSERT_TRUE(compositedLayerMapping->hasScrollingLayer());
357     ASSERT(compositedLayerMapping->scrollingContentsLayer());
358
359     graphicsLayer = compositedLayerMapping->scrollingContentsLayer();
360     ASSERT_EQ(box->layer()->scrollableArea(), graphicsLayer->scrollableArea());
361
362     webScrollLayer = compositedLayerMapping->scrollingContentsLayer()->platformLayer();
363     ASSERT_TRUE(webScrollLayer->scrollable());
364     ASSERT_FALSE(webScrollLayer->userScrollableHorizontal());
365     ASSERT_TRUE(webScrollLayer->userScrollableVertical());
366 }
367
368 TEST_F(ScrollingCoordinatorChromiumTest, iframeScrolling)
369 {
370     registerMockedHttpURLLoad("iframe-scrolling.html");
371     registerMockedHttpURLLoad("iframe-scrolling-inner.html");
372     navigateTo(m_baseURL + "iframe-scrolling.html");
373     forceFullCompositingUpdate();
374
375     // Verify the properties of the accelerated scrolling element starting from the RenderObject
376     // all the way to the WebLayer.
377     Element* scrollableFrame = frame()->document()->getElementById("scrollable");
378     ASSERT_TRUE(scrollableFrame);
379
380     RenderObject* renderer = scrollableFrame->renderer();
381     ASSERT_TRUE(renderer);
382     ASSERT_TRUE(renderer->isWidget());
383
384     RenderWidget* renderWidget = toRenderWidget(renderer);
385     ASSERT_TRUE(renderWidget);
386     ASSERT_TRUE(renderWidget->widget());
387     ASSERT_TRUE(renderWidget->widget()->isFrameView());
388
389     FrameView* innerFrameView = toFrameView(renderWidget->widget());
390     RenderView* innerRenderView = innerFrameView->renderView();
391     ASSERT_TRUE(innerRenderView);
392
393     RenderLayerCompositor* innerCompositor = innerRenderView->compositor();
394     ASSERT_TRUE(innerCompositor->inCompositingMode());
395     ASSERT_TRUE(innerCompositor->scrollLayer());
396
397     GraphicsLayer* scrollLayer = innerCompositor->scrollLayer();
398     ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea());
399
400     WebLayer* webScrollLayer = scrollLayer->platformLayer();
401     ASSERT_TRUE(webScrollLayer->scrollable());
402
403 #if OS(ANDROID)
404     // Now verify we've attached impl-side scrollbars onto the scrollbar layers
405     ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar());
406     ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar()->hasContentsLayer());
407     ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar());
408     ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar()->hasContentsLayer());
409 #endif
410 }
411
412 TEST_F(ScrollingCoordinatorChromiumTest, rtlIframe)
413 {
414     registerMockedHttpURLLoad("rtl-iframe.html");
415     registerMockedHttpURLLoad("rtl-iframe-inner.html");
416     navigateTo(m_baseURL + "rtl-iframe.html");
417     forceFullCompositingUpdate();
418
419     // Verify the properties of the accelerated scrolling element starting from the RenderObject
420     // all the way to the WebLayer.
421     Element* scrollableFrame = frame()->document()->getElementById("scrollable");
422     ASSERT_TRUE(scrollableFrame);
423
424     RenderObject* renderer = scrollableFrame->renderer();
425     ASSERT_TRUE(renderer);
426     ASSERT_TRUE(renderer->isWidget());
427
428     RenderWidget* renderWidget = toRenderWidget(renderer);
429     ASSERT_TRUE(renderWidget);
430     ASSERT_TRUE(renderWidget->widget());
431     ASSERT_TRUE(renderWidget->widget()->isFrameView());
432
433     FrameView* innerFrameView = toFrameView(renderWidget->widget());
434     RenderView* innerRenderView = innerFrameView->renderView();
435     ASSERT_TRUE(innerRenderView);
436
437     RenderLayerCompositor* innerCompositor = innerRenderView->compositor();
438     ASSERT_TRUE(innerCompositor->inCompositingMode());
439     ASSERT_TRUE(innerCompositor->scrollLayer());
440
441     GraphicsLayer* scrollLayer = innerCompositor->scrollLayer();
442     ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea());
443
444     WebLayer* webScrollLayer = scrollLayer->platformLayer();
445     ASSERT_TRUE(webScrollLayer->scrollable());
446
447     int expectedScrollPosition = 958 + (innerFrameView->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15);
448     ASSERT_EQ(expectedScrollPosition, webScrollLayer->scrollPosition().x);
449 }
450
451 TEST_F(ScrollingCoordinatorChromiumTest, setupScrollbarLayerShouldNotCrash)
452 {
453     registerMockedHttpURLLoad("setup_scrollbar_layer_crash.html");
454     navigateTo(m_baseURL + "setup_scrollbar_layer_crash.html");
455     forceFullCompositingUpdate();
456     // This test document setup an iframe with scrollbars, then switch to
457     // an empty document by javascript.
458 }
459
460 } // namespace