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