1 // Copyright 2014 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.
6 #include "core/css/RemoteFontFaceSource.h"
8 #include "core/css/CSSCustomFontData.h"
9 #include "core/css/CSSFontFace.h"
10 #include "core/css/FontLoader.h"
11 #include "platform/fonts/FontCache.h"
12 #include "platform/fonts/FontDescription.h"
13 #include "platform/fonts/SimpleFontData.h"
14 #include "public/platform/Platform.h"
15 #include "wtf/CurrentTime.h"
19 RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, PassRefPtrWillBeRawPtr<FontLoader> fontLoader)
21 , m_fontLoader(fontLoader)
23 m_font->addClient(this);
26 RemoteFontFaceSource::~RemoteFontFaceSource()
28 m_font->removeClient(this);
32 void RemoteFontFaceSource::pruneTable()
34 if (m_fontDataTable.isEmpty())
37 for (const auto& item : m_fontDataTable) {
38 SimpleFontData* fontData = item.value.get();
39 if (fontData && fontData->customFontData())
40 fontData->customFontData()->clearFontFaceSource();
42 m_fontDataTable.clear();
45 bool RemoteFontFaceSource::isLoading() const
47 return !m_font->stillNeedsLoad() && !m_font->isLoaded();
50 bool RemoteFontFaceSource::isLoaded() const
52 return m_font->isLoaded();
55 bool RemoteFontFaceSource::isValid() const
57 return !m_font->errorOccurred();
60 void RemoteFontFaceSource::didStartFontLoad(FontResource*)
62 // We may send duplicated reports when multiple CSSFontFaceSource are
63 // registered at this FontResource. Associating the same URL to different
64 // font-family causes the case, but we treat them as indivisual resources.
65 m_histograms.loadStarted();
68 void RemoteFontFaceSource::fontLoaded(FontResource*)
70 m_histograms.recordRemoteFont(m_font.get());
74 m_fontLoader->fontFaceInvalidated();
75 m_face->fontLoaded(this);
79 void RemoteFontFaceSource::fontLoadWaitLimitExceeded(FontResource*)
83 m_fontLoader->fontFaceInvalidated();
84 m_face->fontLoadWaitLimitExceeded(this);
87 m_histograms.recordFallbackTime(m_font.get());
90 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescription& fontDescription)
93 return createLoadingFallbackFontData(fontDescription);
95 // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
96 if (!m_font->ensureCustomFontData())
99 m_histograms.recordFallbackTime(m_font.get());
101 return SimpleFontData::create(
102 m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
103 fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
104 fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create());
107 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createLoadingFallbackFontData(const FontDescription& fontDescription)
109 // This temporary font is not retained and should not be returned.
110 FontCachePurgePreventer fontCachePurgePreventer;
111 SimpleFontData* temporaryFont = FontCache::fontCache()->getNonRetainedLastResortFallbackFont(fontDescription);
112 if (!temporaryFont) {
113 ASSERT_NOT_REACHED();
116 RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(this, m_font->exceedsFontLoadWaitLimit() ? CSSCustomFontData::VisibleFallback : CSSCustomFontData::InvisibleFallback);
117 return SimpleFontData::create(temporaryFont->platformData(), cssFontData);
120 void RemoteFontFaceSource::beginLoadIfNeeded()
122 if (m_font->stillNeedsLoad())
123 m_fontLoader->addFontToBeginLoading(m_font.get());
126 m_face->didBeginLoad();
129 bool RemoteFontFaceSource::ensureFontData()
131 return m_font->ensureCustomFontData();
134 void RemoteFontFaceSource::trace(Visitor* visitor)
136 visitor->trace(m_fontLoader);
137 CSSFontFaceSource::trace(visitor);
140 void RemoteFontFaceSource::FontLoadHistograms::loadStarted()
142 if (!m_loadStartTime)
143 m_loadStartTime = currentTimeMS();
146 void RemoteFontFaceSource::FontLoadHistograms::fallbackFontPainted()
148 if (!m_fallbackPaintTime)
149 m_fallbackPaintTime = currentTimeMS();
152 void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime(const FontResource* font)
154 if (m_fallbackPaintTime <= 0)
156 int duration = static_cast<int>(currentTimeMS() - m_fallbackPaintTime);
157 blink::Platform::current()->histogramCustomCounts("WebFont.BlankTextShownTime", duration, 0, 10000, 50);
158 m_fallbackPaintTime = -1;
161 void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font)
163 if (m_loadStartTime > 0 && font && !font->isLoading()) {
164 int duration = static_cast<int>(currentTimeMS() - m_loadStartTime);
165 blink::Platform::current()->histogramCustomCounts(histogramName(font), duration, 0, 10000, 50);
166 m_loadStartTime = -1;
168 enum { Miss, Hit, DataUrl, CacheHitEnumMax };
169 int histogramValue = font->url().protocolIsData() ? DataUrl
170 : font->response().wasCached() ? Hit
172 blink::Platform::current()->histogramEnumeration("WebFont.CacheHit", histogramValue, CacheHitEnumMax);
174 enum { CORSFail, CORSSuccess, CORSEnumMax };
175 int corsValue = font->isCORSFailed() ? CORSFail : CORSSuccess;
176 blink::Platform::current()->histogramEnumeration("WebFont.CORSSuccess", corsValue, CORSEnumMax);
180 const char* RemoteFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font)
182 if (font->errorOccurred())
183 return "WebFont.DownloadTime.LoadError";
185 unsigned size = font->encodedSize();
186 if (size < 10 * 1024)
187 return "WebFont.DownloadTime.0.Under10KB";
188 if (size < 50 * 1024)
189 return "WebFont.DownloadTime.1.10KBTo50KB";
190 if (size < 100 * 1024)
191 return "WebFont.DownloadTime.2.50KBTo100KB";
192 if (size < 1024 * 1024)
193 return "WebFont.DownloadTime.3.100KBTo1MB";
194 return "WebFont.DownloadTime.4.Over1MB";