Index: content/common/dwrite_font_proxy_init_win.cc |
diff --git a/content/common/dwrite_font_proxy_init_win.cc b/content/common/dwrite_font_proxy_init_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..032f0ec5e56b68f7893be44dc94193016888f9d5 |
--- /dev/null |
+++ b/content/common/dwrite_font_proxy_init_win.cc |
@@ -0,0 +1,115 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/common/dwrite_font_proxy_init_win.h" |
+ |
+#include <dwrite.h> |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/debug/alias.h" |
+#include "base/win/iat_patch_function.h" |
+#include "base/win/windows_version.h" |
+#include "content/common/dwrite_font_proxy_win.h" |
+#include "content/common/font_warmup_win.h" |
+#include "skia/ext/fontmgr_default_win.h" |
+#include "third_party/WebKit/public/web/win/WebFontRendering.h" |
+#include "third_party/skia/include/ports/SkTypeface_win.h" |
+ |
+namespace mswr = Microsoft::WRL; |
+ |
+namespace content { |
+ |
+namespace { |
+mswr::ComPtr<DWriteFontCollectionProxy> g_font_collection; |
+IPC::Sender* g_senderOverride = nullptr; |
+} |
+ |
+// Windows-only DirectWrite support. These warm up the DirectWrite paths |
+// before sandbox lock down to allow Skia access to the Font Manager service. |
+void CreateDirectWriteFactory(IDWriteFactory** factory) { |
+ typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; |
+ HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll"); |
+ // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. |
+ if (!dwrite_dll) { |
+ DWORD load_library_get_last_error = GetLastError(); |
+ base::debug::Alias(&dwrite_dll); |
+ base::debug::Alias(&load_library_get_last_error); |
+ CHECK(false); |
+ } |
+ |
+ // This shouldn't be necessary, but not having this causes breakage in |
+ // content_browsertests, and possibly other high-stress cases. |
+ PatchServiceManagerCalls(); |
+ |
+ DWriteCreateFactoryProc dwrite_create_factory_proc = |
+ reinterpret_cast<DWriteCreateFactoryProc>( |
+ GetProcAddress(dwrite_dll, "DWriteCreateFactory")); |
+ // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867. |
+ if (!dwrite_create_factory_proc) { |
+ DWORD get_proc_address_get_last_error = GetLastError(); |
+ base::debug::Alias(&dwrite_create_factory_proc); |
+ base::debug::Alias(&get_proc_address_get_last_error); |
+ CHECK(false); |
+ } |
+ CHECK(SUCCEEDED(dwrite_create_factory_proc( |
+ DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory), |
+ reinterpret_cast<IUnknown**>(factory)))); |
+} |
+ |
+HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory, |
+ IDWriteFontCollection** col, |
+ BOOL checkUpdates) { |
+ DCHECK(g_font_collection != nullptr); |
+ g_font_collection.CopyTo(col); |
+ return S_OK; |
+} |
+ |
+// Copied from content/common/font_warmup_win.cc |
+void PatchDWriteFactory(IDWriteFactory* factory) { |
+ const unsigned int kGetSystemFontCollectionVTableIndex = 3; |
+ |
+ PROC* vtable = *reinterpret_cast<PROC**>(factory); |
+ PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex]; |
+ void* stub_function = &StubFontCollection; |
+ base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC)); |
+} |
+ |
+void SetDWriteFontProxyTestModeSender(IPC::Sender* sender) { |
+ g_senderOverride = sender; |
+} |
+ |
+// Needed as a function for Bind() |
+IPC::Sender* GetSenderOverride() { |
+ return g_senderOverride; |
+} |
+ |
+void InitializeDWriteFontProxy( |
+ const base::Callback<IPC::Sender*(void)>& getSender) { |
+ mswr::ComPtr<IDWriteFactory> factory; |
+ |
+ CreateDirectWriteFactory(&factory); |
+ |
+ if (g_font_collection == nullptr) { |
+ if (g_senderOverride != nullptr) |
+ mswr::MakeAndInitialize<DWriteFontCollectionProxy>( |
+ &g_font_collection, factory.Get(), base::Bind(&GetSenderOverride)); |
+ else |
+ mswr::MakeAndInitialize<DWriteFontCollectionProxy>( |
+ &g_font_collection, factory.Get(), getSender); |
+ } |
+ |
+ PatchDWriteFactory(factory.Get()); |
+ |
+ blink::WebFontRendering::setDirectWriteFactory(factory.Get()); |
+ SkFontMgr* skiaFontManager = SkFontMgr_New_DirectWrite(factory.Get()); |
+ SetDefaultSkiaFactory(skiaFontManager); |
+} |
+ |
+void UninitializeDWriteFontProxy() { |
+ if (g_font_collection != nullptr) |
+ g_font_collection->Unregister(); |
+} |
+ |
+} // namespace content |