| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/renderer/render_font_warmup_win.h" | 5 #include "content/common/font_warmup_win.h" |
| 6 | 6 |
| 7 #include <dwrite.h> | 7 #include <dwrite.h> |
| 8 | 8 |
| 9 #include "base/debug/alias.h" | 9 #include "base/debug/alias.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/win/iat_patch_function.h" | 11 #include "base/win/iat_patch_function.h" |
| 12 #include "base/win/windows_version.h" | 12 #include "base/win/windows_version.h" |
| 13 #include "content/public/common/dwrite_font_platform_win.h" | 13 #include "content/public/common/dwrite_font_platform_win.h" |
| 14 #include "third_party/WebKit/public/web/win/WebFontRendering.h" | 14 #include "third_party/WebKit/public/web/win/WebFontRendering.h" |
| 15 #include "third_party/skia/include/core/SkPaint.h" | 15 #include "third_party/skia/include/core/SkPaint.h" |
| 16 #include "third_party/skia/include/ports/SkFontMgr.h" | 16 #include "third_party/skia/include/ports/SkFontMgr.h" |
| 17 #include "third_party/skia/include/ports/SkTypeface_win.h" | 17 #include "third_party/skia/include/ports/SkTypeface_win.h" |
| 18 | 18 |
| 19 namespace content { | 19 namespace content { |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 SkFontMgr* g_warmup_fontmgr = NULL; | 23 SkFontMgr* g_warmup_fontmgr = nullptr; |
| 24 | 24 |
| 25 base::win::IATPatchFunction g_iat_patch_open_sc_manager; | 25 base::win::IATPatchFunction g_iat_patch_open_sc_manager; |
| 26 base::win::IATPatchFunction g_iat_patch_close_service_handle; | 26 base::win::IATPatchFunction g_iat_patch_close_service_handle; |
| 27 base::win::IATPatchFunction g_iat_patch_open_service; | 27 base::win::IATPatchFunction g_iat_patch_open_service; |
| 28 base::win::IATPatchFunction g_iat_patch_start_service; | 28 base::win::IATPatchFunction g_iat_patch_start_service; |
| 29 base::win::IATPatchFunction g_iat_patch_nt_connect_port; | 29 base::win::IATPatchFunction g_iat_patch_nt_connect_port; |
| 30 | 30 |
| 31 // These are from ntddk.h | 31 // These are from ntddk.h |
| 32 #if !defined(STATUS_ACCESS_DENIED) | 32 #if !defined(STATUS_ACCESS_DENIED) |
| 33 #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) | 33 #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) |
| 34 #endif | 34 #endif |
| 35 | 35 |
| 36 typedef LONG NTSTATUS; | 36 typedef LONG NTSTATUS; |
| 37 | 37 |
| 38 const uintptr_t kFakeSCMHandle = 0xdead0001; |
| 39 const uintptr_t kFakeServiceHandle = 0xdead0002; |
| 40 |
| 38 SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name, | 41 SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name, |
| 39 const wchar_t* database_name, | 42 const wchar_t* database_name, |
| 40 DWORD access_mask) { | 43 DWORD access_mask) { |
| 41 ::SetLastError(0); | 44 ::SetLastError(0); |
| 42 return reinterpret_cast<SC_HANDLE>(0xdeadbeef); | 45 return reinterpret_cast<SC_HANDLE>(kFakeSCMHandle); |
| 43 } | 46 } |
| 44 | 47 |
| 45 SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager, | 48 SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager, |
| 46 const wchar_t* service_name, | 49 const wchar_t* service_name, |
| 47 DWORD access_mask) { | 50 DWORD access_mask) { |
| 48 ::SetLastError(0); | 51 ::SetLastError(0); |
| 49 return reinterpret_cast<SC_HANDLE>(0xdeadbabe); | 52 return reinterpret_cast<SC_HANDLE>(kFakeServiceHandle); |
| 50 } | 53 } |
| 51 | 54 |
| 52 BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) { | 55 BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) { |
| 53 if (service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbabe) && | 56 if (service_handle != reinterpret_cast<SC_HANDLE>(kFakeServiceHandle) && |
| 54 service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbeef)) | 57 service_handle != reinterpret_cast<SC_HANDLE>(kFakeSCMHandle)) |
| 55 CHECK(false); | 58 CHECK(false); |
| 56 ::SetLastError(0); | 59 ::SetLastError(0); |
| 57 return TRUE; | 60 return TRUE; |
| 58 } | 61 } |
| 59 | 62 |
| 60 BOOL WINAPI StartServiceWPatch(SC_HANDLE service, | 63 BOOL WINAPI StartServiceWPatch(SC_HANDLE service, |
| 61 DWORD args, | 64 DWORD args, |
| 62 const wchar_t** arg_vectors) { | 65 const wchar_t** arg_vectors) { |
| 63 if (service != reinterpret_cast<SC_HANDLE>(0xdeadbabe)) | 66 if (service != reinterpret_cast<SC_HANDLE>(kFakeServiceHandle)) |
| 64 CHECK(false); | 67 CHECK(false); |
| 65 ::SetLastError(ERROR_ACCESS_DENIED); | 68 ::SetLastError(ERROR_ACCESS_DENIED); |
| 66 return FALSE; | 69 return FALSE; |
| 67 } | 70 } |
| 68 | 71 |
| 69 NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle, | 72 NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle, |
| 70 void* port_name, | 73 void* port_name, |
| 71 void* object_attribs, | 74 void* object_attribs, |
| 72 void* port_attribs, | 75 void* port_attribs, |
| 73 DWORD flags, | 76 DWORD flags, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 94 // OpenSCManagerW | 97 // OpenSCManagerW |
| 95 // OpenServiceW | 98 // OpenServiceW |
| 96 // StartServiceW | 99 // StartServiceW |
| 97 // CloseServiceHandle. | 100 // CloseServiceHandle. |
| 98 // These are all IAT patched. | 101 // These are all IAT patched. |
| 99 void PatchServiceManagerCalls() { | 102 void PatchServiceManagerCalls() { |
| 100 static bool is_patched = false; | 103 static bool is_patched = false; |
| 101 if (is_patched) | 104 if (is_patched) |
| 102 return; | 105 return; |
| 103 const char* service_provider_dll = | 106 const char* service_provider_dll = |
| 104 (base::win::GetVersion() >= base::win::VERSION_WIN8 ? | 107 (base::win::GetVersion() >= base::win::VERSION_WIN8 |
| 105 "api-ms-win-service-management-l1-1-0.dll" : "advapi32.dll"); | 108 ? "api-ms-win-service-management-l1-1-0.dll" |
| 109 : "advapi32.dll"); |
| 106 | 110 |
| 107 is_patched = true; | 111 is_patched = true; |
| 108 | 112 |
| 109 DWORD patched = g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", | 113 DWORD patched = |
| 110 service_provider_dll, "OpenSCManagerW", OpenSCManagerWPatch); | 114 g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", service_provider_dll, |
| 115 "OpenSCManagerW", OpenSCManagerWPatch); |
| 111 DCHECK(patched == 0); | 116 DCHECK(patched == 0); |
| 112 | 117 |
| 113 patched = g_iat_patch_close_service_handle.Patch(L"dwrite.dll", | 118 patched = g_iat_patch_close_service_handle.Patch( |
| 114 service_provider_dll, "CloseServiceHandle", CloseServiceHandlePatch); | 119 L"dwrite.dll", service_provider_dll, "CloseServiceHandle", |
| 120 CloseServiceHandlePatch); |
| 115 DCHECK(patched == 0); | 121 DCHECK(patched == 0); |
| 116 | 122 |
| 117 patched = g_iat_patch_open_service.Patch(L"dwrite.dll", | 123 patched = g_iat_patch_open_service.Patch(L"dwrite.dll", service_provider_dll, |
| 118 service_provider_dll, "OpenServiceW", OpenServiceWPatch); | 124 "OpenServiceW", OpenServiceWPatch); |
| 119 DCHECK(patched == 0); | 125 DCHECK(patched == 0); |
| 120 | 126 |
| 121 patched = g_iat_patch_start_service.Patch(L"dwrite.dll", | 127 patched = g_iat_patch_start_service.Patch( |
| 122 service_provider_dll, "StartServiceW", StartServiceWPatch); | 128 L"dwrite.dll", service_provider_dll, "StartServiceW", StartServiceWPatch); |
| 123 DCHECK(patched == 0); | 129 DCHECK(patched == 0); |
| 124 | 130 |
| 125 patched = g_iat_patch_nt_connect_port.Patch(L"dwrite.dll", | 131 patched = g_iat_patch_nt_connect_port.Patch( |
| 126 "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch); | 132 L"dwrite.dll", "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch); |
| 127 DCHECK(patched == 0); | 133 DCHECK(patched == 0); |
| 128 } | 134 } |
| 129 | 135 |
| 130 // Windows-only DirectWrite support. These warm up the DirectWrite paths | 136 // Windows-only DirectWrite support. These warm up the DirectWrite paths |
| 131 // before sandbox lock down to allow Skia access to the Font Manager service. | 137 // before sandbox lock down to allow Skia access to the Font Manager service. |
| 132 void CreateDirectWriteFactory(IDWriteFactory** factory) { | 138 void CreateDirectWriteFactory(IDWriteFactory** factory) { |
| 133 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; | 139 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; |
| 134 HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll"); | 140 HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll"); |
| 135 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. | 141 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. |
| 136 if (!dwrite_dll) { | 142 if (!dwrite_dll) { |
| 137 DWORD load_library_get_last_error = GetLastError(); | 143 DWORD load_library_get_last_error = GetLastError(); |
| 138 base::debug::Alias(&dwrite_dll); | 144 base::debug::Alias(&dwrite_dll); |
| 139 base::debug::Alias(&load_library_get_last_error); | 145 base::debug::Alias(&load_library_get_last_error); |
| 140 CHECK(false); | 146 CHECK(false); |
| 141 } | 147 } |
| 142 | 148 |
| 143 PatchServiceManagerCalls(); | 149 PatchServiceManagerCalls(); |
| 144 | 150 |
| 145 DWriteCreateFactoryProc dwrite_create_factory_proc = | 151 DWriteCreateFactoryProc dwrite_create_factory_proc = |
| 146 reinterpret_cast<DWriteCreateFactoryProc>( | 152 reinterpret_cast<DWriteCreateFactoryProc>( |
| 147 GetProcAddress(dwrite_dll, "DWriteCreateFactory")); | 153 GetProcAddress(dwrite_dll, "DWriteCreateFactory")); |
| 148 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. | 154 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. |
| 149 if (!dwrite_create_factory_proc) { | 155 if (!dwrite_create_factory_proc) { |
| 150 DWORD get_proc_address_get_last_error = GetLastError(); | 156 DWORD get_proc_address_get_last_error = GetLastError(); |
| 151 base::debug::Alias(&dwrite_create_factory_proc); | 157 base::debug::Alias(&dwrite_create_factory_proc); |
| 152 base::debug::Alias(&get_proc_address_get_last_error); | 158 base::debug::Alias(&get_proc_address_get_last_error); |
| 153 CHECK(false); | 159 CHECK(false); |
| 154 } | 160 } |
| 155 CHECK(SUCCEEDED( | 161 CHECK(SUCCEEDED(dwrite_create_factory_proc( |
| 156 dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_ISOLATED, | 162 DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory), |
| 157 __uuidof(IDWriteFactory), | 163 reinterpret_cast<IUnknown**>(factory)))); |
| 158 reinterpret_cast<IUnknown**>(factory)))); | |
| 159 } | 164 } |
| 160 | 165 |
| 161 HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory, | 166 HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory, |
| 162 IDWriteFontCollection** col, | 167 IDWriteFontCollection** col, |
| 163 BOOL checkUpdates) { | 168 BOOL checkUpdates) { |
| 164 // We always return pre-created font collection from here. | 169 // We always return pre-created font collection from here. |
| 165 IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory); | 170 IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory); |
| 166 DCHECK(custom_collection != NULL); | 171 DCHECK(custom_collection != nullptr); |
| 167 *col = custom_collection; | 172 *col = custom_collection; |
| 168 return S_OK; | 173 return S_OK; |
| 169 } | 174 } |
| 170 | 175 |
| 171 void PatchDWriteFactory(IDWriteFactory* factory) { | 176 void PatchDWriteFactory(IDWriteFactory* factory) { |
| 172 const unsigned int kGetSystemFontCollectionVTableIndex = 3; | 177 const unsigned int kGetSystemFontCollectionVTableIndex = 3; |
| 173 | 178 |
| 174 PROC* vtable = *reinterpret_cast<PROC**>(factory); | 179 PROC* vtable = *reinterpret_cast<PROC**>(factory); |
| 175 PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex]; | 180 PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex]; |
| 176 void* stub_function = &StubFontCollection; | 181 void* stub_function = &StubFontCollection; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 195 | 200 |
| 196 PatchDWriteFactory(factory); | 201 PatchDWriteFactory(factory); |
| 197 | 202 |
| 198 blink::WebFontRendering::setDirectWriteFactory(factory); | 203 blink::WebFontRendering::setDirectWriteFactory(factory); |
| 199 g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory); | 204 g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory); |
| 200 } | 205 } |
| 201 return g_warmup_fontmgr; | 206 return g_warmup_fontmgr; |
| 202 } | 207 } |
| 203 | 208 |
| 204 } // namespace content | 209 } // namespace content |
| OLD | NEW |