Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / RemoteFontFaceSource.cpp
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 blink {
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 (const auto& item : m_fontDataTable) {
38         SimpleFontData* fontData = item.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         enum { CORSFail, CORSSuccess, CORSEnumMax };
175         int corsValue = font->isCORSFailed() ? CORSFail : CORSSuccess;
176         blink::Platform::current()->histogramEnumeration("WebFont.CORSSuccess", corsValue, CORSEnumMax);
177     }
178 }
179
180 const char* RemoteFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font)
181 {
182     if (font->errorOccurred())
183         return "WebFont.DownloadTime.LoadError";
184
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";
195 }
196
197 } // namespace blink