Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/child/dwrite_font_proxy/dwrite_font_proxy_win.h" | 5 #include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/debug/crash_logging.h" | 12 #include "base/debug/crash_logging.h" |
| 13 #include "base/feature_list.h" | 13 #include "base/feature_list.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 17 #include "base/win/scoped_handle.h" | 17 #include "base/win/scoped_handle.h" |
| 18 #include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h" | 18 #include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h" |
| 19 #include "content/common/dwrite_font_proxy_messages.h" | 19 #include "content/common/dwrite_font_proxy_messages.h" |
| 20 #include "content/public/child/child_thread.h" | 20 #include "content/public/child/child_thread.h" |
| 21 #include "ipc/ipc_platform_file.h" | |
| 21 #include "ipc/ipc_sender.h" | 22 #include "ipc/ipc_sender.h" |
| 22 | 23 |
| 23 namespace mswr = Microsoft::WRL; | 24 namespace mswr = Microsoft::WRL; |
| 24 | 25 |
| 25 namespace content { | 26 namespace content { |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 // This enum is used to define the buckets for an enumerated UMA histogram. | 30 // This enum is used to define the buckets for an enumerated UMA histogram. |
| 30 // Hence, | 31 // Hence, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 44 // Hence, | 45 // Hence, |
| 45 // (a) existing enumerated constants should never be deleted or reordered, and | 46 // (a) existing enumerated constants should never be deleted or reordered, and |
| 46 // (b) new constants should only be appended at the end of the enumeration. | 47 // (b) new constants should only be appended at the end of the enumeration. |
| 47 enum FontProxyError { | 48 enum FontProxyError { |
| 48 FIND_FAMILY_SEND_FAILED = 0, | 49 FIND_FAMILY_SEND_FAILED = 0, |
| 49 GET_FAMILY_COUNT_SEND_FAILED = 1, | 50 GET_FAMILY_COUNT_SEND_FAILED = 1, |
| 50 COLLECTION_KEY_INVALID = 2, | 51 COLLECTION_KEY_INVALID = 2, |
| 51 FAMILY_INDEX_OUT_OF_RANGE = 3, | 52 FAMILY_INDEX_OUT_OF_RANGE = 3, |
| 52 GET_FONT_FILES_SEND_FAILED = 4, | 53 GET_FONT_FILES_SEND_FAILED = 4, |
| 53 MAPPED_FILE_FAILED = 5, | 54 MAPPED_FILE_FAILED = 5, |
| 55 DUPLICATE_HANDLE_FAILED = 6, | |
| 54 | 56 |
| 55 FONT_PROXY_ERROR_MAX_VALUE | 57 FONT_PROXY_ERROR_MAX_VALUE |
| 56 }; | 58 }; |
| 57 | 59 |
| 58 const char kFontKeyName[] = "font_key_name"; | 60 const char kFontKeyName[] = "font_key_name"; |
| 59 | 61 |
| 60 void LogLoadFamilyResult(DirectWriteLoadFamilyResult result) { | 62 void LogLoadFamilyResult(DirectWriteLoadFamilyResult result) { |
| 61 UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoadFamilyResult", result, | 63 UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoadFamilyResult", result, |
| 62 LOAD_FAMILY_MAX_VALUE); | 64 LOAD_FAMILY_MAX_VALUE); |
| 63 } | 65 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 | 187 |
| 186 if (*family_index >= GetFontFamilyCount()) { | 188 if (*family_index >= GetFontFamilyCount()) { |
| 187 LogFontProxyError(FAMILY_INDEX_OUT_OF_RANGE); | 189 LogFontProxyError(FAMILY_INDEX_OUT_OF_RANGE); |
| 188 return E_INVALIDARG; | 190 return E_INVALIDARG; |
| 189 } | 191 } |
| 190 | 192 |
| 191 // If we already loaded the family we should reuse the existing collection. | 193 // If we already loaded the family we should reuse the existing collection. |
| 192 DCHECK(!families_[*family_index]->IsLoaded()); | 194 DCHECK(!families_[*family_index]->IsLoaded()); |
| 193 | 195 |
| 194 std::vector<base::string16> file_names; | 196 std::vector<base::string16> file_names; |
| 195 if (!GetSender()->Send( | 197 std::vector<IPC::PlatformFileForTransit> file_handles; |
| 196 new DWriteFontProxyMsg_GetFontFiles(*family_index, &file_names))) { | 198 if (!GetSender()->Send(new DWriteFontProxyMsg_GetFontFiles( |
| 199 *family_index, &file_names, &file_handles))) { | |
| 197 LogFontProxyError(GET_FONT_FILES_SEND_FAILED); | 200 LogFontProxyError(GET_FONT_FILES_SEND_FAILED); |
| 198 return E_FAIL; | 201 return E_FAIL; |
| 199 } | 202 } |
| 200 | 203 |
| 204 std::vector<HANDLE> handles; | |
| 205 file_handles.reserve(file_names.size() + file_handles.size()); | |
| 206 for (const base::string16& file_name : file_names) { | |
| 207 // This leaks the handles, since they are used as the reference key to | |
| 208 // CreateStreamFromKey, and DirectWrite requires the reference keys to | |
| 209 // remain valid for the lifetime of the loader. The loader is the font | |
| 210 // collection proxy, which remains alive for the lifetime of the renderer. | |
| 211 HANDLE handle = | |
| 212 CreateFile(file_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, | |
| 213 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 214 if (handle != INVALID_HANDLE_VALUE) | |
| 215 handles.push_back(handle); | |
| 216 } | |
| 217 for (const IPC::PlatformFileForTransit& file_handle : file_handles) { | |
| 218 handles.push_back(IPC::PlatformFileForTransitToPlatformFile(file_handle)); | |
| 219 } | |
| 220 | |
| 201 HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>( | 221 HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>( |
| 202 font_file_enumerator, factory, this, &file_names); | 222 font_file_enumerator, factory, this, &handles); |
| 203 | 223 |
| 204 if (!SUCCEEDED(hr)) { | 224 if (!SUCCEEDED(hr)) { |
| 205 DCHECK(false); | 225 DCHECK(false); |
| 206 return E_FAIL; | 226 return E_FAIL; |
| 207 } | 227 } |
| 208 | 228 |
| 209 return S_OK; | 229 return S_OK; |
| 210 } | 230 } |
| 211 | 231 |
| 212 HRESULT DWriteFontCollectionProxy::CreateStreamFromKey( | 232 HRESULT DWriteFontCollectionProxy::CreateStreamFromKey( |
| 213 const void* font_file_reference_key, | 233 const void* font_file_reference_key, |
| 214 UINT32 font_file_reference_key_size, | 234 UINT32 font_file_reference_key_size, |
| 215 IDWriteFontFileStream** font_file_stream) { | 235 IDWriteFontFileStream** font_file_stream) { |
| 216 if (!font_file_reference_key) { | 236 if (font_file_reference_key_size != sizeof(HANDLE)) { |
| 217 return E_FAIL; | |
| 218 } | |
| 219 | |
| 220 const base::char16* file_name = | |
| 221 reinterpret_cast<const base::char16*>(font_file_reference_key); | |
| 222 DCHECK_EQ(font_file_reference_key_size % sizeof(base::char16), 0u); | |
| 223 size_t file_name_size = | |
| 224 static_cast<size_t>(font_file_reference_key_size) / sizeof(base::char16); | |
| 225 | |
| 226 if (file_name_size == 0 || file_name[file_name_size - 1] != L'\0') { | |
| 227 return E_FAIL; | 237 return E_FAIL; |
| 228 } | 238 } |
| 229 | 239 |
| 230 TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey"); | 240 TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey"); |
| 231 | 241 |
| 232 mswr::ComPtr<IDWriteFontFileStream> stream; | 242 HANDLE file_handle = |
| 233 if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name))) { | 243 *reinterpret_cast<const HANDLE*>(font_file_reference_key); |
| 244 | |
| 245 if (file_handle == NULL || file_handle == INVALID_HANDLE_VALUE) { | |
| 234 DCHECK(false); | 246 DCHECK(false); |
| 235 return E_FAIL; | 247 return E_FAIL; |
| 236 } | 248 } |
| 249 | |
| 250 mswr::ComPtr<FontFileStream> stream; | |
| 251 if (!SUCCEEDED( | |
| 252 mswr::MakeAndInitialize<FontFileStream>(&stream, file_handle))) { | |
| 253 DCHECK(false); | |
| 254 return E_FAIL; | |
| 255 } | |
| 237 *font_file_stream = stream.Detach(); | 256 *font_file_stream = stream.Detach(); |
| 238 return S_OK; | 257 return S_OK; |
| 239 } | 258 } |
| 240 | 259 |
| 241 HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize( | 260 HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize( |
| 242 IDWriteFactory* factory, | 261 IDWriteFactory* factory, |
| 243 IPC::Sender* sender_override) { | 262 IPC::Sender* sender_override) { |
| 244 DCHECK(factory); | 263 DCHECK(factory); |
| 245 | 264 |
| 246 factory_ = factory; | 265 factory_ = factory; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 | 523 |
| 505 return SUCCEEDED(hr); | 524 return SUCCEEDED(hr); |
| 506 } | 525 } |
| 507 | 526 |
| 508 FontFileEnumerator::FontFileEnumerator() = default; | 527 FontFileEnumerator::FontFileEnumerator() = default; |
| 509 | 528 |
| 510 FontFileEnumerator::~FontFileEnumerator() = default; | 529 FontFileEnumerator::~FontFileEnumerator() = default; |
| 511 | 530 |
| 512 HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) { | 531 HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) { |
| 513 DCHECK(file); | 532 DCHECK(file); |
| 514 if (current_file_ >= file_names_.size()) { | 533 if (current_file_ >= files_.size()) { |
| 515 return E_FAIL; | 534 return E_FAIL; |
| 516 } | 535 } |
| 517 | 536 |
| 518 TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile"); | 537 TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile"); |
| 538 | |
| 519 // CreateCustomFontFileReference ends up calling | 539 // CreateCustomFontFileReference ends up calling |
| 520 // DWriteFontCollectionProxy::CreateStreamFromKey. | 540 // DWriteFontCollectionProxy::CreateStreamFromKey. |
| 521 HRESULT hr = factory_->CreateCustomFontFileReference( | 541 HRESULT hr = factory_->CreateCustomFontFileReference( |
| 522 reinterpret_cast<const void*>(file_names_[current_file_].c_str()), | 542 reinterpret_cast<const void*>(&files_[current_file_]), |
|
brucedawson
2016/08/02 00:44:47
This cast isn't actually needed, is it? Pointers d
| |
| 523 (file_names_[current_file_].length() + 1) * sizeof(base::char16), | 543 sizeof(files_[current_file_]), loader_.Get() /*IDWriteFontFileLoader*/, |
| 524 loader_.Get() /*IDWriteFontFileLoader*/, file); | 544 file); |
| 525 DCHECK(SUCCEEDED(hr)); | 545 DCHECK(SUCCEEDED(hr)); |
| 526 return hr; | 546 return hr; |
| 527 } | 547 } |
| 528 | 548 |
| 529 HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) { | 549 HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) { |
| 530 DCHECK(has_current_file); | 550 DCHECK(has_current_file); |
| 531 | 551 |
| 532 TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext"); | 552 TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext"); |
| 533 if (next_file_ >= file_names_.size()) { | 553 if (next_file_ >= files_.size()) { |
| 534 *has_current_file = FALSE; | 554 *has_current_file = FALSE; |
| 535 current_file_ = UINT_MAX; | 555 current_file_ = UINT_MAX; |
| 536 return S_OK; | 556 return S_OK; |
| 537 } | 557 } |
| 538 | 558 |
| 539 current_file_ = next_file_; | 559 current_file_ = next_file_; |
| 540 ++next_file_; | 560 ++next_file_; |
| 541 *has_current_file = TRUE; | 561 *has_current_file = TRUE; |
| 542 return S_OK; | 562 return S_OK; |
| 543 } | 563 } |
| 544 | 564 |
| 545 HRESULT FontFileEnumerator::RuntimeClassInitialize( | 565 HRESULT FontFileEnumerator::RuntimeClassInitialize( |
| 546 IDWriteFactory* factory, | 566 IDWriteFactory* factory, |
| 547 IDWriteFontFileLoader* loader, | 567 IDWriteFontFileLoader* loader, |
| 548 std::vector<base::string16>* file_names) { | 568 std::vector<HANDLE>* files) { |
| 549 factory_ = factory; | 569 factory_ = factory; |
| 550 loader_ = loader; | 570 loader_ = loader; |
| 551 file_names_.swap(*file_names); | 571 files_.swap(*files); |
| 552 file_streams_.resize(file_names_.size()); | |
| 553 return S_OK; | 572 return S_OK; |
| 554 } | 573 } |
| 555 | 574 |
| 556 FontFileStream::FontFileStream() = default; | 575 FontFileStream::FontFileStream() = default; |
| 557 | 576 |
| 558 FontFileStream::~FontFileStream() = default; | 577 FontFileStream::~FontFileStream() = default; |
| 559 | 578 |
| 560 HRESULT FontFileStream::GetFileSize(UINT64* file_size) { | 579 HRESULT FontFileStream::GetFileSize(UINT64* file_size) { |
| 561 *file_size = data_.length(); | 580 *file_size = data_.length(); |
| 562 return S_OK; | 581 return S_OK; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 573 void** fragment_context) { | 592 void** fragment_context) { |
| 574 if (fragment_offset + fragment_size < fragment_offset) | 593 if (fragment_offset + fragment_size < fragment_offset) |
| 575 return E_FAIL; | 594 return E_FAIL; |
| 576 if (fragment_offset + fragment_size > data_.length()) | 595 if (fragment_offset + fragment_size > data_.length()) |
| 577 return E_FAIL; | 596 return E_FAIL; |
| 578 *fragment_start = data_.data() + fragment_offset; | 597 *fragment_start = data_.data() + fragment_offset; |
| 579 *fragment_context = nullptr; | 598 *fragment_context = nullptr; |
| 580 return S_OK; | 599 return S_OK; |
| 581 } | 600 } |
| 582 | 601 |
| 583 HRESULT FontFileStream::RuntimeClassInitialize( | 602 HRESULT FontFileStream::RuntimeClassInitialize(HANDLE handle) { |
| 584 const base::string16& file_name) { | 603 // Duplicate the original handle so we can reopen the file after the memory |
| 585 data_.Initialize(base::FilePath(file_name)); | 604 // mapped section closes it. |
| 605 HANDLE duplicate_handle; | |
| 606 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), | |
| 607 &duplicate_handle, 0 /* dwDesiredAccess */, | |
| 608 false /* bInheritHandle */, DUPLICATE_SAME_ACCESS)) { | |
| 609 LogFontProxyError(DUPLICATE_HANDLE_FAILED); | |
| 610 return E_FAIL; | |
| 611 } | |
| 612 | |
| 613 data_.Initialize(base::File(duplicate_handle)); | |
| 586 if (!data_.IsValid()) { | 614 if (!data_.IsValid()) { |
| 587 LogFontProxyError(MAPPED_FILE_FAILED); | 615 LogFontProxyError(MAPPED_FILE_FAILED); |
| 588 return E_FAIL; | 616 return E_FAIL; |
| 589 } | 617 } |
| 590 return S_OK; | 618 return S_OK; |
| 591 } | 619 } |
| 592 | 620 |
| 593 } // namespace content | 621 } // namespace content |
| OLD | NEW |