Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / web / tests / DocumentLoadingRenderingTest.cpp
blob1e03f63b0fdbd91a2fe365f95b221f2f86336cd4
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.
5 #include "config.h"
7 #include "core/dom/Document.h"
8 #include "core/frame/FrameView.h"
9 #include "web/WebLocalFrameImpl.h"
10 #include "web/tests/FrameTestHelpers.h"
11 #include "web/tests/sim/SimCompositor.h"
12 #include "web/tests/sim/SimDisplayItemList.h"
13 #include "web/tests/sim/SimLayerTreeView.h"
14 #include "web/tests/sim/SimNetwork.h"
15 #include "web/tests/sim/SimRequest.h"
16 #include "web/tests/sim/SimWebViewClient.h"
17 #include <gtest/gtest.h>
19 namespace blink {
21 class DocumentLoadingRenderingTest : public ::testing::Test {
22 protected:
23 DocumentLoadingRenderingTest()
24 : m_webViewClient(m_layerTreeView)
25 , m_compositor(m_layerTreeView)
27 m_webViewHelper.initialize(true, nullptr, &m_webViewClient);
28 m_compositor.setWebViewImpl(webView());
29 Document::setThreadedParsingEnabledForTesting(false);
32 virtual ~DocumentLoadingRenderingTest()
34 Document::setThreadedParsingEnabledForTesting(true);
37 void loadURL(const String& url)
39 WebURLRequest request;
40 request.initialize();
41 request.setURL(KURL(ParsedURLString, url));
42 webView().mainFrameImpl()->loadRequest(request);
45 Document& document()
47 return *webView().mainFrameImpl()->frame()->document();
50 WebViewImpl& webView()
52 return *m_webViewHelper.webViewImpl();
55 SimNetwork m_network;
56 SimLayerTreeView m_layerTreeView;
57 SimWebViewClient m_webViewClient;
58 SimCompositor m_compositor;
59 FrameTestHelpers::WebViewHelper m_webViewHelper;
62 TEST_F(DocumentLoadingRenderingTest, ShouldResumeCommitsAfterBodyParsedWithoutSheets)
64 SimRequest mainResource("https://example.com/test.html", "text/html");
66 loadURL("https://example.com/test.html");
68 mainResource.start();
70 // Still in the head, should not resume commits.
71 mainResource.write("<!DOCTYPE html>");
72 EXPECT_TRUE(m_layerTreeView.deferCommits());
73 mainResource.write("<title>Test</title><style>div { color red; }</style>");
74 EXPECT_TRUE(m_layerTreeView.deferCommits());
76 // Implicitly inserts the body. Since there's no loading stylesheets we
77 // should resume commits.
78 mainResource.write("<p>Hello World</p>");
79 EXPECT_FALSE(m_layerTreeView.deferCommits());
81 // Finish the load, should stay resumed.
82 mainResource.finish();
83 EXPECT_FALSE(m_layerTreeView.deferCommits());
86 TEST_F(DocumentLoadingRenderingTest, ShouldResumeCommitsAfterBodyIfSheetsLoaded)
88 SimRequest mainResource("https://example.com/test.html", "text/html");
89 SimRequest cssResource("https://example.com/test.css", "text/css");
91 loadURL("https://example.com/test.html");
93 mainResource.start();
95 // Still in the head, should not resume commits.
96 mainResource.write("<!DOCTYPE html><link rel=stylesheet href=test.css>");
97 EXPECT_TRUE(m_layerTreeView.deferCommits());
99 // Sheet is streaming in, but not ready yet.
100 cssResource.start();
101 cssResource.write("a { color: red; }");
102 EXPECT_TRUE(m_layerTreeView.deferCommits());
104 // Sheet finished, but no body yet, so don't resume.
105 cssResource.finish();
106 EXPECT_TRUE(m_layerTreeView.deferCommits());
108 // Body inserted and sheet is loaded so resume commits.
109 mainResource.write("<body>");
110 EXPECT_FALSE(m_layerTreeView.deferCommits());
112 // Finish the load, should stay resumed.
113 mainResource.finish();
114 EXPECT_FALSE(m_layerTreeView.deferCommits());
117 TEST_F(DocumentLoadingRenderingTest, ShouldResumeCommitsAfterSheetsLoaded)
119 SimRequest mainResource("https://example.com/test.html", "text/html");
120 SimRequest cssResource("https://example.com/test.css", "text/css");
122 loadURL("https://example.com/test.html");
124 mainResource.start();
126 // Still in the head, should not resume commits.
127 mainResource.write("<!DOCTYPE html><link rel=stylesheet href=test.css>");
128 EXPECT_TRUE(m_layerTreeView.deferCommits());
130 // Sheet is streaming in, but not ready yet.
131 cssResource.start();
132 cssResource.write("a { color: red; }");
133 EXPECT_TRUE(m_layerTreeView.deferCommits());
135 // Body inserted, but sheet is still loading so don't resume.
136 mainResource.write("<body>");
137 EXPECT_TRUE(m_layerTreeView.deferCommits());
139 // Sheet finished and there's a body so resume.
140 cssResource.finish();
141 EXPECT_FALSE(m_layerTreeView.deferCommits());
143 // Finish the load, should stay resumed.
144 mainResource.finish();
145 EXPECT_FALSE(m_layerTreeView.deferCommits());
148 TEST_F(DocumentLoadingRenderingTest, ShouldResumeCommitsAfterDocumentElementWithNoSheets)
150 SimRequest mainResource("https://example.com/test.svg", "image/svg+xml");
151 SimRequest cssResource("https://example.com/test.css", "text/css");
153 loadURL("https://example.com/test.svg");
155 mainResource.start();
157 // Sheet loading and no documentElement, so don't resume.
158 mainResource.write("<?xml-stylesheet type='text/css' href='test.css'?>");
159 EXPECT_TRUE(m_layerTreeView.deferCommits());
161 // Sheet finishes loading, but no documentElement yet so don't resume.
162 cssResource.start();
163 cssResource.write("a { color: red; }");
164 cssResource.finish();
165 EXPECT_TRUE(m_layerTreeView.deferCommits());
167 // Root inserted so resume.
168 mainResource.write("<svg xmlns='http://www.w3.org/2000/svg'></svg>");
169 EXPECT_FALSE(m_layerTreeView.deferCommits());
171 // Finish the load, should stay resumed.
172 mainResource.finish();
173 EXPECT_FALSE(m_layerTreeView.deferCommits());
176 TEST_F(DocumentLoadingRenderingTest, ShouldResumeCommitsAfterSheetsLoadForXml)
178 SimRequest mainResource("https://example.com/test.svg", "image/svg+xml");
179 SimRequest cssResource("https://example.com/test.css", "text/css");
181 loadURL("https://example.com/test.svg");
183 mainResource.start();
185 // Not done parsing.
186 mainResource.write("<?xml-stylesheet type='text/css' href='test.css'?>");
187 EXPECT_TRUE(m_layerTreeView.deferCommits());
189 // Sheet is streaming in, but not ready yet.
190 cssResource.start();
191 cssResource.write("a { color: red; }");
192 EXPECT_TRUE(m_layerTreeView.deferCommits());
194 // Root inserted, but sheet is still loading so don't resume.
195 mainResource.write("<svg xmlns='http://www.w3.org/2000/svg'></svg>");
196 EXPECT_TRUE(m_layerTreeView.deferCommits());
198 // Finish the load, but sheets still loading so don't resume.
199 mainResource.finish();
200 EXPECT_TRUE(m_layerTreeView.deferCommits());
202 // Sheet finished, so resume commits.
203 cssResource.finish();
204 EXPECT_FALSE(m_layerTreeView.deferCommits());
207 TEST_F(DocumentLoadingRenderingTest, ShouldResumeCommitsAfterFinishParsingXml)
209 SimRequest mainResource("https://example.com/test.svg", "image/svg+xml");
211 loadURL("https://example.com/test.svg");
213 mainResource.start();
215 // Finish parsing, no sheets loading so resume.
216 mainResource.finish();
217 EXPECT_FALSE(m_layerTreeView.deferCommits());
220 TEST_F(DocumentLoadingRenderingTest, ShouldResumeImmediatelyForImageDocuments)
222 SimRequest mainResource("https://example.com/test.png", "image/png");
224 loadURL("https://example.com/test.png");
226 mainResource.start();
227 EXPECT_TRUE(m_layerTreeView.deferCommits());
229 // Not really a valid image but enough for the test. ImageDocuments should
230 // resume painting as soon as the first bytes arrive.
231 mainResource.write("image data");
232 EXPECT_FALSE(m_layerTreeView.deferCommits());
234 mainResource.finish();
235 EXPECT_FALSE(m_layerTreeView.deferCommits());
238 TEST_F(DocumentLoadingRenderingTest, ShouldScheduleFrameAfterSheetsLoaded)
240 SimRequest mainResource("https://example.com/test.html", "text/html");
241 SimRequest firstCssResource("https://example.com/first.css", "text/css");
242 SimRequest secondCssResource("https://example.com/second.css", "text/css");
244 loadURL("https://example.com/test.html");
246 mainResource.start();
248 // Load a stylesheet.
249 mainResource.write("<!DOCTYPE html><link id=link rel=stylesheet href=first.css>");
250 EXPECT_TRUE(m_layerTreeView.deferCommits());
252 firstCssResource.start();
253 firstCssResource.write("body { color: red; }");
254 mainResource.write("<body>");
255 firstCssResource.finish();
257 // Sheet finished and there's a body so resume.
258 EXPECT_FALSE(m_layerTreeView.deferCommits());
260 mainResource.finish();
261 m_layerTreeView.clearNeedsAnimate();
263 // Replace the stylesheet by changing href.
264 Element* element = document().getElementById("link");
265 EXPECT_NE(nullptr, element);
266 element->setAttribute(HTMLNames::hrefAttr, "second.css");
267 EXPECT_FALSE(m_layerTreeView.needsAnimate());
269 secondCssResource.start();
270 secondCssResource.write("body { color: red; }");
271 secondCssResource.finish();
272 EXPECT_TRUE(m_layerTreeView.needsAnimate());
275 TEST_F(DocumentLoadingRenderingTest, ShouldNotPaintIframeContentWithPendingSheets)
277 SimRequest mainResource("https://example.com/test.html", "text/html");
278 SimRequest frameResource("https://example.com/frame.html", "text/html");
279 SimRequest cssResource("https://example.com/test.css", "text/css");
281 loadURL("https://example.com/test.html");
283 webView().resize(WebSize(800, 600));
285 mainResource.start();
286 mainResource.write(
287 "<!DOCTYPE html>"
288 "<iframe src=frame.html style='border: none'></iframe>"
289 "<p style='transform: translateZ(0)'>Hello World</p>"
291 mainResource.finish();
293 // Main page is ready to begin painting as there's no pending sheets.
294 // The frame is not yet loaded, so we only paint the top level page.
295 auto frame1 = m_compositor.beginFrame();
296 EXPECT_TRUE(frame1.containsText());
298 frameResource.start();
299 frameResource.write(
300 "<!DOCTYPE html>"
301 "<style>html { background: pink }</style>"
302 "<link rel=stylesheet href=test.css>"
303 "<p style='background: yellow;'>Hello World</p>"
304 "<div style='transform: translateZ(0); background: green;'>"
305 " <p style='background: blue;'>Hello Layer</p>"
306 " <div style='position: relative; background: red;'>Hello World</div>"
307 "</div>"
309 frameResource.finish();
311 // Trigger a layout with pending sheets. For example a page could trigger
312 // this by doing offsetTop in a setTimeout, or by a parent frame executing
313 // script that touched offsetTop in the child frame.
314 LocalFrame* childFrame = toLocalFrame(document().frame()->tree().firstChild());
315 childFrame->document()->updateLayoutIgnorePendingStylesheets();
317 auto frame2 = m_compositor.beginFrame();
319 // The child frame still has pending sheets, and the parent frame has no
320 // invalid paint so we shouldn't draw any text.
321 EXPECT_FALSE(frame2.containsText());
323 // 1 for the main frame background (white),
324 // 1 for the iframe background (pink)
325 // 1 for the composited transform layer in the iframe (green).
326 // TODO(esprehn): Why FOUC the background (borders, etc.) of iframes and
327 // composited layers? Seems like a bug.
328 EXPECT_EQ(3, frame2.drawCount());
329 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "white"));
330 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "pink"));
331 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "green"));
333 // Finish loading the sheets in the child frame. After it should issue a
334 // paint invalidation for every layer since frame2 painted them but skipped
335 // painting the real content to avoid FOUC.
336 cssResource.start();
337 cssResource.finish();
339 // First frame where all frames are loaded, should paint the text in the
340 // child frame.
341 auto frame3 = m_compositor.beginFrame();
342 EXPECT_TRUE(frame3.containsText());
345 } // namespace blink