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. 4 5 #include "config.h" 6 #include "core/css/RemoteFontFaceSource.h" 7 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" 16 17 namespace WebCore { 18 19 RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, PassRefPtrWillBeRawPtr<FontLoader> fontLoader) 20 : m_font(font) 21 , m_fontLoader(fontLoader) 22 { 23 m_font->addClient(this); 24 } 25 26 RemoteFontFaceSource::~RemoteFontFaceSource() 27 { 28 m_font->removeClient(this); 29 pruneTable(); 30 } 31 32 void RemoteFontFaceSource::pruneTable() 33 { 34 if (m_fontDataTable.isEmpty()) 35 return; 36 37 for (FontDataTable::iterator it = m_fontDataTable.begin(); it != m_fontDataTable.end(); ++it) { 38 SimpleFontData* fontData = it->value.get(); 39 if (fontData && fontData->customFontData()) 40 fontData->customFontData()->clearFontFaceSource(); 41 } 42 m_fontDataTable.clear(); 43 } 44 45 bool RemoteFontFaceSource::isLoading() const 46 { 47 return !m_font->stillNeedsLoad() && !m_font->isLoaded(); 48 } 49 50 bool RemoteFontFaceSource::isLoaded() const 51 { 52 return m_font->isLoaded(); 53 } 54 55 bool RemoteFontFaceSource::isValid() const 56 { 57 return !m_font->errorOccurred(); 58 } 59 60 void RemoteFontFaceSource::didStartFontLoad(FontResource*) 61 { 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(); 66 } 67 68 void RemoteFontFaceSource::fontLoaded(FontResource*) 69 { 70 m_histograms.recordRemoteFont(m_font.get()); 71 72 pruneTable(); 73 if (m_face) { 74 m_fontLoader->fontFaceInvalidated(); 75 m_face->fontLoaded(this); 76 } 77 } 78 79 void RemoteFontFaceSource::fontLoadWaitLimitExceeded(FontResource*) 80 { 81 pruneTable(); 82 if (m_face) { 83 m_fontLoader->fontFaceInvalidated(); 84 m_face->fontLoadWaitLimitExceeded(this); 85 } 86 87 m_histograms.recordFallbackTime(m_font.get()); 88 } 89 90 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescription& fontDescription) 91 { 92 if (!isLoaded()) 93 return createLoadingFallbackFontData(fontDescription); 94 95 // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. 96 if (!m_font->ensureCustomFontData()) 97 return nullptr; 98 99 m_histograms.recordFallbackTime(m_font.get()); 100 101 return SimpleFontData::create( 102 m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(), 103 fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(), 104 fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create()); 105 } 106 107 PassRefPtr<SimpleFontData> RemoteFontFaceSource::createLoadingFallbackFontData(const FontDescription& fontDescription) 108 { 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(); 114 return nullptr; 115 } 116 RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(this, m_font->exceedsFontLoadWaitLimit() ? CSSCustomFontData::VisibleFallback : CSSCustomFontData::InvisibleFallback); 117 return SimpleFontData::create(temporaryFont->platformData(), cssFontData); 118 } 119 120 void RemoteFontFaceSource::beginLoadIfNeeded() 121 { 122 if (m_font->stillNeedsLoad()) 123 m_fontLoader->addFontToBeginLoading(m_font.get()); 124 125 if (m_face) 126 m_face->didBeginLoad(); 127 } 128 129 bool RemoteFontFaceSource::ensureFontData() 130 { 131 return m_font->ensureCustomFontData(); 132 } 133 134 void RemoteFontFaceSource::trace(Visitor* visitor) 135 { 136 visitor->trace(m_fontLoader); 137 CSSFontFaceSource::trace(visitor); 138 } 139 140 void RemoteFontFaceSource::FontLoadHistograms::loadStarted() 141 { 142 if (!m_loadStartTime) 143 m_loadStartTime = currentTimeMS(); 144 } 145 146 void RemoteFontFaceSource::FontLoadHistograms::fallbackFontPainted() 147 { 148 if (!m_fallbackPaintTime) 149 m_fallbackPaintTime = currentTimeMS(); 150 } 151 152 void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime(const FontResource* font) 153 { 154 if (m_fallbackPaintTime <= 0) 155 return; 156 int duration = static_cast<int>(currentTimeMS() - m_fallbackPaintTime); 157 blink::Platform::current()->histogramCustomCounts("WebFont.BlankTextShownTime", duration, 0, 10000, 50); 158 m_fallbackPaintTime = -1; 159 } 160 161 void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font) 162 { 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; 167 168 enum { Miss, Hit, DataUrl, CacheHitEnumMax }; 169 int histogramValue = font->url().protocolIsData() ? DataUrl 170 : font->response().wasCached() ? Hit 171 : Miss; 172 blink::Platform::current()->histogramEnumeration("WebFont.CacheHit", histogramValue, CacheHitEnumMax); 173 } 174 } 175 176 const char* RemoteFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font) 177 { 178 if (font->errorOccurred()) 179 return "WebFont.DownloadTime.LoadError"; 180 181 unsigned size = font->encodedSize(); 182 if (size < 10 * 1024) 183 return "WebFont.DownloadTime.0.Under10KB"; 184 if (size < 50 * 1024) 185 return "WebFont.DownloadTime.1.10KBTo50KB"; 186 if (size < 100 * 1024) 187 return "WebFont.DownloadTime.2.50KBTo100KB"; 188 if (size < 1024 * 1024) 189 return "WebFont.DownloadTime.3.100KBTo1MB"; 190 return "WebFont.DownloadTime.4.Over1MB"; 191 } 192 193 } // namespace WebCore 194