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

Side by Side Diff: content/renderer/dwrite_font_proxy_init_win.cc

Issue 1378353006: Implementation of dwrite font proxy and removal of dwrite font cache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More codereview fixes. Jumped the gun on previous patchset. Created 5 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/renderer/dwrite_font_proxy_init_win.h"
6
7 #include <dwrite.h>
8
9 #include "base/callback.h"
10 #include "base/debug/alias.h"
11 #include "base/win/iat_patch_function.h"
12 #include "base/win/windows_version.h"
13 #include "content/renderer/dwrite_font_proxy_win.h"
14 #include "skia/ext/fontmgr_default_win.h"
15 #include "third_party/WebKit/public/web/win/WebFontRendering.h"
16 #include "third_party/skia/include/ports/SkTypeface_win.h"
17
18 namespace mswr = Microsoft::WRL;
19
20 namespace content {
21
22 namespace {
23 mswr::ComPtr<DWriteFontCollectionProxy> g_font_collection;
24 base::win::IATPatchFunction g_iat_patch_open_sc_manager;
25 base::win::IATPatchFunction g_iat_patch_close_service_handle;
26 base::win::IATPatchFunction g_iat_patch_open_service;
27 base::win::IATPatchFunction g_iat_patch_start_service;
28 base::win::IATPatchFunction g_iat_patch_nt_connect_port;
29 IPC::Sender* g_senderOverride = nullptr;
30 }
31
32 // These are from ntddk.h
33 #if !defined(STATUS_ACCESS_DENIED)
34 #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
35 #endif
36
37 typedef LONG NTSTATUS;
38
39 const uintptr_t kFakeSCMHandle = 0xdead0001;
40 const uintptr_t kFakeServiceHandle = 0xdead0002;
41
42 SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name,
43 const wchar_t* database_name,
44 DWORD access_mask) {
45 ::SetLastError(0);
46 return reinterpret_cast<SC_HANDLE>(kFakeSCMHandle);
47 }
48
49 SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager,
50 const wchar_t* service_name,
51 DWORD access_mask) {
52 ::SetLastError(0);
53 return reinterpret_cast<SC_HANDLE>(kFakeServiceHandle);
54 }
55
56 BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) {
57 if (service_handle != reinterpret_cast<SC_HANDLE>(kFakeServiceHandle) &&
58 service_handle != reinterpret_cast<SC_HANDLE>(kFakeSCMHandle))
59 CHECK(false);
60 ::SetLastError(0);
61 return TRUE;
62 }
63
64 BOOL WINAPI StartServiceWPatch(SC_HANDLE service,
65 DWORD args,
66 const wchar_t** arg_vectors) {
67 if (service != reinterpret_cast<SC_HANDLE>(kFakeServiceHandle))
68 CHECK(false);
69 ::SetLastError(ERROR_ACCESS_DENIED);
70 return FALSE;
71 }
72
73 NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle,
74 void* port_name,
75 void* object_attribs,
76 void* port_attribs,
77 DWORD flags,
78 void* server_sid,
79 void* message,
80 DWORD* buffer_length,
81 void* out_message_attributes,
82 void* in_message_attributes,
83 void* time_out) {
84 return STATUS_ACCESS_DENIED;
85 }
86
87 // Directwrite connects to the font cache service to retrieve information about
88 // fonts installed on the system etc. This works well outside the sandbox and
89 // within the sandbox as long as the lpc connection maintained by the current
90 // process with the font cache service remains valid. It appears that there
91 // are cases when this connection is dropped after which directwrite is unable
92 // to connect to the font cache service which causes problems with characters
93 // disappearing.
94 // Directwrite has fallback code to enumerate fonts if it is unable to connect
95 // to the font cache service. We need to intercept the following APIs to
96 // ensure that it does not connect to the font cache service.
97 // NtALpcConnectPort
98 // OpenSCManagerW
99 // OpenServiceW
100 // StartServiceW
101 // CloseServiceHandle.
102 // These are all IAT patched.
103 void PatchServiceManagerCalls() {
104 static bool is_patched = false;
105 if (is_patched)
106 return;
107 const char* service_provider_dll =
108 (base::win::GetVersion() >= base::win::VERSION_WIN8
109 ? "api-ms-win-service-management-l1-1-0.dll"
110 : "advapi32.dll");
111
112 is_patched = true;
113
114 DWORD patched =
115 g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", service_provider_dll,
116 "OpenSCManagerW", OpenSCManagerWPatch);
117 DCHECK(patched == 0);
118
119 patched = g_iat_patch_close_service_handle.Patch(
120 L"dwrite.dll", service_provider_dll, "CloseServiceHandle",
121 CloseServiceHandlePatch);
122 DCHECK(patched == 0);
123
124 patched = g_iat_patch_open_service.Patch(L"dwrite.dll", service_provider_dll,
125 "OpenServiceW", OpenServiceWPatch);
126 DCHECK(patched == 0);
127
128 patched = g_iat_patch_start_service.Patch(
129 L"dwrite.dll", service_provider_dll, "StartServiceW", StartServiceWPatch);
130 DCHECK(patched == 0);
131
132 patched = g_iat_patch_nt_connect_port.Patch(
133 L"dwrite.dll", "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch);
134 DCHECK(patched == 0);
135 }
136
137 // Copied from content/common/font_warmup_win.cc
138 // Windows-only DirectWrite support. These warm up the DirectWrite paths
139 // before sandbox lock down to allow Skia access to the Font Manager service.
140 void CreateDirectWriteFactory(IDWriteFactory** factory) {
141 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
142 HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
143 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
144 if (!dwrite_dll) {
145 DWORD load_library_get_last_error = GetLastError();
146 base::debug::Alias(&dwrite_dll);
147 base::debug::Alias(&load_library_get_last_error);
148 CHECK(false);
149 }
150
151 // TODO(kulshin): This shouldn't be necessary, but not having this causes
152 // breakage in content_browsertests, and possibly other high-stress cases.
153 PatchServiceManagerCalls();
154
155 DWriteCreateFactoryProc dwrite_create_factory_proc =
156 reinterpret_cast<DWriteCreateFactoryProc>(
157 GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
158 // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
159 if (!dwrite_create_factory_proc) {
160 DWORD get_proc_address_get_last_error = GetLastError();
161 base::debug::Alias(&dwrite_create_factory_proc);
162 base::debug::Alias(&get_proc_address_get_last_error);
163 CHECK(false);
164 }
165 CHECK(SUCCEEDED(dwrite_create_factory_proc(
166 DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory),
167 reinterpret_cast<IUnknown**>(factory))));
168 }
169
170 HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory,
171 IDWriteFontCollection** col,
172 BOOL checkUpdates) {
173 DCHECK(g_font_collection != nullptr);
174 g_font_collection.CopyTo(col);
175 return S_OK;
176 }
177
178 // Copied from content/common/font_warmup_win.cc
179 // TODO(kulshin): eventually, make Skia deal with custom font collections and
180 // get rid of this altogether.
181 void PatchDWriteFactory(IDWriteFactory* factory) {
182 const unsigned int kGetSystemFontCollectionVTableIndex = 3;
183
184 PROC* vtable = *reinterpret_cast<PROC**>(factory);
185 PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex];
186 void* stub_function = &StubFontCollection;
187 base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC));
188 }
189
190 void InitializeDWriteFontProxy(
191 const base::Callback<IPC::Sender(void)>& getSender) {
192 mswr::ComPtr<IDWriteFactory> factory;
193
194 CreateDirectWriteFactory(&factory);
195
196 if (g_font_collection == nullptr) {
197 mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
198 &g_font_collection, factory.Get(), getSender);
199 }
200
201 PatchDWriteFactory(factory.Get());
202
203 blink::WebFontRendering::setDirectWriteFactory(factory.Get());
204 SkFontMgr* skiaFontManager = SkFontMgr_New_DirectWrite(factory.Get());
205 SetDefaultSkiaFactory(skiaFontManager);
206 }
207
208 void UninitializeDWriteFontProxy() {
209 if (g_font_collection != nullptr)
210 g_font_collection->Unregister();
211 }
212
213 void SetDWriteFontProxyTestModeSender(IPC::Sender* sender) {
214 g_senderOverride = sender;
215 }
216
217 } // namespace content
OLDNEW
« no previous file with comments | « content/public/test/render_view_test.cc ('k') | content/renderer/renderer_main_platform_delegate_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698