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