| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 reinterpret_cast<const uint32_t*>(collection_key); | 156 reinterpret_cast<const uint32_t*>(collection_key); |
| 156 | 157 |
| 157 if (*family_index >= GetFontFamilyCount()) { | 158 if (*family_index >= GetFontFamilyCount()) { |
| 158 return E_INVALIDARG; | 159 return E_INVALIDARG; |
| 159 } | 160 } |
| 160 | 161 |
| 161 // If we already loaded the family we should reuse the existing collection. | 162 // If we already loaded the family we should reuse the existing collection. |
| 162 DCHECK(!families_[*family_index]->IsLoaded()); | 163 DCHECK(!families_[*family_index]->IsLoaded()); |
| 163 | 164 |
| 164 std::vector<base::string16> file_names; | 165 std::vector<base::string16> file_names; |
| 165 if (!GetSender()->Send( | 166 std::vector<IPC::PlatformFileForTransit> file_handles; |
| 166 new DWriteFontProxyMsg_GetFontFiles(*family_index, &file_names))) { | 167 if (!GetSender()->Send(new DWriteFontProxyMsg_GetFontFiles( |
| 168 *family_index, &file_names, &file_handles))) { |
| 167 return E_FAIL; | 169 return E_FAIL; |
| 168 } | 170 } |
| 169 | 171 |
| 172 std::vector<HANDLE> handles; |
| 173 file_handles.reserve(file_names.size() + file_handles.size()); |
| 174 for (const base::string16& file_name : file_names) { |
| 175 // This leaks the handles, since they are used as the reference key to |
| 176 // CreateStreamFromKey, and DirectWrite requires the reference keys to |
| 177 // remain valid for the lifetime of the loader. The loader is the font |
| 178 // collection proxy, which remains alive for the lifetime of the renderer. |
| 179 HANDLE handle = |
| 180 CreateFile(file_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, |
| 181 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
| 182 if (handle != INVALID_HANDLE_VALUE) |
| 183 handles.push_back(handle); |
| 184 } |
| 185 for (const IPC::PlatformFileForTransit& file_handle : file_handles) { |
| 186 handles.push_back(IPC::PlatformFileForTransitToPlatformFile(file_handle)); |
| 187 } |
| 188 |
| 170 HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>( | 189 HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>( |
| 171 font_file_enumerator, factory, this, &file_names); | 190 font_file_enumerator, factory, this, &handles); |
| 172 | 191 |
| 173 if (!SUCCEEDED(hr)) { | 192 if (!SUCCEEDED(hr)) { |
| 174 DCHECK(false); | 193 DCHECK(false); |
| 175 return E_FAIL; | 194 return E_FAIL; |
| 176 } | 195 } |
| 177 | 196 |
| 178 return S_OK; | 197 return S_OK; |
| 179 } | 198 } |
| 180 | 199 |
| 181 HRESULT DWriteFontCollectionProxy::CreateStreamFromKey( | 200 HRESULT DWriteFontCollectionProxy::CreateStreamFromKey( |
| 182 const void* font_file_reference_key, | 201 const void* font_file_reference_key, |
| 183 UINT32 font_file_reference_key_size, | 202 UINT32 font_file_reference_key_size, |
| 184 IDWriteFontFileStream** font_file_stream) { | 203 IDWriteFontFileStream** font_file_stream) { |
| 185 if (!font_file_reference_key) { | 204 if (font_file_reference_key_size != sizeof(HANDLE)) { |
| 186 return E_FAIL; | |
| 187 } | |
| 188 | |
| 189 const base::char16* file_name = | |
| 190 reinterpret_cast<const base::char16*>(font_file_reference_key); | |
| 191 DCHECK_EQ(font_file_reference_key_size % sizeof(base::char16), 0u); | |
| 192 size_t file_name_size = | |
| 193 static_cast<size_t>(font_file_reference_key_size) / sizeof(base::char16); | |
| 194 | |
| 195 if (file_name_size == 0 || file_name[file_name_size - 1] != L'\0') { | |
| 196 return E_FAIL; | 205 return E_FAIL; |
| 197 } | 206 } |
| 198 | 207 |
| 199 TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey"); | 208 TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey"); |
| 200 | 209 |
| 201 mswr::ComPtr<IDWriteFontFileStream> stream; | 210 HANDLE file_handle = |
| 202 if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name))) { | 211 *reinterpret_cast<const HANDLE*>(font_file_reference_key); |
| 212 |
| 213 if (file_handle == NULL || file_handle == INVALID_HANDLE_VALUE) { |
| 203 DCHECK(false); | 214 DCHECK(false); |
| 204 return E_FAIL; | 215 return E_FAIL; |
| 205 } | 216 } |
| 217 |
| 218 mswr::ComPtr<FontFileStream> stream; |
| 219 if (!SUCCEEDED( |
| 220 mswr::MakeAndInitialize<FontFileStream>(&stream, file_handle))) { |
| 221 DCHECK(false); |
| 222 return E_FAIL; |
| 223 } |
| 206 *font_file_stream = stream.Detach(); | 224 *font_file_stream = stream.Detach(); |
| 207 return S_OK; | 225 return S_OK; |
| 208 } | 226 } |
| 209 | 227 |
| 210 HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize( | 228 HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize( |
| 211 IDWriteFactory* factory, | 229 IDWriteFactory* factory, |
| 212 IPC::Sender* sender_override) { | 230 IPC::Sender* sender_override) { |
| 213 DCHECK(factory); | 231 DCHECK(factory); |
| 214 | 232 |
| 215 factory_ = factory; | 233 factory_ = factory; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 | 491 |
| 474 return SUCCEEDED(hr); | 492 return SUCCEEDED(hr); |
| 475 } | 493 } |
| 476 | 494 |
| 477 FontFileEnumerator::FontFileEnumerator() = default; | 495 FontFileEnumerator::FontFileEnumerator() = default; |
| 478 | 496 |
| 479 FontFileEnumerator::~FontFileEnumerator() = default; | 497 FontFileEnumerator::~FontFileEnumerator() = default; |
| 480 | 498 |
| 481 HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) { | 499 HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) { |
| 482 DCHECK(file); | 500 DCHECK(file); |
| 483 if (current_file_ >= file_names_.size()) { | 501 if (current_file_ >= files_.size()) { |
| 484 return E_FAIL; | 502 return E_FAIL; |
| 485 } | 503 } |
| 486 | 504 |
| 487 TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile"); | 505 TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile"); |
| 506 |
| 488 // CreateCustomFontFileReference ends up calling | 507 // CreateCustomFontFileReference ends up calling |
| 489 // DWriteFontCollectionProxy::CreateStreamFromKey. | 508 // DWriteFontCollectionProxy::CreateStreamFromKey. |
| 490 HRESULT hr = factory_->CreateCustomFontFileReference( | 509 HRESULT hr = factory_->CreateCustomFontFileReference( |
| 491 reinterpret_cast<const void*>(file_names_[current_file_].c_str()), | 510 reinterpret_cast<const void*>(&files_[current_file_]), |
| 492 (file_names_[current_file_].length() + 1) * sizeof(base::char16), | 511 sizeof(files_[current_file_]), loader_.Get() /*IDWriteFontFileLoader*/, |
| 493 loader_.Get() /*IDWriteFontFileLoader*/, file); | 512 file); |
| 494 DCHECK(SUCCEEDED(hr)); | 513 DCHECK(SUCCEEDED(hr)); |
| 495 return hr; | 514 return hr; |
| 496 } | 515 } |
| 497 | 516 |
| 498 HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) { | 517 HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) { |
| 499 DCHECK(has_current_file); | 518 DCHECK(has_current_file); |
| 500 | 519 |
| 501 TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext"); | 520 TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext"); |
| 502 if (next_file_ >= file_names_.size()) { | 521 if (next_file_ >= files_.size()) { |
| 503 *has_current_file = FALSE; | 522 *has_current_file = FALSE; |
| 504 current_file_ = UINT_MAX; | 523 current_file_ = UINT_MAX; |
| 505 return S_OK; | 524 return S_OK; |
| 506 } | 525 } |
| 507 | 526 |
| 508 current_file_ = next_file_; | 527 current_file_ = next_file_; |
| 509 ++next_file_; | 528 ++next_file_; |
| 510 *has_current_file = TRUE; | 529 *has_current_file = TRUE; |
| 511 return S_OK; | 530 return S_OK; |
| 512 } | 531 } |
| 513 | 532 |
| 514 HRESULT FontFileEnumerator::RuntimeClassInitialize( | 533 HRESULT FontFileEnumerator::RuntimeClassInitialize( |
| 515 IDWriteFactory* factory, | 534 IDWriteFactory* factory, |
| 516 IDWriteFontFileLoader* loader, | 535 IDWriteFontFileLoader* loader, |
| 517 std::vector<base::string16>* file_names) { | 536 std::vector<HANDLE>* files) { |
| 518 factory_ = factory; | 537 factory_ = factory; |
| 519 loader_ = loader; | 538 loader_ = loader; |
| 520 file_names_.swap(*file_names); | 539 files_.swap(*files); |
| 521 file_streams_.resize(file_names_.size()); | |
| 522 return S_OK; | 540 return S_OK; |
| 523 } | 541 } |
| 524 | 542 |
| 525 FontFileStream::FontFileStream() = default; | 543 FontFileStream::FontFileStream() = default; |
| 526 | 544 |
| 527 FontFileStream::~FontFileStream() = default; | 545 FontFileStream::~FontFileStream() = default; |
| 528 | 546 |
| 529 HRESULT FontFileStream::GetFileSize(UINT64* file_size) { | 547 HRESULT FontFileStream::GetFileSize(UINT64* file_size) { |
| 530 *file_size = data_.length(); | 548 *file_size = data_.length(); |
| 531 return S_OK; | 549 return S_OK; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 542 void** fragment_context) { | 560 void** fragment_context) { |
| 543 if (fragment_offset + fragment_size < fragment_offset) | 561 if (fragment_offset + fragment_size < fragment_offset) |
| 544 return E_FAIL; | 562 return E_FAIL; |
| 545 if (fragment_offset + fragment_size > data_.length()) | 563 if (fragment_offset + fragment_size > data_.length()) |
| 546 return E_FAIL; | 564 return E_FAIL; |
| 547 *fragment_start = data_.data() + fragment_offset; | 565 *fragment_start = data_.data() + fragment_offset; |
| 548 *fragment_context = nullptr; | 566 *fragment_context = nullptr; |
| 549 return S_OK; | 567 return S_OK; |
| 550 } | 568 } |
| 551 | 569 |
| 552 HRESULT FontFileStream::RuntimeClassInitialize( | 570 HRESULT FontFileStream::RuntimeClassInitialize(HANDLE handle) { |
| 553 const base::string16& file_name) { | 571 // Duplicate the original handle so we can reopen the file after the memory |
| 554 data_.Initialize(base::FilePath(file_name)); | 572 // mapped section closes it. |
| 555 if (!data_.IsValid()) | 573 HANDLE duplicate_handle; |
| 574 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), |
| 575 &duplicate_handle, 0 /* dwDesiredAccess */, |
| 576 false /* bInheritHandle */, DUPLICATE_SAME_ACCESS)) { |
| 577 return E_FAIL; |
| 578 } |
| 579 |
| 580 data_.Initialize(base::File(duplicate_handle)); |
| 581 if (!data_.IsValid()) { |
| 556 return E_FAIL; | 582 return E_FAIL; |
| 557 return S_OK; | 583 return S_OK; |
| 558 } | 584 } |
| 559 | 585 |
| 560 } // namespace content | 586 } // namespace content |
| OLD | NEW |