Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(636)

Side by Side Diff: content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc

Issue 1846433005: Implement direct write fallback proxy (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add a missing SUCCEEDED call Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h" 5 #include "content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h"
6 6
7 #include <dwrite.h> 7 #include <dwrite.h>
8 #include <shlobj.h> 8 #include <shlobj.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <stdint.h> 10 #include <stdint.h>
11 11
12 #include <set> 12 #include <set>
13 #include <utility> 13 #include <utility>
14 14
15 #include "base/callback_helpers.h" 15 #include "base/callback_helpers.h"
16 #include "base/i18n/case_conversion.h" 16 #include "base/i18n/case_conversion.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/metrics/histogram_macros.h" 18 #include "base/metrics/histogram_macros.h"
19 #include "base/strings/string16.h" 19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
22 #include "content/common/dwrite_font_proxy_messages.h" 22 #include "content/common/dwrite_font_proxy_messages.h"
23 #include "content/common/dwrite_text_analysis_source_win.h"
23 #include "ipc/ipc_message_macros.h" 24 #include "ipc/ipc_message_macros.h"
24 #include "ui/gfx/win/direct_write.h" 25 #include "ui/gfx/win/direct_write.h"
25 26
26 namespace mswr = Microsoft::WRL; 27 namespace mswr = Microsoft::WRL;
27 28
28 namespace content { 29 namespace content {
29 30
30 namespace { 31 namespace {
31 32
32 // This enum is used to define the buckets for an enumerated UMA histogram. 33 // This enum is used to define the buckets for an enumerated UMA histogram.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 DWriteFontProxyMessageFilter::~DWriteFontProxyMessageFilter() = default; 84 DWriteFontProxyMessageFilter::~DWriteFontProxyMessageFilter() = default;
84 85
85 bool DWriteFontProxyMessageFilter::OnMessageReceived( 86 bool DWriteFontProxyMessageFilter::OnMessageReceived(
86 const IPC::Message& message) { 87 const IPC::Message& message) {
87 bool handled = true; 88 bool handled = true;
88 IPC_BEGIN_MESSAGE_MAP(DWriteFontProxyMessageFilter, message) 89 IPC_BEGIN_MESSAGE_MAP(DWriteFontProxyMessageFilter, message)
89 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_FindFamily, OnFindFamily) 90 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_FindFamily, OnFindFamily)
90 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyCount, OnGetFamilyCount) 91 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyCount, OnGetFamilyCount)
91 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyNames, OnGetFamilyNames) 92 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyNames, OnGetFamilyNames)
92 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFontFiles, OnGetFontFiles) 93 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFontFiles, OnGetFontFiles)
94 IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_MapCharacters, OnMapCharacters)
93 IPC_MESSAGE_UNHANDLED(handled = false) 95 IPC_MESSAGE_UNHANDLED(handled = false)
94 IPC_END_MESSAGE_MAP() 96 IPC_END_MESSAGE_MAP()
95 return handled; 97 return handled;
96 } 98 }
97 99
98 void DWriteFontProxyMessageFilter::OverrideThreadForMessage( 100 void DWriteFontProxyMessageFilter::OverrideThreadForMessage(
99 const IPC::Message& message, 101 const IPC::Message& message,
100 content::BrowserThread::ID* thread) { 102 content::BrowserThread::ID* thread) {
101 if (IPC_MESSAGE_CLASS(message) == DWriteFontProxyMsgStart) 103 if (IPC_MESSAGE_CLASS(message) == DWriteFontProxyMsgStart)
102 *thread = BrowserThread::FILE; 104 *thread = BrowserThread::FILE;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 InitializeDirectWrite(); 137 InitializeDirectWrite();
136 TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFamilyNames"); 138 TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFamilyNames");
137 DCHECK(collection_); 139 DCHECK(collection_);
138 if (!collection_) 140 if (!collection_)
139 return; 141 return;
140 142
141 TRACE_EVENT0("dwrite", "FontProxyHost::DoGetFamilyNames"); 143 TRACE_EVENT0("dwrite", "FontProxyHost::DoGetFamilyNames");
142 144
143 mswr::ComPtr<IDWriteFontFamily> family; 145 mswr::ComPtr<IDWriteFontFamily> family;
144 HRESULT hr = collection_->GetFontFamily(family_index, &family); 146 HRESULT hr = collection_->GetFontFamily(family_index, &family);
145 if (!SUCCEEDED(hr)) { 147 if (FAILED(hr)) {
146 return; 148 return;
147 } 149 }
148 150
149 mswr::ComPtr<IDWriteLocalizedStrings> localized_names; 151 mswr::ComPtr<IDWriteLocalizedStrings> localized_names;
150 hr = family->GetFamilyNames(&localized_names); 152 hr = family->GetFamilyNames(&localized_names);
151 if (!SUCCEEDED(hr)) { 153 if (FAILED(hr)) {
152 return; 154 return;
153 } 155 }
154 156
155 size_t string_count = localized_names->GetCount(); 157 size_t string_count = localized_names->GetCount();
156 158
157 std::vector<base::char16> locale; 159 std::vector<base::char16> locale;
158 std::vector<base::char16> name; 160 std::vector<base::char16> name;
159 for (size_t index = 0; index < string_count; ++index) { 161 for (size_t index = 0; index < string_count; ++index) {
160 UINT32 length = 0; 162 UINT32 length = 0;
161 hr = localized_names->GetLocaleNameLength(index, &length); 163 hr = localized_names->GetLocaleNameLength(index, &length);
162 if (!SUCCEEDED(hr)) { 164 if (FAILED(hr)) {
163 return; 165 return;
164 } 166 }
165 ++length; // Reserve space for the null terminator. 167 ++length; // Reserve space for the null terminator.
166 locale.resize(length); 168 locale.resize(length);
167 hr = localized_names->GetLocaleName(index, locale.data(), length); 169 hr = localized_names->GetLocaleName(index, locale.data(), length);
168 if (!SUCCEEDED(hr)) { 170 if (FAILED(hr)) {
169 return; 171 return;
170 } 172 }
171 CHECK_EQ(L'\0', locale[length - 1]); 173 CHECK_EQ(L'\0', locale[length - 1]);
172 174
173 length = 0; 175 length = 0;
174 hr = localized_names->GetStringLength(index, &length); 176 hr = localized_names->GetStringLength(index, &length);
175 if (!SUCCEEDED(hr)) { 177 if (FAILED(hr)) {
176 return; 178 return;
177 } 179 }
178 ++length; // Reserve space for the null terminator. 180 ++length; // Reserve space for the null terminator.
179 name.resize(length); 181 name.resize(length);
180 hr = localized_names->GetString(index, name.data(), length); 182 hr = localized_names->GetString(index, name.data(), length);
181 if (!SUCCEEDED(hr)) { 183 if (FAILED(hr)) {
182 return; 184 return;
183 } 185 }
184 CHECK_EQ(L'\0', name[length - 1]); 186 CHECK_EQ(L'\0', name[length - 1]);
185 187
186 // Would be great to use emplace_back instead. 188 // Would be great to use emplace_back instead.
187 family_names->push_back(std::pair<base::string16, base::string16>( 189 family_names->push_back(std::pair<base::string16, base::string16>(
188 base::string16(locale.data()), base::string16(name.data()))); 190 base::string16(locale.data()), base::string16(name.data())));
189 } 191 }
190 } 192 }
191 193
192 void DWriteFontProxyMessageFilter::OnGetFontFiles( 194 void DWriteFontProxyMessageFilter::OnGetFontFiles(
193 uint32_t family_index, 195 uint32_t family_index,
194 std::vector<base::string16>* file_paths) { 196 std::vector<base::string16>* file_paths) {
195 InitializeDirectWrite(); 197 InitializeDirectWrite();
196 TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFontFiles"); 198 TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFontFiles");
197 DCHECK(collection_); 199 DCHECK(collection_);
198 if (!collection_) 200 if (!collection_)
199 return; 201 return;
200 202
201 mswr::ComPtr<IDWriteFontFamily> family; 203 mswr::ComPtr<IDWriteFontFamily> family;
202 HRESULT hr = collection_->GetFontFamily(family_index, &family); 204 HRESULT hr = collection_->GetFontFamily(family_index, &family);
203 if (!SUCCEEDED(hr)) { 205 if (FAILED(hr)) {
204 return; 206 return;
205 } 207 }
206 208
207 UINT32 font_count = family->GetFontCount(); 209 UINT32 font_count = family->GetFontCount();
208 210
209 std::set<base::string16> path_set; 211 std::set<base::string16> path_set;
210 // Iterate through all the fonts in the family, and all the files for those 212 // Iterate through all the fonts in the family, and all the files for those
211 // fonts. If anything goes wrong, bail on the entire family to avoid having 213 // fonts. If anything goes wrong, bail on the entire family to avoid having
212 // a partially-loaded font family. 214 // a partially-loaded font family.
213 for (UINT32 font_index = 0; font_index < font_count; ++font_index) { 215 for (UINT32 font_index = 0; font_index < font_count; ++font_index) {
214 mswr::ComPtr<IDWriteFont> font; 216 mswr::ComPtr<IDWriteFont> font;
215 hr = family->GetFont(font_index, &font); 217 hr = family->GetFont(font_index, &font);
216 if (!SUCCEEDED(hr)) { 218 if (FAILED(hr)) {
217 return; 219 return;
218 } 220 }
219 221
220 AddFilesForFont(&path_set, font.Get()); 222 AddFilesForFont(&path_set, font.Get());
221 } 223 }
222 224
223 file_paths->assign(path_set.begin(), path_set.end()); 225 file_paths->assign(path_set.begin(), path_set.end());
224 } 226 }
225 227
228 void DWriteFontProxyMessageFilter::OnMapCharacters(
229 const base::string16& text,
230 const DWriteFontStyle& font_style,
231 const base::string16& locale_name,
232 uint32_t reading_direction,
233 const base::string16& base_family_name,
234 MapCharactersResult* result) {
235 InitializeDirectWrite();
236 result->family_index = UINT32_MAX;
237 result->mapped_length = text.length();
238 result->family_name.clear();
239 result->scale = 0.0;
240 result->font_style.font_slant = DWRITE_FONT_STYLE_NORMAL;
241 result->font_style.font_stretch = DWRITE_FONT_STRETCH_NORMAL;
242 result->font_style.font_weight = DWRITE_FONT_WEIGHT_NORMAL;
243 if (factory2_ == nullptr || collection_ == nullptr)
244 return;
245 if (font_fallback_ == nullptr) {
246 if (FAILED(factory2_->GetSystemFontFallback(&font_fallback_)))
247 return;
248 }
249
250 UINT32 length;
251 mswr::ComPtr<IDWriteFont> mapped_font;
252
253 mswr::ComPtr<IDWriteNumberSubstitution> number_substitution;
254 if (FAILED(factory2_->CreateNumberSubstitution(
255 DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, locale_name.c_str(),
256 TRUE /* ignoreUserOverride */, &number_substitution))) {
257 DCHECK(false);
258 return;
259 }
260 mswr::ComPtr<IDWriteTextAnalysisSource> analysis_source;
261 if (FAILED(mswr::MakeAndInitialize<TextAnalysisSource>(
262 &analysis_source, text, locale_name, number_substitution.Get(),
263 static_cast<DWRITE_READING_DIRECTION>(reading_direction)))) {
264 DCHECK(false);
265 return;
266 }
267
268 if (FAILED(font_fallback_->MapCharacters(
269 analysis_source.Get(), 0, text.length(), collection_.Get(),
270 base_family_name.c_str(),
271 static_cast<DWRITE_FONT_WEIGHT>(font_style.font_weight),
272 static_cast<DWRITE_FONT_STYLE>(font_style.font_slant),
273 static_cast<DWRITE_FONT_STRETCH>(font_style.font_stretch), &length,
274 &mapped_font, &result->scale))) {
275 DCHECK(false);
276 return;
277 }
278
279 result->mapped_length = length;
280 if (mapped_font == nullptr)
281 return;
282
283 mswr::ComPtr<IDWriteFontFamily> mapped_family;
284 if (FAILED(mapped_font->GetFontFamily(&mapped_family))) {
285 DCHECK(false);
286 return;
287 }
288 mswr::ComPtr<IDWriteLocalizedStrings> family_names;
289 if (FAILED(mapped_family->GetFamilyNames(&family_names))) {
290 DCHECK(false);
291 return;
292 }
293
294 result->font_style.font_slant = mapped_font->GetStyle();
295 result->font_style.font_stretch = mapped_font->GetStretch();
296 result->font_style.font_weight = mapped_font->GetWeight();
297
298 std::vector<base::char16> name;
299 size_t name_count = family_names->GetCount();
300 for (size_t name_index = 0; name_index < name_count; name_index++) {
301 UINT32 name_length = 0;
302 if (FAILED(family_names->GetStringLength(name_index, &name_length)))
303 continue; // Keep trying other names
304
305 ++name_length; // Reserve space for the null terminator.
306 name.resize(name_length);
307 if (FAILED(family_names->GetString(name_index, name.data(), name_length)))
308 continue;
309 UINT32 index = UINT32_MAX;
310 BOOL exists = false;
311 if (FAILED(collection_->FindFamilyName(name.data(), &index, &exists)) ||
312 !exists)
313 continue;
314
315 // Found a matching family!
316 result->family_index = index;
317 result->family_name = name.data();
318 return;
319 }
320 // Could not find a matching family
321 // TODO(kulshin): log UMA that we matched a font, but could not locate the
322 // family
323 DCHECK_EQ(result->family_index, UINT32_MAX);
324 DCHECK_GT(result->mapped_length, 0u);
325 }
326
226 void DWriteFontProxyMessageFilter::InitializeDirectWrite() { 327 void DWriteFontProxyMessageFilter::InitializeDirectWrite() {
227 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 328 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
228 if (direct_write_initialized_) 329 if (direct_write_initialized_)
229 return; 330 return;
230 direct_write_initialized_ = true; 331 direct_write_initialized_ = true;
231 332
232 mswr::ComPtr<IDWriteFactory> factory; 333 mswr::ComPtr<IDWriteFactory> factory;
233 gfx::win::CreateDWriteFactory(&factory); 334 gfx::win::CreateDWriteFactory(&factory);
234 if (factory == nullptr) { 335 if (factory == nullptr) {
235 // We won't be able to load fonts, but we should still return messages so 336 // We won't be able to load fonts, but we should still return messages so
236 // renderers don't hang if they for some reason send us a font message. 337 // renderers don't hang if they for some reason send us a font message.
237 return; 338 return;
238 } 339 }
239 340
341 // QueryInterface for IDWriteFactory2. It's ok for this to fail if we are
342 // running an older version of DirectWrite (earlier than Win8.1).
343 factory.As<IDWriteFactory2>(&factory2_);
344
240 HRESULT hr = factory->GetSystemFontCollection(&collection_); 345 HRESULT hr = factory->GetSystemFontCollection(&collection_);
241 DCHECK(SUCCEEDED(hr)); 346 DCHECK(SUCCEEDED(hr));
242 } 347 }
243 348
244 bool DWriteFontProxyMessageFilter::AddFilesForFont( 349 bool DWriteFontProxyMessageFilter::AddFilesForFont(
245 std::set<base::string16>* path_set, 350 std::set<base::string16>* path_set,
246 IDWriteFont* font) { 351 IDWriteFont* font) {
247 mswr::ComPtr<IDWriteFontFace> font_face; 352 mswr::ComPtr<IDWriteFontFace> font_face;
248 HRESULT hr; 353 HRESULT hr;
249 hr = font->CreateFontFace(&font_face); 354 hr = font->CreateFontFace(&font_face);
250 if (!SUCCEEDED(hr)) { 355 if (FAILED(hr)) {
251 return false; 356 return false;
252 } 357 }
253 358
254 UINT32 file_count; 359 UINT32 file_count;
255 hr = font_face->GetFiles(&file_count, nullptr); 360 hr = font_face->GetFiles(&file_count, nullptr);
256 if (!SUCCEEDED(hr)) { 361 if (FAILED(hr)) {
257 return false; 362 return false;
258 } 363 }
259 364
260 std::vector<mswr::ComPtr<IDWriteFontFile>> font_files; 365 std::vector<mswr::ComPtr<IDWriteFontFile>> font_files;
261 font_files.resize(file_count); 366 font_files.resize(file_count);
262 hr = font_face->GetFiles( 367 hr = font_face->GetFiles(
263 &file_count, reinterpret_cast<IDWriteFontFile**>(font_files.data())); 368 &file_count, reinterpret_cast<IDWriteFontFile**>(font_files.data()));
264 if (!SUCCEEDED(hr)) { 369 if (FAILED(hr)) {
265 return false; 370 return false;
266 } 371 }
267 372
268 for (unsigned int file_index = 0; file_index < file_count; ++file_index) { 373 for (unsigned int file_index = 0; file_index < file_count; ++file_index) {
269 mswr::ComPtr<IDWriteFontFileLoader> loader; 374 mswr::ComPtr<IDWriteFontFileLoader> loader;
270 hr = font_files[file_index]->GetLoader(&loader); 375 hr = font_files[file_index]->GetLoader(&loader);
271 if (!SUCCEEDED(hr)) { 376 if (FAILED(hr)) {
272 return false; 377 return false;
273 } 378 }
274 379
275 mswr::ComPtr<IDWriteLocalFontFileLoader> local_loader; 380 mswr::ComPtr<IDWriteLocalFontFileLoader> local_loader;
276 hr = loader.CopyTo(local_loader.GetAddressOf()); // QueryInterface. 381 hr = loader.CopyTo(local_loader.GetAddressOf()); // QueryInterface.
277 382
278 if (hr == E_NOINTERFACE) { 383 if (hr == E_NOINTERFACE) {
279 // We could get here if the system font collection contains fonts that 384 // We could get here if the system font collection contains fonts that
280 // are backed by something other than files in the system fonts folder. 385 // are backed by something other than files in the system fonts folder.
281 // I don't think that is actually possible, so for now we'll just 386 // I don't think that is actually possible, so for now we'll just
282 // ignore it (result will be that we'll be unable to match any styles 387 // ignore it (result will be that we'll be unable to match any styles
283 // for this font, forcing blink/skia to fall back to whatever font is 388 // for this font, forcing blink/skia to fall back to whatever font is
284 // next). If we get telemetry indicating that this case actually 389 // next). If we get telemetry indicating that this case actually
285 // happens, we can implement this by exposing the loader via ipc. That 390 // happens, we can implement this by exposing the loader via ipc. That
286 // will likely be by loading the font data into shared memory, although 391 // will likely be by loading the font data into shared memory, although
287 // we could proxy the stream reads directly instead. 392 // we could proxy the stream reads directly instead.
288 LogLoaderType(OTHER_LOADER); 393 LogLoaderType(OTHER_LOADER);
289 DCHECK(false); 394 DCHECK(false);
290 395
291 return false; 396 return false;
292 } else if (!SUCCEEDED(hr)) { 397 } else if (FAILED(hr)) {
293 return false; 398 return false;
294 } 399 }
295 400
296 if (!AddLocalFile(path_set, local_loader.Get(), 401 if (!AddLocalFile(path_set, local_loader.Get(),
297 font_files[file_index].Get())) { 402 font_files[file_index].Get())) {
298 return false; 403 return false;
299 } 404 }
300 } 405 }
301 return true; 406 return true;
302 } 407 }
303 408
304 bool DWriteFontProxyMessageFilter::AddLocalFile( 409 bool DWriteFontProxyMessageFilter::AddLocalFile(
305 std::set<base::string16>* path_set, 410 std::set<base::string16>* path_set,
306 IDWriteLocalFontFileLoader* local_loader, 411 IDWriteLocalFontFileLoader* local_loader,
307 IDWriteFontFile* font_file) { 412 IDWriteFontFile* font_file) {
308 HRESULT hr; 413 HRESULT hr;
309 const void* key; 414 const void* key;
310 UINT32 key_size; 415 UINT32 key_size;
311 hr = font_file->GetReferenceKey(&key, &key_size); 416 hr = font_file->GetReferenceKey(&key, &key_size);
312 if (!SUCCEEDED(hr)) { 417 if (FAILED(hr)) {
313 return false; 418 return false;
314 } 419 }
315 420
316 UINT32 path_length = 0; 421 UINT32 path_length = 0;
317 hr = local_loader->GetFilePathLengthFromKey(key, key_size, &path_length); 422 hr = local_loader->GetFilePathLengthFromKey(key, key_size, &path_length);
318 if (!SUCCEEDED(hr)) { 423 if (FAILED(hr)) {
319 return false; 424 return false;
320 } 425 }
321 ++path_length; // Reserve space for the null terminator. 426 ++path_length; // Reserve space for the null terminator.
322 std::vector<base::char16> file_path_chars; 427 std::vector<base::char16> file_path_chars;
323 file_path_chars.resize(path_length); 428 file_path_chars.resize(path_length);
324 hr = local_loader->GetFilePathFromKey(key, key_size, file_path_chars.data(), 429 hr = local_loader->GetFilePathFromKey(key, key_size, file_path_chars.data(),
325 path_length); 430 path_length);
326 if (!SUCCEEDED(hr)) { 431 if (FAILED(hr)) {
327 return false; 432 return false;
328 } 433 }
329 434
330 base::string16 file_path = base::i18n::FoldCase(file_path_chars.data()); 435 base::string16 file_path = base::i18n::FoldCase(file_path_chars.data());
331 if (!base::StartsWith(file_path, windows_fonts_path_, 436 if (!base::StartsWith(file_path, windows_fonts_path_,
332 base::CompareCase::SENSITIVE)) { 437 base::CompareCase::SENSITIVE)) {
333 // Skip loading fonts from outside the system fonts directory, since 438 // Skip loading fonts from outside the system fonts directory, since
334 // these families will not be accessible to the renderer process. If 439 // these families will not be accessible to the renderer process. If
335 // this turns out to be a common case, we can either grant the renderer 440 // this turns out to be a common case, we can either grant the renderer
336 // access to these files (not sure if this is actually possible), or 441 // access to these files (not sure if this is actually possible), or
(...skipping 23 matching lines...) Expand all
360 return true; 465 return true;
361 } 466 }
362 } 467 }
363 468
364 LogLoaderType(FILE_SYSTEM_FONT_DIR); 469 LogLoaderType(FILE_SYSTEM_FONT_DIR);
365 path_set->insert(file_path); 470 path_set->insert(file_path);
366 return true; 471 return true;
367 } 472 }
368 473
369 } // namespace content 474 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698