OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/dom/Document.h" | 5 #include "core/dom/Document.h" |
| 6 #include "core/dom/FrameRequestCallback.h" |
6 #include "core/html/HTMLIFrameElement.h" | 7 #include "core/html/HTMLIFrameElement.h" |
7 #include "core/layout/api/LayoutViewItem.h" | 8 #include "core/layout/api/LayoutViewItem.h" |
8 #include "core/paint/PaintLayer.h" | 9 #include "core/paint/PaintLayer.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "web/tests/sim/SimCompositor.h" | 11 #include "web/tests/sim/SimCompositor.h" |
11 #include "web/tests/sim/SimDisplayItemList.h" | 12 #include "web/tests/sim/SimDisplayItemList.h" |
12 #include "web/tests/sim/SimRequest.h" | 13 #include "web/tests/sim/SimRequest.h" |
13 #include "web/tests/sim/SimTest.h" | 14 #include "web/tests/sim/SimTest.h" |
14 | 15 |
15 namespace blink { | 16 namespace blink { |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 SimRequest mainResource("https://example.com/test.html", "text/html"); | 229 SimRequest mainResource("https://example.com/test.html", "text/html"); |
229 SimRequest frameResource("https://example.com/frame.html", "text/html"); | 230 SimRequest frameResource("https://example.com/frame.html", "text/html"); |
230 SimRequest cssResource("https://example.com/test.css", "text/css"); | 231 SimRequest cssResource("https://example.com/test.css", "text/css"); |
231 | 232 |
232 loadURL("https://example.com/test.html"); | 233 loadURL("https://example.com/test.html"); |
233 | 234 |
234 webView().resize(WebSize(800, 600)); | 235 webView().resize(WebSize(800, 600)); |
235 | 236 |
236 mainResource.complete( | 237 mainResource.complete( |
237 "<!DOCTYPE html>" | 238 "<!DOCTYPE html>" |
| 239 "<body style='background: red'>" |
238 "<iframe id=frame src=frame.html style='border: none'></iframe>" | 240 "<iframe id=frame src=frame.html style='border: none'></iframe>" |
239 "<p style='transform: translateZ(0)'>Hello World</p>"); | 241 "<p style='transform: translateZ(0)'>Hello World</p>"); |
240 | 242 |
241 // Main page is ready to begin painting as there's no pending sheets. | 243 // Main page is ready to begin painting as there's no pending sheets. |
242 // The frame is not yet loaded, so we only paint the top level page. | 244 // The frame is not yet loaded, so we only paint the top level page. |
243 auto frame1 = compositor().beginFrame(); | 245 auto frame1 = compositor().beginFrame(); |
244 EXPECT_TRUE(frame1.contains(SimCanvas::Text)); | 246 EXPECT_TRUE(frame1.contains(SimCanvas::Text)); |
245 | 247 |
246 frameResource.complete( | 248 frameResource.complete( |
247 "<!DOCTYPE html>" | 249 "<!DOCTYPE html>" |
(...skipping 10 matching lines...) Expand all Loading... |
258 // script that touched offsetTop in the child frame. | 260 // script that touched offsetTop in the child frame. |
259 auto* childFrame = toHTMLIFrameElement(document().getElementById("frame")); | 261 auto* childFrame = toHTMLIFrameElement(document().getElementById("frame")); |
260 childFrame->contentDocument()->updateStyleAndLayoutIgnorePendingStylesheets(); | 262 childFrame->contentDocument()->updateStyleAndLayoutIgnorePendingStylesheets(); |
261 | 263 |
262 auto frame2 = compositor().beginFrame(); | 264 auto frame2 = compositor().beginFrame(); |
263 | 265 |
264 // The child frame still has pending sheets, and the parent frame has no | 266 // The child frame still has pending sheets, and the parent frame has no |
265 // invalid paint so we shouldn't draw any text. | 267 // invalid paint so we shouldn't draw any text. |
266 EXPECT_FALSE(frame2.contains(SimCanvas::Text)); | 268 EXPECT_FALSE(frame2.contains(SimCanvas::Text)); |
267 | 269 |
268 LayoutViewItem iframeLayoutViewItem = | 270 // 1 for the main frame background (red). |
269 childFrame->contentDocument()->layoutViewItem(); | 271 // TODO(esprehn): If we were super smart we'd notice that the nested iframe is |
270 const DisplayItemList& displayItemList = iframeLayoutViewItem.layer() | 272 // actually composited and not repaint the main frame, but that likely |
271 ->graphicsLayerBacking() | 273 // requires doing compositing and paint invalidation bottom up. |
272 ->getPaintController() | 274 EXPECT_EQ(1, frame2.drawCount()); |
273 .getDisplayItemList(); | 275 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "red")); |
274 // Check that the DisplayItemList has no subsequene caching markers. These are | |
275 // not allowed in pending-style-sheets mode since otherwise caching would be | |
276 // incorrect. | |
277 ASSERT_EQ(2u, displayItemList.size()); | |
278 EXPECT_EQ(DisplayItem::kDocumentBackground, displayItemList[0].getType()); | |
279 EXPECT_EQ(DisplayItem::kBoxDecorationBackground, | |
280 displayItemList[1].getType()); | |
281 | |
282 // 1 for the main frame background (white), | |
283 // 1 for the iframe background (pink) | |
284 // 1 for the composited transform layer in the iframe (green). | |
285 // TODO(esprehn): Why FOUC the background (borders, etc.) of iframes and | |
286 // composited layers? Seems like a bug. | |
287 EXPECT_EQ(3, frame2.drawCount()); | |
288 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "white")); | |
289 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "pink")); | |
290 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "green")); | |
291 | 276 |
292 // Finish loading the sheets in the child frame. After it should issue a | 277 // Finish loading the sheets in the child frame. After it should issue a |
293 // paint invalidation for every layer since frame2 painted them but skipped | 278 // paint invalidation for every layer when the frame becomes unthrottled. |
294 // painting the real content to avoid FOUC. | |
295 cssResource.complete(); | 279 cssResource.complete(); |
296 | 280 |
297 // First frame where all frames are loaded, should paint the text in the | 281 // First frame where all frames are loaded, should paint the text in the |
298 // child frame. | 282 // child frame. |
299 auto frame3 = compositor().beginFrame(); | 283 auto frame3 = compositor().beginFrame(); |
300 EXPECT_TRUE(frame3.contains(SimCanvas::Text)); | 284 EXPECT_TRUE(frame3.contains(SimCanvas::Text)); |
301 } | 285 } |
302 | 286 |
| 287 namespace { |
| 288 |
| 289 class CheckRafCallback final : public FrameRequestCallback { |
| 290 public: |
| 291 void handleEvent(double highResTimeMs) override { m_wasCalled = true; } |
| 292 bool wasCalled() const { return m_wasCalled; } |
| 293 |
| 294 private: |
| 295 bool m_wasCalled = false; |
| 296 }; |
| 297 }; |
| 298 |
| 299 TEST_F(DocumentLoadingRenderingTest, |
| 300 ShouldThrottleIframeLifecycleUntilPendingSheetsLoaded) { |
| 301 SimRequest mainResource("https://example.com/main.html", "text/html"); |
| 302 SimRequest frameResource("https://example.com/frame.html", "text/html"); |
| 303 SimRequest cssResource("https://example.com/frame.css", "text/css"); |
| 304 |
| 305 loadURL("https://example.com/main.html"); |
| 306 |
| 307 webView().resize(WebSize(800, 600)); |
| 308 |
| 309 mainResource.complete( |
| 310 "<!DOCTYPE html>" |
| 311 "<body style='background: red'>" |
| 312 "<iframe id=frame src=frame.html></iframe>"); |
| 313 |
| 314 frameResource.complete( |
| 315 "<!DOCTYPE html>" |
| 316 "<link rel=stylesheet href=frame.css>" |
| 317 "<body style='background: blue'>"); |
| 318 |
| 319 auto* childFrame = toHTMLIFrameElement(document().getElementById("frame")); |
| 320 |
| 321 // Frame while the child frame still has pending sheets. |
| 322 auto* frame1Callback = new CheckRafCallback(); |
| 323 childFrame->contentDocument()->requestAnimationFrame(frame1Callback); |
| 324 auto frame1 = compositor().beginFrame(); |
| 325 EXPECT_FALSE(frame1Callback->wasCalled()); |
| 326 EXPECT_TRUE(frame1.contains(SimCanvas::Rect, "red")); |
| 327 EXPECT_FALSE(frame1.contains(SimCanvas::Rect, "blue")); |
| 328 |
| 329 // Finish loading the sheets in the child frame. Should enable lifecycle |
| 330 // updates and raf callbacks. |
| 331 cssResource.complete(); |
| 332 |
| 333 // Frame with all lifecycle updates enabled. |
| 334 auto* frame2Callback = new CheckRafCallback(); |
| 335 childFrame->contentDocument()->requestAnimationFrame(frame2Callback); |
| 336 auto frame2 = compositor().beginFrame(); |
| 337 EXPECT_TRUE(frame1Callback->wasCalled()); |
| 338 EXPECT_TRUE(frame2Callback->wasCalled()); |
| 339 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "red")); |
| 340 EXPECT_TRUE(frame2.contains(SimCanvas::Rect, "blue")); |
| 341 } |
| 342 |
303 TEST_F(DocumentLoadingRenderingTest, | 343 TEST_F(DocumentLoadingRenderingTest, |
304 ShouldContinuePaintingWhenSheetsStartedAfterBody) { | 344 ShouldContinuePaintingWhenSheetsStartedAfterBody) { |
305 SimRequest mainResource("https://example.com/test.html", "text/html"); | 345 SimRequest mainResource("https://example.com/test.html", "text/html"); |
306 SimRequest cssHeadResource("https://example.com/testHead.css", "text/css"); | 346 SimRequest cssHeadResource("https://example.com/testHead.css", "text/css"); |
307 SimRequest cssBodyResource("https://example.com/testBody.css", "text/css"); | 347 SimRequest cssBodyResource("https://example.com/testBody.css", "text/css"); |
308 | 348 |
309 loadURL("https://example.com/test.html"); | 349 loadURL("https://example.com/test.html"); |
310 | 350 |
311 mainResource.start(); | 351 mainResource.start(); |
312 | 352 |
(...skipping 21 matching lines...) Expand all Loading... |
334 // Finish loading the CSS resource (no change to painting). | 374 // Finish loading the CSS resource (no change to painting). |
335 cssBodyResource.complete("a { color: red; }"); | 375 cssBodyResource.complete("a { color: red; }"); |
336 EXPECT_TRUE(document().isRenderingReady()); | 376 EXPECT_TRUE(document().isRenderingReady()); |
337 | 377 |
338 // Finish the load, painting should stay enabled. | 378 // Finish the load, painting should stay enabled. |
339 mainResource.finish(); | 379 mainResource.finish(); |
340 EXPECT_TRUE(document().isRenderingReady()); | 380 EXPECT_TRUE(document().isRenderingReady()); |
341 } | 381 } |
342 | 382 |
343 } // namespace blink | 383 } // namespace blink |
OLD | NEW |