Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1052)

Side by Side Diff: third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp

Issue 1364063007: Throttle rendering pipeline for invisible frames (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Might help to include the test source code. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/web/WebViewImpl.cpp ('k') | third_party/WebKit/Source/web/web.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6
7 #include "core/dom/Document.h"
8 #include "core/frame/FrameView.h"
9 #include "public/web/WebElement.h"
10 #include "web/WebLocalFrameImpl.h"
11 #include "web/tests/FrameTestHelpers.h"
12 #include "web/tests/sim/SimCompositor.h"
13 #include "web/tests/sim/SimDisplayItemList.h"
14 #include "web/tests/sim/SimLayerTreeView.h"
15 #include "web/tests/sim/SimWebViewClient.h"
16 #include <gtest/gtest.h>
17
18 namespace blink {
19
20 class FrameThrottlingTest : public ::testing::Test {
21 protected:
22 using SecurityOriginStatus = FrameView::SecurityOriginStatus;
23 using ViewportVisibility = FrameView::ViewportVisibility;
24
25 FrameThrottlingTest()
26 : m_webViewClient(m_layerTreeView)
27 , m_compositor(m_layerTreeView)
28 {
29 m_webViewHelper.initialize(true, &m_webFrameClient, &m_webViewClient);
30 m_compositor.setWebViewImpl(webView());
31 webView().resize(WebSize(640, 480));
32 }
33
34 ~FrameThrottlingTest() override { }
35
36 void setInnerHTML(const String& html)
37 {
38 document().documentElement()->setInnerHTML(html, ASSERT_NO_EXCEPTION);
39 m_webFrameClient.waitForLoadToComplete();
40 webView().layout();
41 }
42
43 void setupPageWithThrottleableFrame()
44 {
45 setInnerHTML("<iframe sandbox=\"\"></iframe>");
46 }
47
48 Document& document()
49 {
50 return *webView().mainFrameImpl()->frame()->document();
51 }
52
53 WebNode root()
54 {
55 return WebNode(document().documentElement());
56 }
57
58 WebViewImpl& webView()
59 {
60 return *m_webViewHelper.webViewImpl();
61 }
62
63 ViewportVisibility viewportVisibility(FrameView* frameView)
64 {
65 return frameView->m_viewportVisibility;
66 }
67
68 SimLayerTreeView m_layerTreeView;
69 SimWebViewClient m_webViewClient;
70 SimCompositor m_compositor;
71 FrameTestHelpers::TestWebFrameClient m_webFrameClient;
72 FrameTestHelpers::WebViewHelper m_webViewHelper;
73 };
74
75 TEST_F(FrameThrottlingTest, ThrottleInvisibleFrames)
76 {
77 setupPageWithThrottleableFrame();
78
79 // Initially both frames are visible.
80 FrameView* frameView = document().view();
81 FrameView* childFrameView = toLocalFrame(frameView->frame().tree().firstChil d())->view();
82 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
83 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(childFrameView));
84
85 // Moving the child fully outside the parent makes it invisible.
86 childFrameView->move(0, frameView->height());
87 frameView->updateAllLifecyclePhases();
88 frameView->finalizeLifecycleUpdate();
89 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
90 EXPECT_EQ(ViewportVisibility::Hidden, viewportVisibility(childFrameView));
91
92 // A partially visible child is considered visible.
93 childFrameView->move(-childFrameView->width() / 2, 0);
94 frameView->updateAllLifecyclePhases();
95 frameView->finalizeLifecycleUpdate();
esprehn 2015/10/01 08:21:37 m_compositor.beginFrame()
Sami 2015/10/05 17:58:24 Done.
96 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
97 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(childFrameView));
98 }
99
100 TEST_F(FrameThrottlingTest, viewportVisibilityFullyClipped)
101 {
102 setupPageWithThrottleableFrame();
103
104 // A child which is fully clipped away by its ancestor should become invisib le.
105 FrameView* frameView = document().view();
106 FrameView* childFrameView = toLocalFrame(frameView->frame().tree().firstChil d())->view();
107 webView().resize(WebSize(0, 0));
108 webView().layout();
esprehn 2015/10/01 08:21:37 ditto, layout is only triggered from frames, so yo
Sami 2015/10/05 17:58:24 Done.
109 frameView->updateAllLifecyclePhases();
110 frameView->finalizeLifecycleUpdate();
esprehn 2015/10/01 08:21:36 and then you don't need this
Sami 2015/10/05 17:58:24 Done.
111 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
112 EXPECT_EQ(ViewportVisibility::Hidden, viewportVisibility(childFrameView));
113 }
114
115 TEST_F(FrameThrottlingTest, hiddenCrossOriginFramesAreThrottled)
116 {
117 // Create a document with doubly nested iframes.
118 setInnerHTML("<iframe srcdoc=\"<iframe></iframe>\"></iframe>");
119
120 FrameView* frameView = document().view();
121 LocalFrame* childFrame = toLocalFrame(frameView->frame().tree().firstChild() );
122 LocalFrame* grandChildFrame = toLocalFrame(childFrame->tree().firstChild());
123 FrameView* childFrameView = childFrame->view();
124 FrameView* grandChildFrameView = grandChildFrame->view();
125 EXPECT_FALSE(frameView->shouldThrottleRenderingPipeline());
126 EXPECT_FALSE(childFrameView->shouldThrottleRenderingPipeline());
127 EXPECT_FALSE(grandChildFrameView->shouldThrottleRenderingPipeline());
128
129 // Just being hidden doesn't make a frame throttled.
130 grandChildFrameView->move(0, frameView->height());
esprehn 2015/10/01 08:21:36 this can't happen in a real page, set some style t
Sami 2015/10/05 17:58:24 Done.
131 frameView->finalizeLifecycleUpdate();
132 EXPECT_FALSE(frameView->shouldThrottleRenderingPipeline());
133 EXPECT_FALSE(childFrameView->shouldThrottleRenderingPipeline());
134 EXPECT_FALSE(grandChildFrameView->shouldThrottleRenderingPipeline());
135
136 // Making the middle frame cross origin enables throttling for the grand chi ld.
137 childFrame->securityContext()->setSecurityOrigin(SecurityOrigin::createUniqu e());
138 frameView->finalizeLifecycleUpdate();
esprehn 2015/10/01 08:21:36 why would this happen again in a real page?
Sami 2015/10/05 17:58:24 You're right, it wouldn't. To make this more reali
139 EXPECT_FALSE(frameView->shouldThrottleRenderingPipeline());
140 EXPECT_FALSE(childFrameView->shouldThrottleRenderingPipeline());
141 EXPECT_TRUE(grandChildFrameView->shouldThrottleRenderingPipeline());
142 }
143
144 TEST_F(FrameThrottlingTest, throttledLifecycleUpdate)
145 {
146 setupPageWithThrottleableFrame();
147
148 FrameView* frameView = document().view();
149 LocalFrame* childFrame = toLocalFrame(frameView->frame().tree().firstChild() );
150 FrameView* childFrameView = childFrame->view();
151
152 // Enable throttling for the child frame.
153 childFrameView->move(0, frameView->height());
esprehn 2015/10/01 08:21:36 move with style, real pages can't go through ->mov
Sami 2015/10/05 17:58:25 Done.
154 frameView->updateAllLifecyclePhases();
155 frameView->finalizeLifecycleUpdate();
esprehn 2015/10/01 08:21:36 ditto, beginFrame()
Sami 2015/10/05 17:58:24 Done.
156 EXPECT_TRUE(childFrameView->shouldThrottleRenderingPipeline());
157
158 // Doing a lifecycle update while allowing throttling shouldn't clear the
159 // needs layout bit on the child frame.
160 childFrameView->setNeedsLayout();
esprehn 2015/10/01 08:21:37 don't artificially cause layout, do something real
Sami 2015/10/05 17:58:24 Done.
161 EXPECT_TRUE(childFrameView->needsLayout());
162 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Allow );
esprehn 2015/10/01 08:21:37 this can't really happen
Sami 2015/10/05 17:58:24 Replaced with another beginFrame().
163 EXPECT_TRUE(childFrameView->needsLayout());
164
165 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Disal low);
166 EXPECT_FALSE(childFrameView->needsLayout());
167 }
168
169 TEST_F(FrameThrottlingTest, unthrottlingFrameSchedulesAnimation)
170 {
171 setupPageWithThrottleableFrame();
172 FrameView* frameView = document().view();
173 LocalFrame* childFrame = toLocalFrame(frameView->frame().tree().firstChild() );
174 FrameView* childFrameView = childFrame->view();
175
176 // First make the child hidden to enable throttling.
177 childFrameView->move(0, frameView->height());
esprehn 2015/10/01 08:21:37 ditto
Sami 2015/10/05 17:58:24 Done.
178 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Allow );
179 m_layerTreeView.clearNeedsAnimate();
180 frameView->finalizeLifecycleUpdate();
181 EXPECT_FALSE(m_layerTreeView.needsAnimate());
182
183 // Then bring it back on-screen. This should schedule an animation update.
184 childFrameView->move(0, 0);
185 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Allow );
186 m_layerTreeView.clearNeedsAnimate();
esprehn 2015/10/01 08:21:36 beginFrame() clears this bit, real pages never cle
Sami 2015/10/05 17:58:24 Thanks, replaced this with beginFrame too, but had
187 frameView->finalizeLifecycleUpdate();
188 EXPECT_TRUE(m_layerTreeView.needsAnimate());
189 }
190
191 TEST_F(FrameThrottlingTest, mutatingThrottledFrameDoesNotCauseAnimation)
192 {
193 setInnerHTML("<iframe id=\"frame\" sandbox=\"\" srcdoc=\"<style> html { back ground: red; } </style>\"></iframe>");
194 WebExceptionCode ec;
195 WebElement frameElement = root().querySelector("#frame", ec);
196 EXPECT_EQ(0, ec);
197
198 // Check that the frame initially shows up.
199 m_layerTreeView.setDeferCommits(false);
200 SimDisplayItemList displayItems1 = m_compositor.beginFrame();
201 EXPECT_TRUE(displayItems1.contains(SimCanvas::Rect, "red"));
202
203 // Move the frame offscreen to throttle it.
204 FrameView* frameView = document().view();
205 LocalFrame* childFrame = toLocalFrame(frameView->frame().tree().firstChild() );
206 frameElement.setAttribute("style", "transform: translateY(480px)");
207 webView().layout();
208 frameView->finalizeLifecycleUpdate();
209
210 // Mutating the throttled frame should not cause an animation to be schedule d.
211 m_layerTreeView.clearNeedsAnimate();
212 childFrame->document()->documentElement()->setInnerHTML("<style> html { back ground: green; } </style>", ASSERT_NO_EXCEPTION);
213 EXPECT_FALSE(m_layerTreeView.needsAnimate());
214
215 // Moving the frame back on screen should make its new contents show up.
216 frameElement.setAttribute("style", "");
217 EXPECT_TRUE(m_layerTreeView.needsAnimate());
218 webView().layout();
esprehn 2015/10/01 08:21:36 beginFrame()
219 frameView->finalizeLifecycleUpdate();
esprehn 2015/10/01 08:21:36 How does this happen in a real page? You cause an
Sami 2015/10/05 17:58:24 Replaced this with a series of composites that sho
220
221 SimDisplayItemList displayItems2 = m_compositor.beginFrame();
222 EXPECT_TRUE(displayItems2.contains(SimCanvas::Rect, "green"));
223 }
224
225 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/web/WebViewImpl.cpp ('k') | third_party/WebKit/Source/web/web.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698