OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/css/RemoteFontFaceSource.h" | 5 #include "core/css/RemoteFontFaceSource.h" |
6 | 6 |
7 #include "core/css/CSSCustomFontData.h" | 7 #include "core/css/CSSCustomFontData.h" |
8 #include "core/css/CSSFontFace.h" | 8 #include "core/css/CSSFontFace.h" |
9 #include "core/css/CSSFontSelector.h" | 9 #include "core/css/CSSFontSelector.h" |
10 #include "core/dom/Document.h" | 10 #include "core/dom/Document.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 : WebEffectiveConnectionType::TypeSlow2G; | 33 : WebEffectiveConnectionType::TypeSlow2G; |
34 | 34 |
35 return WebEffectiveConnectionType::TypeOffline <= type && type <= thresholdT
ype; | 35 return WebEffectiveConnectionType::TypeOffline <= type && type <= thresholdT
ype; |
36 } | 36 } |
37 | 37 |
38 bool isConnectionTypeSlow() | 38 bool isConnectionTypeSlow() |
39 { | 39 { |
40 return networkStateNotifier().connectionType() == WebConnectionTypeCellular2
G; | 40 return networkStateNotifier().connectionType() == WebConnectionTypeCellular2
G; |
41 } | 41 } |
42 | 42 |
43 bool shouldTriggerWebFontsIntervention(Document* document, FontDisplay display,
bool isLoadedFromMemoryCache, bool isLoadedFromDataURL) | |
44 { | |
45 if (RuntimeEnabledFeatures::webFontsInterventionTriggerEnabled()) | |
46 return true; | |
47 if (isLoadedFromMemoryCache || isLoadedFromDataURL) | |
48 return false; | |
49 | |
50 bool isV2Enabled = RuntimeEnabledFeatures::webFontsInterventionV2With2GEnabl
ed() || RuntimeEnabledFeatures::webFontsInterventionV2WithSlow2GEnabled(); | |
51 | |
52 bool networkIsSlow = isV2Enabled ? isEffectiveConnectionTypeSlowFor(document
) : isConnectionTypeSlow(); | |
53 | |
54 return networkIsSlow && display == FontDisplayAuto; | |
55 } | |
56 | |
57 } // namespace | 43 } // namespace |
58 | 44 |
59 RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, CSSFontSelector*
fontSelector, FontDisplay display) | 45 RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, CSSFontSelector*
fontSelector, FontDisplay display) |
60 : m_font(font) | 46 : m_font(font) |
61 , m_fontSelector(fontSelector) | 47 , m_fontSelector(fontSelector) |
62 , m_display(display) | 48 , m_display(display) |
63 , m_period(display == FontDisplaySwap ? SwapPeriod : BlockPeriod) | 49 , m_period(display == FontDisplaySwap ? SwapPeriod : BlockPeriod) |
| 50 , m_histograms(font->url().protocolIsData() ? FontLoadHistograms::FromDataUR
L : font->isLoaded() ? FontLoadHistograms::FromMemoryCache : FontLoadHistograms:
:FromUnknown) |
64 , m_isInterventionTriggered(false) | 51 , m_isInterventionTriggered(false) |
65 , m_isLoadedFromMemoryCache(font->isLoaded()) | |
66 { | 52 { |
67 ThreadState::current()->registerPreFinalizer(this); | 53 ThreadState::current()->registerPreFinalizer(this); |
68 m_font->addClient(this); | 54 m_font->addClient(this); |
69 | 55 |
70 if (shouldTriggerWebFontsIntervention(m_fontSelector->document(), display, m
_isLoadedFromMemoryCache, m_font->url().protocolIsData())) { | 56 if (shouldTriggerWebFontsIntervention()) { |
71 | |
72 m_isInterventionTriggered = true; | 57 m_isInterventionTriggered = true; |
73 m_period = SwapPeriod; | 58 m_period = SwapPeriod; |
74 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create(Oth
erMessageSource, InfoMessageLevel, "Slow network is detected. Fallback font will
be used while loading: " + m_font->url().elidedString())); | 59 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create(Oth
erMessageSource, InfoMessageLevel, "Slow network is detected. Fallback font will
be used while loading: " + m_font->url().elidedString())); |
75 } | 60 } |
76 } | 61 } |
77 | 62 |
78 RemoteFontFaceSource::~RemoteFontFaceSource() | 63 RemoteFontFaceSource::~RemoteFontFaceSource() |
79 { | 64 { |
80 } | 65 } |
81 | 66 |
(...skipping 27 matching lines...) Expand all Loading... |
109 return m_font->isLoaded(); | 94 return m_font->isLoaded(); |
110 } | 95 } |
111 | 96 |
112 bool RemoteFontFaceSource::isValid() const | 97 bool RemoteFontFaceSource::isValid() const |
113 { | 98 { |
114 return !m_font->errorOccurred(); | 99 return !m_font->errorOccurred(); |
115 } | 100 } |
116 | 101 |
117 void RemoteFontFaceSource::notifyFinished(Resource*) | 102 void RemoteFontFaceSource::notifyFinished(Resource*) |
118 { | 103 { |
119 m_histograms.recordRemoteFont(m_font.get(), m_isLoadedFromMemoryCache); | 104 m_histograms.maySetDataSource(m_font->response().wasCached() ? FontLoadHisto
grams::FromDiskCache : FontLoadHistograms::FromNetwork); |
120 m_histograms.fontLoaded(m_isInterventionTriggered, !m_isLoadedFromMemoryCach
e && !m_font->url().protocolIsData() && !m_font->response().wasCached()); | 105 m_histograms.recordRemoteFont(m_font.get()); |
| 106 m_histograms.fontLoaded(m_isInterventionTriggered); |
121 | 107 |
122 m_font->ensureCustomFontData(); | 108 m_font->ensureCustomFontData(); |
123 // FIXME: Provide more useful message such as OTS rejection reason. | 109 // FIXME: Provide more useful message such as OTS rejection reason. |
124 // See crbug.com/97467 | 110 // See crbug.com/97467 |
125 if (m_font->getStatus() == Resource::DecodeError && m_fontSelector->document
()) { | 111 if (m_font->getStatus() == Resource::DecodeError && m_fontSelector->document
()) { |
126 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create(Oth
erMessageSource, WarningMessageLevel, "Failed to decode downloaded font: " + m_f
ont->url().elidedString())); | 112 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create(Oth
erMessageSource, WarningMessageLevel, "Failed to decode downloaded font: " + m_f
ont->url().elidedString())); |
127 if (m_font->otsParsingMessage().length() > 1) | 113 if (m_font->otsParsingMessage().length() > 1) |
128 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create
(OtherMessageSource, WarningMessageLevel, "OTS parsing error: " + m_font->otsPar
singMessage())); | 114 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create
(OtherMessageSource, WarningMessageLevel, "OTS parsing error: " + m_font->otsPar
singMessage())); |
129 } | 115 } |
130 | 116 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 156 } |
171 | 157 |
172 void RemoteFontFaceSource::switchToFailurePeriod() | 158 void RemoteFontFaceSource::switchToFailurePeriod() |
173 { | 159 { |
174 if (m_period == BlockPeriod) | 160 if (m_period == BlockPeriod) |
175 switchToSwapPeriod(); | 161 switchToSwapPeriod(); |
176 ASSERT(m_period == SwapPeriod); | 162 ASSERT(m_period == SwapPeriod); |
177 m_period = FailurePeriod; | 163 m_period = FailurePeriod; |
178 } | 164 } |
179 | 165 |
| 166 bool RemoteFontFaceSource::shouldTriggerWebFontsIntervention() |
| 167 { |
| 168 if (RuntimeEnabledFeatures::webFontsInterventionTriggerEnabled()) |
| 169 return true; |
| 170 if (m_histograms.dataSource() == FontLoadHistograms::FromMemoryCache || m_hi
stograms.dataSource() == FontLoadHistograms::FromDataURL) |
| 171 return false; |
| 172 |
| 173 bool isV2Enabled = RuntimeEnabledFeatures::webFontsInterventionV2With2GEnabl
ed() || RuntimeEnabledFeatures::webFontsInterventionV2WithSlow2GEnabled(); |
| 174 |
| 175 bool networkIsSlow = isV2Enabled ? isEffectiveConnectionTypeSlowFor(m_fontSe
lector->document()) : isConnectionTypeSlow(); |
| 176 |
| 177 return networkIsSlow && m_display == FontDisplayAuto; |
| 178 } |
| 179 |
| 180 |
180 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescri
ption& fontDescription) | 181 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescri
ption& fontDescription) |
181 { | 182 { |
182 if (!isLoaded()) | 183 if (!isLoaded()) |
183 return createLoadingFallbackFontData(fontDescription); | 184 return createLoadingFallbackFontData(fontDescription); |
184 | 185 |
185 if (!m_font->ensureCustomFontData() || m_period == FailurePeriod) | 186 if (!m_font->ensureCustomFontData() || m_period == FailurePeriod) |
186 return nullptr; | 187 return nullptr; |
187 | 188 |
188 m_histograms.recordFallbackTime(m_font.get()); | 189 m_histograms.recordFallbackTime(m_font.get()); |
189 | 190 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 if (!m_loadStartTime) | 232 if (!m_loadStartTime) |
232 m_loadStartTime = currentTimeMS(); | 233 m_loadStartTime = currentTimeMS(); |
233 } | 234 } |
234 | 235 |
235 void RemoteFontFaceSource::FontLoadHistograms::fallbackFontPainted(DisplayPeriod
period) | 236 void RemoteFontFaceSource::FontLoadHistograms::fallbackFontPainted(DisplayPeriod
period) |
236 { | 237 { |
237 if (period == BlockPeriod && !m_blankPaintTime) | 238 if (period == BlockPeriod && !m_blankPaintTime) |
238 m_blankPaintTime = currentTimeMS(); | 239 m_blankPaintTime = currentTimeMS(); |
239 } | 240 } |
240 | 241 |
241 void RemoteFontFaceSource::FontLoadHistograms::fontLoaded(bool isInterventionTri
ggered, bool isLoadedFromNetwork) | 242 void RemoteFontFaceSource::FontLoadHistograms::fontLoaded(bool isInterventionTri
ggered) |
242 { | 243 { |
243 if (!m_isLongLimitExceeded) | 244 if (!m_isLongLimitExceeded) |
244 recordInterventionResult(isInterventionTriggered, isLoadedFromNetwork); | 245 recordInterventionResult(isInterventionTriggered); |
245 } | 246 } |
246 | 247 |
247 void RemoteFontFaceSource::FontLoadHistograms::longLimitExceeded(bool isInterven
tionTriggered) | 248 void RemoteFontFaceSource::FontLoadHistograms::longLimitExceeded(bool isInterven
tionTriggered) |
248 { | 249 { |
249 m_isLongLimitExceeded = true; | 250 m_isLongLimitExceeded = true; |
250 recordInterventionResult(isInterventionTriggered, true); | 251 if (m_dataSource == FromUnknown) |
| 252 m_dataSource = FromNetwork; |
| 253 recordInterventionResult(isInterventionTriggered); |
251 } | 254 } |
252 | 255 |
253 void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime(const FontReso
urce* font) | 256 void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime(const FontReso
urce* font) |
254 { | 257 { |
255 if (m_blankPaintTime <= 0) | 258 if (m_blankPaintTime <= 0) |
256 return; | 259 return; |
257 int duration = static_cast<int>(currentTimeMS() - m_blankPaintTime); | 260 int duration = static_cast<int>(currentTimeMS() - m_blankPaintTime); |
258 DEFINE_STATIC_LOCAL(CustomCountHistogram, blankTextShownTimeHistogram, ("Web
Font.BlankTextShownTime", 0, 10000, 50)); | 261 DEFINE_STATIC_LOCAL(CustomCountHistogram, blankTextShownTimeHistogram, ("Web
Font.BlankTextShownTime", 0, 10000, 50)); |
259 blankTextShownTimeHistogram.count(duration); | 262 blankTextShownTimeHistogram.count(duration); |
260 m_blankPaintTime = -1; | 263 m_blankPaintTime = -1; |
261 } | 264 } |
262 | 265 |
263 void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResour
ce* font, bool isLoadedFromMemoryCache) | 266 void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResour
ce* font) |
264 { | 267 { |
265 if (m_loadStartTime > 0 && font && !font->isLoading()) { | 268 if (m_loadStartTime > 0 && font && !font->isLoading()) { |
| 269 enum { Miss, DiskHit, DataUrl, MemoryHit, CacheHitEnumMax }; |
| 270 DEFINE_STATIC_LOCAL(EnumerationHistogram, cacheHitHistogram, ("WebFont.C
acheHit", CacheHitEnumMax)); |
| 271 cacheHitHistogram.count(dataSourceMetricsValue()); |
| 272 |
266 int duration = static_cast<int>(currentTimeMS() - m_loadStartTime); | 273 int duration = static_cast<int>(currentTimeMS() - m_loadStartTime); |
267 recordLoadTimeHistogram(font, duration); | 274 recordLoadTimeHistogram(font, duration); |
268 m_loadStartTime = -1; | 275 m_loadStartTime = -1; |
269 | 276 |
270 enum { Miss, DiskHit, DataUrl, MemoryHit, CacheHitEnumMax }; | |
271 int histogramValue = font->url().protocolIsData() ? DataUrl | |
272 : isLoadedFromMemoryCache ? MemoryHit | |
273 : font->response().wasCached() ? DiskHit | |
274 : Miss; | |
275 DEFINE_STATIC_LOCAL(EnumerationHistogram, cacheHitHistogram, ("WebFont.C
acheHit", CacheHitEnumMax)); | |
276 cacheHitHistogram.count(histogramValue); | |
277 | |
278 enum { CORSFail, CORSSuccess, CORSEnumMax }; | 277 enum { CORSFail, CORSSuccess, CORSEnumMax }; |
279 int corsValue = font->isCORSFailed() ? CORSFail : CORSSuccess; | 278 int corsValue = font->isCORSFailed() ? CORSFail : CORSSuccess; |
280 DEFINE_STATIC_LOCAL(EnumerationHistogram, corsHistogram, ("WebFont.CORSS
uccess", CORSEnumMax)); | 279 DEFINE_STATIC_LOCAL(EnumerationHistogram, corsHistogram, ("WebFont.CORSS
uccess", CORSEnumMax)); |
281 corsHistogram.count(corsValue); | 280 corsHistogram.count(corsValue); |
282 } | 281 } |
283 } | 282 } |
284 | 283 |
285 void RemoteFontFaceSource::FontLoadHistograms::recordLoadTimeHistogram(const Fon
tResource* font, int duration) | 284 void RemoteFontFaceSource::FontLoadHistograms::recordLoadTimeHistogram(const Fon
tResource* font, int duration) |
286 { | 285 { |
| 286 CHECK_NE(FromUnknown, m_dataSource); |
| 287 |
287 if (font->errorOccurred()) { | 288 if (font->errorOccurred()) { |
288 DEFINE_STATIC_LOCAL(CustomCountHistogram, loadErrorHistogram, ("WebFont.
DownloadTime.LoadError", 0, 10000, 50)); | 289 DEFINE_STATIC_LOCAL(CustomCountHistogram, loadErrorHistogram, ("WebFont.
DownloadTime.LoadError", 0, 10000, 50)); |
| 290 DEFINE_STATIC_LOCAL(CustomCountHistogram, missedCacheLoadErrorHistogram,
("WebFont.MissedCache.DownloadTime.LoadError", 0, 10000, 50)); |
289 loadErrorHistogram.count(duration); | 291 loadErrorHistogram.count(duration); |
| 292 if (m_dataSource == FromNetwork) |
| 293 missedCacheLoadErrorHistogram.count(duration); |
290 return; | 294 return; |
291 } | 295 } |
292 | 296 |
293 unsigned size = font->encodedSize(); | 297 unsigned size = font->encodedSize(); |
294 if (size < 10 * 1024) { | 298 if (size < 10 * 1024) { |
295 DEFINE_STATIC_LOCAL(CustomCountHistogram, under10kHistogram, ("WebFont.D
ownloadTime.0.Under10KB", 0, 10000, 50)); | 299 DEFINE_STATIC_LOCAL(CustomCountHistogram, under10kHistogram, ("WebFont.D
ownloadTime.0.Under10KB", 0, 10000, 50)); |
| 300 DEFINE_STATIC_LOCAL(CustomCountHistogram, missedCacheUnder10kHistogram,
("WebFont.MissedCache.DownloadTime.0.Under10KB", 0, 10000, 50)); |
296 under10kHistogram.count(duration); | 301 under10kHistogram.count(duration); |
| 302 if (m_dataSource == FromNetwork) |
| 303 missedCacheUnder10kHistogram.count(duration); |
297 return; | 304 return; |
298 } | 305 } |
299 if (size < 50 * 1024) { | 306 if (size < 50 * 1024) { |
300 DEFINE_STATIC_LOCAL(CustomCountHistogram, under50kHistogram, ("WebFont.D
ownloadTime.1.10KBTo50KB", 0, 10000, 50)); | 307 DEFINE_STATIC_LOCAL(CustomCountHistogram, under50kHistogram, ("WebFont.D
ownloadTime.1.10KBTo50KB", 0, 10000, 50)); |
| 308 DEFINE_STATIC_LOCAL(CustomCountHistogram, missedCacheUnder50kHistogram,
("WebFont.MissedCache.DownloadTime.1.10KBTo50KB", 0, 10000, 50)); |
301 under50kHistogram.count(duration); | 309 under50kHistogram.count(duration); |
| 310 if (m_dataSource == FromNetwork) |
| 311 missedCacheUnder50kHistogram.count(duration); |
302 return; | 312 return; |
303 } | 313 } |
304 if (size < 100 * 1024) { | 314 if (size < 100 * 1024) { |
305 DEFINE_STATIC_LOCAL(CustomCountHistogram, under100kHistogram, ("WebFont.
DownloadTime.2.50KBTo100KB", 0, 10000, 50)); | 315 DEFINE_STATIC_LOCAL(CustomCountHistogram, under100kHistogram, ("WebFont.
DownloadTime.2.50KBTo100KB", 0, 10000, 50)); |
| 316 DEFINE_STATIC_LOCAL(CustomCountHistogram, missedCacheUnder100kHistogram,
("WebFont.MissedCache.DownloadTime.2.50KBTo100KB", 0, 10000, 50)); |
306 under100kHistogram.count(duration); | 317 under100kHistogram.count(duration); |
| 318 if (m_dataSource == FromNetwork) |
| 319 missedCacheUnder100kHistogram.count(duration); |
307 return; | 320 return; |
308 } | 321 } |
309 if (size < 1024 * 1024) { | 322 if (size < 1024 * 1024) { |
310 DEFINE_STATIC_LOCAL(CustomCountHistogram, under1mbHistogram, ("WebFont.D
ownloadTime.3.100KBTo1MB", 0, 10000, 50)); | 323 DEFINE_STATIC_LOCAL(CustomCountHistogram, under1mbHistogram, ("WebFont.D
ownloadTime.3.100KBTo1MB", 0, 10000, 50)); |
| 324 DEFINE_STATIC_LOCAL(CustomCountHistogram, missedCacheUnder1mbHistogram,
("WebFont.MissedCache.DownloadTime.3.100KBTo1MB", 0, 10000, 50)); |
311 under1mbHistogram.count(duration); | 325 under1mbHistogram.count(duration); |
| 326 if (m_dataSource == FromNetwork) |
| 327 missedCacheUnder1mbHistogram.count(duration); |
312 return; | 328 return; |
313 } | 329 } |
314 DEFINE_STATIC_LOCAL(CustomCountHistogram, over1mbHistogram, ("WebFont.Downlo
adTime.4.Over1MB", 0, 10000, 50)); | 330 DEFINE_STATIC_LOCAL(CustomCountHistogram, over1mbHistogram, ("WebFont.Downlo
adTime.4.Over1MB", 0, 10000, 50)); |
| 331 DEFINE_STATIC_LOCAL(CustomCountHistogram, missedCacheOver1mbHistogram, ("Web
Font.MissedCache.DownloadTime.4.Over1MB", 0, 10000, 50)); |
315 over1mbHistogram.count(duration); | 332 over1mbHistogram.count(duration); |
| 333 if (m_dataSource == FromNetwork) |
| 334 missedCacheOver1mbHistogram.count(duration); |
316 } | 335 } |
317 | 336 |
318 void RemoteFontFaceSource::FontLoadHistograms::recordInterventionResult(bool isT
riggered, bool isLoadedFromNetwork) | 337 void RemoteFontFaceSource::FontLoadHistograms::recordInterventionResult(bool isT
riggered) |
319 { | 338 { |
| 339 CHECK_NE(FromUnknown, m_dataSource); |
| 340 |
320 // interventionResult takes 0-3 values. | 341 // interventionResult takes 0-3 values. |
321 int interventionResult = 0; | 342 int interventionResult = 0; |
322 if (m_isLongLimitExceeded) | 343 if (m_isLongLimitExceeded) |
323 interventionResult |= 1 << 0; | 344 interventionResult |= 1 << 0; |
324 if (isTriggered) | 345 if (isTriggered) |
325 interventionResult |= 1 << 1; | 346 interventionResult |= 1 << 1; |
326 const int boundary = 1 << 2; | 347 const int boundary = 1 << 2; |
327 | 348 |
328 DEFINE_STATIC_LOCAL(EnumerationHistogram, interventionHistogram, ("WebFont.I
nterventionResult", boundary)); | 349 DEFINE_STATIC_LOCAL(EnumerationHistogram, interventionHistogram, ("WebFont.I
nterventionResult", boundary)); |
329 DEFINE_STATIC_LOCAL(EnumerationHistogram, missedCacheInterventionHistogram,
("WebFont.InterventionResult.MissedCache", boundary)); | 350 DEFINE_STATIC_LOCAL(EnumerationHistogram, missedCacheInterventionHistogram,
("WebFont.InterventionResult.MissedCache", boundary)); |
330 interventionHistogram.count(interventionResult); | 351 interventionHistogram.count(interventionResult); |
331 if (isLoadedFromNetwork) | 352 if (m_dataSource == FromNetwork) |
332 missedCacheInterventionHistogram.count(interventionResult); | 353 missedCacheInterventionHistogram.count(interventionResult); |
333 } | 354 } |
334 | 355 |
| 356 RemoteFontFaceSource::FontLoadHistograms::CacheHitMetrics RemoteFontFaceSource::
FontLoadHistograms::dataSourceMetricsValue() |
| 357 { |
| 358 switch (m_dataSource) { |
| 359 case FromDataURL: |
| 360 return DataUrl; |
| 361 case FromMemoryCache: |
| 362 return MemoryHit; |
| 363 case FromDiskCache: |
| 364 return DiskHit; |
| 365 case FromNetwork: |
| 366 return Miss; |
| 367 case FromUnknown: |
| 368 // Fall through. |
| 369 default: |
| 370 NOTREACHED(); |
| 371 } |
| 372 return Miss; |
| 373 } |
| 374 |
335 } // namespace blink | 375 } // namespace blink |
OLD | NEW |