blob: 29072542ad6287376a55af0694dc0b0866f0b353 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/loader/font_preload_manager.h"
#include "base/test/scoped_feature_list.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
class FontPreloadManagerTest : public SimTest {
public:
void SetUp() override {
scoped_feature_list_.InitAndEnableFeature(
features::kFontPreloadingDelaysRendering);
SimTest::SetUp();
}
protected:
FontPreloadManager& GetFontPreloadManager() {
return GetDocument().GetFontPreloadManager();
}
using State = FontPreloadManager::State;
State GetState() { return GetFontPreloadManager().state_; }
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(FontPreloadManagerTest, FastFontFinishBeforeBody) {
SimRequest main_resource("https://example.com", "text/html");
SimRequest font_resource("https://example.com/font.woff", "font/woff2");
LoadURL("https://example.com");
main_resource.Write(R"HTML(
<!doctype html>
<head>
<link rel="preload" as="font" type="font/woff2"
href="https://example.com/font.woff">
)HTML");
// Rendering is blocked due to ongoing font preloading.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_TRUE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoading, GetState());
font_resource.Finish();
test::RunPendingTasks();
// Font preloading no longer blocks renderings. However, rendering is still
// blocked, as we don't have BODY yet.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_FALSE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoaded, GetState());
main_resource.Complete("</head><body>some text</body>");
// Rendering starts after BODY has arrived, as the font was loaded earlier.
EXPECT_FALSE(Compositor().DeferMainFrameUpdate());
EXPECT_FALSE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kUnblocked, GetState());
}
TEST_F(FontPreloadManagerTest, FastFontFinishAfterBody) {
SimRequest main_resource("https://example.com", "text/html");
SimRequest font_resource("https://example.com/font.woff", "font/woff2");
LoadURL("https://example.com");
main_resource.Write(R"HTML(
<!doctype html>
<head>
<link rel="preload" as="font" type="font/woff2"
href="https://example.com/font.woff">
)HTML");
// Rendering is blocked due to ongoing font preloading.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_TRUE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoading, GetState());
main_resource.Complete("</head><body>some text</body>");
// Rendering is still blocked by font, even if we already have BODY, because
// the font was *not* loaded earlier.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_TRUE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoading, GetState());
font_resource.Finish();
test::RunPendingTasks();
// Rendering starts after font preloading has finished.
EXPECT_FALSE(Compositor().DeferMainFrameUpdate());
EXPECT_FALSE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kUnblocked, GetState());
}
TEST_F(FontPreloadManagerTest, SlowFontTimeoutBeforeBody) {
SimRequest main_resource("https://example.com", "text/html");
SimRequest font_resource("https://example.com/font.woff", "font/woff2");
LoadURL("https://example.com");
main_resource.Write(R"HTML(
<!doctype html>
<head>
<link rel="preload" as="font" type="font/woff2"
href="https://example.com/font.woff">
)HTML");
// Rendering is blocked due to ongoing font preloading.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_TRUE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoading, GetState());
GetFontPreloadManager().FontPreloadingDelaysRenderingTimerFired(nullptr);
// Font preloading no longer blocks renderings after the timeout fires.
// However, rendering is still blocked, as we don't have BODY yet.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_FALSE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kUnblocked, GetState());
main_resource.Complete("</head><body>some text</body>");
// Rendering starts after BODY has arrived.
EXPECT_FALSE(Compositor().DeferMainFrameUpdate());
EXPECT_FALSE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kUnblocked, GetState());
font_resource.Finish();
}
TEST_F(FontPreloadManagerTest, SlowFontTimeoutAfterBody) {
SimRequest main_resource("https://example.com", "text/html");
SimRequest font_resource("https://example.com/font.woff", "font/woff2");
LoadURL("https://example.com");
main_resource.Write(R"HTML(
<!doctype html>
<head>
<link rel="preload" as="font" type="font/woff2"
href="https://example.com/font.woff">
)HTML");
// Rendering is blocked due to ongoing font preloading.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_TRUE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoading, GetState());
main_resource.Complete("</head><body>some text</body>");
// Rendering is still blocked by font, even if we already have BODY.
EXPECT_TRUE(Compositor().DeferMainFrameUpdate());
EXPECT_TRUE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kLoading, GetState());
GetFontPreloadManager().FontPreloadingDelaysRenderingTimerFired(nullptr);
// Rendering starts after we've waited for the font preloading long enough.
EXPECT_FALSE(Compositor().DeferMainFrameUpdate());
EXPECT_FALSE(GetFontPreloadManager().HasPendingRenderBlockingFonts());
EXPECT_EQ(State::kUnblocked, GetState());
font_resource.Finish();
}
} // namespace blink