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

Side by Side Diff: Source/core/frame/FrameViewTest.cpp

Issue 1246173002: Throttle rendering pipeline for invisible iframes (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Add layout tests. 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 | Annotate | Revision Log
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/frame/FrameView.h"
8
9 #include "core/dom/Document.h"
10 #include "core/frame/FrameOwner.h"
11 #include "core/frame/LocalFrame.h"
12 #include "core/loader/EmptyClients.h"
13 #include "core/page/Page.h"
14 #include "core/testing/DummyPageHolder.h"
15 #include "platform/testing/UnitTestHelpers.h"
16 #include <gtest/gtest.h>
17
18 namespace blink {
19
20 class RootFrameLoaderClient;
21
22 class MockChromeClient final : public EmptyChromeClient {
esprehn 2015/09/21 21:27:21 Can we just write a Sim test instead?
Sami 2015/09/23 18:31:07 Looks much nicer that way. Done. One minor issue w
23 public:
24 MockChromeClient()
25 : m_didScheduleAnimation(false) { }
26 ~MockChromeClient() override { }
27
28 void scheduleAnimation() override
29 {
30 m_didScheduleAnimation = true;
31 }
32
33 bool animationScheduled() const
34 {
35 return m_didScheduleAnimation;
36 }
37
38 void resetAnimationScheduled()
39 {
40 m_didScheduleAnimation = false;
41 }
42 private:
43 bool m_didScheduleAnimation;
44 };
45
46 class StubFrameLoaderClientWithParent final : public EmptyFrameLoaderClient {
47 public:
48 static PassOwnPtrWillBeRawPtr<StubFrameLoaderClientWithParent> create(Frame* parent)
49 {
50 return adoptPtrWillBeNoop(new StubFrameLoaderClientWithParent(parent));
51 }
52
53 DEFINE_INLINE_VIRTUAL_TRACE()
54 {
55 visitor->trace(m_parent);
56 EmptyFrameLoaderClient::trace(visitor);
57 }
58
59 Frame* parent() const override { return m_parent.get(); }
60
61 private:
62 explicit StubFrameLoaderClientWithParent(Frame* parent)
63 : m_parent(parent)
64 {
65 }
66
67 RawPtrWillBeMember<Frame> m_parent;
68 };
69
70 class StubFrameOwner : public NoBaseWillBeGarbageCollectedFinalized<StubFrameOwn er>, public FrameOwner {
71 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(StubFrameOwner);
72 public:
73 static PassOwnPtrWillBeRawPtr<StubFrameOwner> create()
74 {
75 return adoptPtrWillBeNoop(new StubFrameOwner);
76 }
77
78 DEFINE_INLINE_VIRTUAL_TRACE() { FrameOwner::trace(visitor); }
79
80 bool isLocal() const override { return false; }
81 SandboxFlags sandboxFlags() const override { return SandboxNone; }
82 void dispatchLoad() override { }
83 void renderFallbackContent() override { }
84 };
85
86 class FrameViewTest : public ::testing::Test {
87 public:
88 using SecurityOriginStatus = FrameView::SecurityOriginStatus;
89 using ViewportVisibility = FrameView::ViewportVisibility;
90
91 void SetUp() override;
92 void TearDown() override;
93
94 LocalFrame* childFrame() const
95 {
96 return m_childFrame.get();
97 }
98
99 ViewportVisibility viewportVisibility(FrameView* frameView)
100 {
101 return frameView->m_viewportVisibility;
102 }
103
104 void enableThrottling(FrameView* frameView)
105 {
106 frameView->m_viewportVisibility = ViewportVisibility::Hidden;
107 frameView->m_securityOriginStatusForThrottling = SecurityOriginStatus::I sCrossOrigin;
108 EXPECT_TRUE(frameView->shouldThrottleRenderingPipeline());
109 }
110
111 protected:
112 MockChromeClient m_mockChromeClient;
113 Page::PageClients m_pageClients;
114 OwnPtr<DummyPageHolder> m_dummyPageHolder;
115 RefPtrWillBePersistent<Document> m_document;
116 OwnPtrWillBePersistent<StubFrameOwner> m_frameOwner;
117
118 OwnPtrWillBePersistent<StubFrameLoaderClientWithParent> m_childClient;
119 RefPtrWillBePersistent<LocalFrame> m_childFrame;
120 };
121
122 class RootFrameLoaderClient final : public EmptyFrameLoaderClient {
123 public:
124 static PassOwnPtrWillBeRawPtr<RootFrameLoaderClient> create(FrameViewTest* t estSuite)
125 {
126 return adoptPtrWillBeNoop(new RootFrameLoaderClient(testSuite));
127 }
128
129 Frame* firstChild() const override { return m_testSuite->childFrame(); }
130
131 private:
132 explicit RootFrameLoaderClient(FrameViewTest* testSuite)
133 : m_testSuite(testSuite)
134 {
135 }
136
137 FrameViewTest* m_testSuite;
138 };
139
140 void FrameViewTest::SetUp()
141 {
142 // Create a root frame and one child frame. The FrameLoaderClients will conn ect the frames in the frame tree.
143 fillWithEmptyClients(m_pageClients);
144 m_pageClients.chromeClient = &m_mockChromeClient;
145 OwnPtrWillBePersistent<RootFrameLoaderClient> frameLoaderClient = RootFrameL oaderClient::create(this);
146 m_dummyPageHolder = DummyPageHolder::create(IntSize(640, 480), &m_pageClient s, frameLoaderClient.release());
147 m_document = &m_dummyPageHolder->document();
148 m_frameOwner = StubFrameOwner::create();
149
150 m_childClient = StubFrameLoaderClientWithParent::create(m_document->frame()) ;
151 m_childFrame = LocalFrame::create(m_childClient.get(), m_document->frame()-> host(), m_frameOwner.get());
152 m_childFrame->setView(FrameView::create(m_childFrame.get(), IntSize(320, 240 )));
153 m_childFrame->init();
154
155 // Also hook up the frames in the FrameView tree.
156 m_document->view()->addChild(m_childFrame->view());
157 }
158
159 void FrameViewTest::TearDown()
160 {
161 m_document->view()->removeChild(m_childFrame->view());
162 m_childFrame->detach(FrameDetachType::Remove);
163 m_childFrame = nullptr;
164 }
165
166 TEST_F(FrameViewTest, viewportVisibility)
167 {
168 // Initially both frames are visible.
169 FrameView* frameView = m_document->view();
170 FrameView* childFrameView = m_childFrame->view();
171 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
172 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(childFrameView));
173
174 // Moving the child fully outside the parent makes it invisible.
175 childFrameView->move(0, frameView->height());
176 frameView->updateAllLifecyclePhases();
177 frameView->updateThrottling();
178 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
179 EXPECT_EQ(ViewportVisibility::Hidden, viewportVisibility(childFrameView));
180
181 // A partially visible child is considered visible.
182 childFrameView->move(-childFrameView->width() / 2, 0);
183 frameView->updateAllLifecyclePhases();
184 frameView->updateThrottling();
185 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
186 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(childFrameView));
187 }
188
189 TEST_F(FrameViewTest, viewportVisibilityFullyClipped)
190 {
191 // A child which is fully clipped away by its ancestor should become invisib le.
192 FrameView* frameView = m_document->view();
193 FrameView* childFrameView = m_childFrame->view();
194 frameView->resize(0, 0);
195 frameView->updateAllLifecyclePhases();
196 frameView->updateThrottling();
197 EXPECT_EQ(ViewportVisibility::Visible, viewportVisibility(frameView));
198 EXPECT_EQ(ViewportVisibility::Hidden, viewportVisibility(childFrameView));
199 }
200
201 TEST_F(FrameViewTest, hiddenCrossOriginFramesAreThrottled)
202 {
203 FrameView* frameView = m_document->view();
204 FrameView* childFrameView = m_childFrame->view();
205 EXPECT_FALSE(frameView->shouldThrottleRenderingPipeline());
206 EXPECT_FALSE(childFrameView->shouldThrottleRenderingPipeline());
207
208 // Just being hidden doesn't make a frame throttled.
209 childFrameView->move(0, frameView->height());
210 frameView->updateAllLifecyclePhases();
211 frameView->updateThrottling();
212 EXPECT_FALSE(frameView->shouldThrottleRenderingPipeline());
213 EXPECT_FALSE(childFrameView->shouldThrottleRenderingPipeline());
214
215 // Also making the frame cross origin enables throttling.
216 m_childFrame->securityContext()->setSecurityOrigin(SecurityOrigin::createUni que());
217 frameView->updateThrottling();
218 EXPECT_FALSE(frameView->shouldThrottleRenderingPipeline());
219 EXPECT_TRUE(childFrameView->shouldThrottleRenderingPipeline());
220 }
221
222 TEST_F(FrameViewTest, throttledLifecycleUpdate)
223 {
224 FrameView* frameView = m_document->view();
225 FrameView* childFrameView = m_childFrame->view();
226 enableThrottling(childFrameView);
227
228 childFrameView->setNeedsLayout();
229 EXPECT_TRUE(childFrameView->needsLayout());
230 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Allow );
231 EXPECT_TRUE(childFrameView->needsLayout());
232
233 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Disal low);
234 EXPECT_FALSE(childFrameView->needsLayout());
235 }
236
237 TEST_F(FrameViewTest, unthrottledFrameSchedulesVisualUpdate)
238 {
239 FrameView* frameView = m_document->view();
240 FrameView* childFrameView = m_childFrame->view();
241 m_childFrame->securityContext()->setSecurityOrigin(SecurityOrigin::createUni que());
242
243 // First make the child hidden to enable throttling.
244 childFrameView->move(0, frameView->height());
245 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Allow );
246 m_mockChromeClient.resetAnimationScheduled();
247 frameView->updateThrottling();
248 EXPECT_FALSE(m_mockChromeClient.animationScheduled());
249
250 // Then bring it back on-screen. This should schedule a visual update.
251 childFrameView->move(0, 0);
252 frameView->updateAllLifecyclePhases(DocumentLifecycle::ThrottlingMode::Allow );
253 m_mockChromeClient.resetAnimationScheduled();
254 frameView->updateThrottling();
255 EXPECT_TRUE(m_mockChromeClient.animationScheduled());
256 }
257
258 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698