Chromium Code Reviews| 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" |
| 11 #include "core/inspector/ConsoleMessage.h" | 11 #include "core/inspector/ConsoleMessage.h" |
| 12 #include "core/loader/FrameLoaderClient.h" | 12 #include "core/loader/FrameLoaderClient.h" |
| 13 #include "core/page/NetworkStateNotifier.h" | 13 #include "core/page/NetworkStateNotifier.h" |
| 14 #include "platform/Histogram.h" | 14 #include "platform/Histogram.h" |
| 15 #include "platform/RuntimeEnabledFeatures.h" | 15 #include "platform/RuntimeEnabledFeatures.h" |
| 16 #include "platform/fonts/FontCache.h" | 16 #include "platform/fonts/FontCache.h" |
| 17 #include "platform/fonts/FontCustomPlatformData.h" | |
| 17 #include "platform/fonts/FontDescription.h" | 18 #include "platform/fonts/FontDescription.h" |
| 18 #include "platform/fonts/SimpleFontData.h" | 19 #include "platform/fonts/SimpleFontData.h" |
| 19 #include "platform/loader/fetch/ResourceFetcher.h" | 20 #include "platform/loader/fetch/ResourceFetcher.h" |
| 20 #include "platform/network/ResourceLoadPriority.h" | 21 #include "platform/network/ResourceLoadPriority.h" |
| 21 #include "public/platform/WebEffectiveConnectionType.h" | 22 #include "public/platform/WebEffectiveConnectionType.h" |
| 22 #include "wtf/CurrentTime.h" | 23 #include "wtf/CurrentTime.h" |
| 23 | 24 |
| 24 namespace blink { | 25 namespace blink { |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create( | 73 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create( |
| 73 OtherMessageSource, InfoMessageLevel, | 74 OtherMessageSource, InfoMessageLevel, |
| 74 "Slow network is detected. Fallback font will be used while loading: " + | 75 "Slow network is detected. Fallback font will be used while loading: " + |
| 75 m_font->url().elidedString())); | 76 m_font->url().elidedString())); |
| 76 } | 77 } |
| 77 } | 78 } |
| 78 | 79 |
| 79 RemoteFontFaceSource::~RemoteFontFaceSource() {} | 80 RemoteFontFaceSource::~RemoteFontFaceSource() {} |
| 80 | 81 |
| 81 void RemoteFontFaceSource::dispose() { | 82 void RemoteFontFaceSource::dispose() { |
| 82 m_font->removeClient(this); | 83 if (m_font) { |
| 83 m_font = nullptr; | 84 m_font->removeClient(this); |
| 85 m_font = nullptr; | |
| 86 } | |
| 84 pruneTable(); | 87 pruneTable(); |
| 85 } | 88 } |
| 86 | 89 |
| 87 void RemoteFontFaceSource::pruneTable() { | 90 void RemoteFontFaceSource::pruneTable() { |
| 88 if (m_fontDataTable.isEmpty()) | 91 if (m_fontDataTable.isEmpty()) |
| 89 return; | 92 return; |
| 90 | 93 |
| 91 for (const auto& item : m_fontDataTable) { | 94 for (const auto& item : m_fontDataTable) { |
| 92 SimpleFontData* fontData = item.value.get(); | 95 SimpleFontData* fontData = item.value.get(); |
| 93 if (fontData && fontData->customFontData()) | 96 if (fontData && fontData->customFontData()) |
| 94 fontData->customFontData()->clearFontFaceSource(); | 97 fontData->customFontData()->clearFontFaceSource(); |
| 95 } | 98 } |
| 96 m_fontDataTable.clear(); | 99 m_fontDataTable.clear(); |
| 97 } | 100 } |
| 98 | 101 |
| 99 bool RemoteFontFaceSource::isLoading() const { | 102 bool RemoteFontFaceSource::isLoading() const { |
| 100 return m_font->isLoading(); | 103 return m_font && m_font->isLoading(); |
| 101 } | 104 } |
| 102 | 105 |
| 103 bool RemoteFontFaceSource::isLoaded() const { | 106 bool RemoteFontFaceSource::isLoaded() const { |
| 104 return m_font->isLoaded(); | 107 return !m_font; |
| 105 } | 108 } |
| 106 | 109 |
| 107 bool RemoteFontFaceSource::isValid() const { | 110 bool RemoteFontFaceSource::isValid() const { |
| 108 return !m_font->errorOccurred(); | 111 return m_font || m_customFontData; |
| 109 } | 112 } |
| 110 | 113 |
| 111 void RemoteFontFaceSource::notifyFinished(Resource*) { | 114 void RemoteFontFaceSource::notifyFinished(Resource* unusedResource) { |
| 115 DCHECK_EQ(unusedResource, m_font); | |
| 112 m_histograms.maySetDataSource(m_font->response().wasCached() | 116 m_histograms.maySetDataSource(m_font->response().wasCached() |
| 113 ? FontLoadHistograms::FromDiskCache | 117 ? FontLoadHistograms::FromDiskCache |
| 114 : FontLoadHistograms::FromNetwork); | 118 : FontLoadHistograms::FromNetwork); |
| 115 m_histograms.recordRemoteFont(m_font.get(), m_isInterventionTriggered); | 119 m_histograms.recordRemoteFont(m_font.get(), m_isInterventionTriggered); |
| 116 m_histograms.fontLoaded(m_font->isCORSFailed(), | 120 m_histograms.fontLoaded(m_font->isCORSFailed(), |
| 117 m_font->getStatus() == ResourceStatus::LoadError, | 121 m_font->getStatus() == ResourceStatus::LoadError, |
| 118 m_isInterventionTriggered); | 122 m_isInterventionTriggered); |
| 119 | 123 |
| 120 m_font->ensureCustomFontData(); | 124 m_customFontData = m_font->getCustomFontData(); |
| 125 | |
| 121 // FIXME: Provide more useful message such as OTS rejection reason. | 126 // FIXME: Provide more useful message such as OTS rejection reason. |
| 122 // See crbug.com/97467 | 127 // See crbug.com/97467 |
| 123 if (m_font->getStatus() == ResourceStatus::DecodeError && | 128 if (m_font->getStatus() == ResourceStatus::DecodeError && |
| 124 m_fontSelector->document()) { | 129 m_fontSelector->document()) { |
| 125 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create( | 130 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create( |
| 126 OtherMessageSource, WarningMessageLevel, | 131 OtherMessageSource, WarningMessageLevel, |
| 127 "Failed to decode downloaded font: " + m_font->url().elidedString())); | 132 "Failed to decode downloaded font: " + m_font->url().elidedString())); |
| 128 if (m_font->otsParsingMessage().length() > 1) | 133 if (m_font->otsParsingMessage().length() > 1) |
| 129 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create( | 134 m_fontSelector->document()->addConsoleMessage(ConsoleMessage::create( |
| 130 OtherMessageSource, WarningMessageLevel, | 135 OtherMessageSource, WarningMessageLevel, |
| 131 "OTS parsing error: " + m_font->otsParsingMessage())); | 136 "OTS parsing error: " + m_font->otsParsingMessage())); |
| 132 } | 137 } |
| 133 | 138 |
| 139 m_font->removeClient(this); | |
| 140 m_font = nullptr; | |
|
hiroshige
2017/02/28 00:18:28
I love clearing |m_font| here, but clearing |m_fon
Kunihiko Sakamoto
2017/02/28 04:04:02
Good point.
For @font-face fonts, CSSFontFaceSrcV
Takashi Toyoshima
2017/03/01 06:44:07
https://www.chromestatus.com/metrics/feature/popul
| |
| 141 | |
| 134 pruneTable(); | 142 pruneTable(); |
| 135 if (m_face) { | 143 if (m_face) { |
| 136 m_fontSelector->fontFaceInvalidated(); | 144 m_fontSelector->fontFaceInvalidated(); |
| 137 m_face->fontLoaded(this); | 145 m_face->fontLoaded(this); |
| 138 } | 146 } |
| 139 } | 147 } |
| 140 | 148 |
| 141 void RemoteFontFaceSource::fontLoadShortLimitExceeded(FontResource*) { | 149 void RemoteFontFaceSource::fontLoadShortLimitExceeded(FontResource*) { |
| 142 if (m_font->isLoaded()) | 150 if (isLoaded()) |
| 143 return; | 151 return; |
| 144 | 152 |
| 145 if (m_display == FontDisplayFallback) | 153 if (m_display == FontDisplayFallback) |
| 146 switchToSwapPeriod(); | 154 switchToSwapPeriod(); |
| 147 else if (m_display == FontDisplayOptional) | 155 else if (m_display == FontDisplayOptional) |
| 148 switchToFailurePeriod(); | 156 switchToFailurePeriod(); |
| 149 } | 157 } |
| 150 | 158 |
| 151 void RemoteFontFaceSource::fontLoadLongLimitExceeded(FontResource*) { | 159 void RemoteFontFaceSource::fontLoadLongLimitExceeded(FontResource*) { |
| 152 if (m_font->isLoaded()) | 160 if (isLoaded()) |
| 153 return; | 161 return; |
| 154 | 162 |
| 155 if (m_display == FontDisplayBlock || | 163 if (m_display == FontDisplayBlock || |
| 156 (!m_isInterventionTriggered && m_display == FontDisplayAuto)) | 164 (!m_isInterventionTriggered && m_display == FontDisplayAuto)) |
| 157 switchToSwapPeriod(); | 165 switchToSwapPeriod(); |
| 158 else if (m_display == FontDisplayFallback) | 166 else if (m_display == FontDisplayFallback) |
| 159 switchToFailurePeriod(); | 167 switchToFailurePeriod(); |
| 160 | 168 |
| 161 m_histograms.longLimitExceeded(m_isInterventionTriggered); | 169 m_histograms.longLimitExceeded(m_isInterventionTriggered); |
| 162 } | 170 } |
| 163 | 171 |
| 164 void RemoteFontFaceSource::switchToSwapPeriod() { | 172 void RemoteFontFaceSource::switchToSwapPeriod() { |
| 165 ASSERT(m_period == BlockPeriod); | 173 ASSERT(m_period == BlockPeriod); |
| 166 m_period = SwapPeriod; | 174 m_period = SwapPeriod; |
| 167 | 175 |
| 168 pruneTable(); | 176 pruneTable(); |
| 169 if (m_face) { | 177 if (m_face) { |
| 170 m_fontSelector->fontFaceInvalidated(); | 178 m_fontSelector->fontFaceInvalidated(); |
| 171 m_face->didBecomeVisibleFallback(this); | 179 m_face->didBecomeVisibleFallback(this); |
| 172 } | 180 } |
| 173 | 181 |
| 174 m_histograms.recordFallbackTime(m_font.get()); | 182 m_histograms.recordFallbackTime(); |
| 175 } | 183 } |
| 176 | 184 |
| 177 void RemoteFontFaceSource::switchToFailurePeriod() { | 185 void RemoteFontFaceSource::switchToFailurePeriod() { |
| 178 if (m_period == BlockPeriod) | 186 if (m_period == BlockPeriod) |
| 179 switchToSwapPeriod(); | 187 switchToSwapPeriod(); |
| 180 ASSERT(m_period == SwapPeriod); | 188 ASSERT(m_period == SwapPeriod); |
| 181 m_period = FailurePeriod; | 189 m_period = FailurePeriod; |
| 182 } | 190 } |
| 183 | 191 |
| 184 bool RemoteFontFaceSource::shouldTriggerWebFontsIntervention() { | 192 bool RemoteFontFaceSource::shouldTriggerWebFontsIntervention() { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 199 | 207 |
| 200 return networkIsSlow && m_display == FontDisplayAuto; | 208 return networkIsSlow && m_display == FontDisplayAuto; |
| 201 } | 209 } |
| 202 | 210 |
| 203 bool RemoteFontFaceSource::isLowPriorityLoadingAllowedForRemoteFont() const { | 211 bool RemoteFontFaceSource::isLowPriorityLoadingAllowedForRemoteFont() const { |
| 204 return m_isInterventionTriggered; | 212 return m_isInterventionTriggered; |
| 205 } | 213 } |
| 206 | 214 |
| 207 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData( | 215 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData( |
| 208 const FontDescription& fontDescription) { | 216 const FontDescription& fontDescription) { |
| 217 if (m_period == FailurePeriod || !isValid()) | |
| 218 return nullptr; | |
| 209 if (!isLoaded()) | 219 if (!isLoaded()) |
| 210 return createLoadingFallbackFontData(fontDescription); | 220 return createLoadingFallbackFontData(fontDescription); |
| 221 DCHECK(m_customFontData); | |
| 211 | 222 |
| 212 if (!m_font->ensureCustomFontData() || m_period == FailurePeriod) | 223 m_histograms.recordFallbackTime(); |
| 213 return nullptr; | |
| 214 | |
| 215 m_histograms.recordFallbackTime(m_font.get()); | |
| 216 | 224 |
| 217 return SimpleFontData::create( | 225 return SimpleFontData::create( |
| 218 m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(), | 226 m_customFontData->fontPlatformData(fontDescription.effectiveFontSize(), |
| 219 fontDescription.isSyntheticBold(), | 227 fontDescription.isSyntheticBold(), |
| 220 fontDescription.isSyntheticItalic(), | 228 fontDescription.isSyntheticItalic(), |
| 221 fontDescription.orientation(), | 229 fontDescription.orientation(), |
| 222 fontDescription.variationSettings()), | 230 fontDescription.variationSettings()), |
| 223 CustomFontData::create()); | 231 CustomFontData::create()); |
| 224 } | 232 } |
| 225 | 233 |
| 226 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createLoadingFallbackFontData( | 234 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createLoadingFallbackFontData( |
| 227 const FontDescription& fontDescription) { | 235 const FontDescription& fontDescription) { |
| 228 // This temporary font is not retained and should not be returned. | 236 // This temporary font is not retained and should not be returned. |
| 229 FontCachePurgePreventer fontCachePurgePreventer; | 237 FontCachePurgePreventer fontCachePurgePreventer; |
| 230 SimpleFontData* temporaryFont = | 238 SimpleFontData* temporaryFont = |
| 231 FontCache::fontCache()->getNonRetainedLastResortFallbackFont( | 239 FontCache::fontCache()->getNonRetainedLastResortFallbackFont( |
| 232 fontDescription); | 240 fontDescription); |
| 233 if (!temporaryFont) { | 241 if (!temporaryFont) { |
| 234 ASSERT_NOT_REACHED(); | 242 ASSERT_NOT_REACHED(); |
| 235 return nullptr; | 243 return nullptr; |
| 236 } | 244 } |
| 237 RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create( | 245 RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create( |
| 238 this, m_period == BlockPeriod ? CSSCustomFontData::InvisibleFallback | 246 this, m_period == BlockPeriod ? CSSCustomFontData::InvisibleFallback |
| 239 : CSSCustomFontData::VisibleFallback); | 247 : CSSCustomFontData::VisibleFallback); |
| 240 return SimpleFontData::create(temporaryFont->platformData(), cssFontData); | 248 return SimpleFontData::create(temporaryFont->platformData(), cssFontData); |
| 241 } | 249 } |
| 242 | 250 |
| 243 void RemoteFontFaceSource::beginLoadIfNeeded() { | 251 void RemoteFontFaceSource::beginLoadIfNeeded() { |
| 252 if (isLoaded()) | |
|
Takashi Toyoshima
2017/02/27 12:56:02
Does this short-circuit affect our metrics?
Kunihiko Sakamoto
2017/02/28 04:04:01
You mean m_histograms.loadStarted() at line 268? T
Takashi Toyoshima
2017/03/01 06:44:07
I see. Thanks!
| |
| 253 return; | |
| 254 DCHECK(m_font); | |
| 255 | |
| 244 if (m_fontSelector->document() && m_font->stillNeedsLoad()) { | 256 if (m_fontSelector->document() && m_font->stillNeedsLoad()) { |
| 245 if (!m_font->url().protocolIsData() && !m_font->isLoaded() && | 257 if (!m_font->url().protocolIsData() && !m_font->isLoaded() && |
| 246 m_display == FontDisplayAuto && | 258 m_display == FontDisplayAuto && |
| 247 m_font->isLowPriorityLoadingAllowedForRemoteFont()) { | 259 m_font->isLowPriorityLoadingAllowedForRemoteFont()) { |
| 248 // Set the loading priority to VeryLow since this font is not required | 260 // Set the loading priority to VeryLow since this font is not required |
| 249 // for painting the text. | 261 // for painting the text. |
| 250 m_font->didChangePriority(ResourceLoadPriorityVeryLow, 0); | 262 m_font->didChangePriority(ResourceLoadPriorityVeryLow, 0); |
| 251 } | 263 } |
| 252 if (m_fontSelector->document()->fetcher()->startLoad(m_font)) { | 264 if (m_fontSelector->document()->fetcher()->startLoad(m_font)) { |
| 253 // Start timers only when load is actually started asynchronously. | 265 // Start timers only when load is actually started asynchronously. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 } | 302 } |
| 291 | 303 |
| 292 void RemoteFontFaceSource::FontLoadHistograms::longLimitExceeded( | 304 void RemoteFontFaceSource::FontLoadHistograms::longLimitExceeded( |
| 293 bool isInterventionTriggered) { | 305 bool isInterventionTriggered) { |
| 294 m_isLongLimitExceeded = true; | 306 m_isLongLimitExceeded = true; |
| 295 maySetDataSource(FromNetwork); | 307 maySetDataSource(FromNetwork); |
| 296 if (m_fontDisplay == FontDisplayAuto) | 308 if (m_fontDisplay == FontDisplayAuto) |
| 297 recordInterventionResult(isInterventionTriggered); | 309 recordInterventionResult(isInterventionTriggered); |
| 298 } | 310 } |
| 299 | 311 |
| 300 void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime( | 312 void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime() { |
| 301 const FontResource* font) { | |
| 302 if (m_blankPaintTime <= 0) | 313 if (m_blankPaintTime <= 0) |
| 303 return; | 314 return; |
| 304 int duration = static_cast<int>(currentTimeMS() - m_blankPaintTime); | 315 int duration = static_cast<int>(currentTimeMS() - m_blankPaintTime); |
| 305 DEFINE_STATIC_LOCAL(CustomCountHistogram, blankTextShownTimeHistogram, | 316 DEFINE_STATIC_LOCAL(CustomCountHistogram, blankTextShownTimeHistogram, |
| 306 ("WebFont.BlankTextShownTime", 0, 10000, 50)); | 317 ("WebFont.BlankTextShownTime", 0, 10000, 50)); |
| 307 blankTextShownTimeHistogram.count(duration); | 318 blankTextShownTimeHistogram.count(duration); |
| 308 m_blankPaintTime = -1; | 319 m_blankPaintTime = -1; |
| 309 } | 320 } |
| 310 | 321 |
| 311 void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont( | 322 void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont( |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 466 return Miss; | 477 return Miss; |
| 467 case FromUnknown: | 478 case FromUnknown: |
| 468 // Fall through. | 479 // Fall through. |
| 469 default: | 480 default: |
| 470 NOTREACHED(); | 481 NOTREACHED(); |
| 471 } | 482 } |
| 472 return Miss; | 483 return Miss; |
| 473 } | 484 } |
| 474 | 485 |
| 475 } // namespace blink | 486 } // namespace blink |
| OLD | NEW |