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