diff options
author | scottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-26 01:41:04 +0000 |
---|---|---|
committer | scottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-26 01:41:04 +0000 |
commit | 3f18e8db464aa841e82b536d85de26f77fd2a2b1 (patch) | |
tree | 3d12007f6e43710c1b433c849b21d7d538b4f791 | |
parent | 6db416a41378f54d8376beb26dc40daac472e690 (diff) | |
download | chromium_src-3f18e8db464aa841e82b536d85de26f77fd2a2b1.zip chromium_src-3f18e8db464aa841e82b536d85de26f77fd2a2b1.tar.gz chromium_src-3f18e8db464aa841e82b536d85de26f77fd2a2b1.tar.bz2 |
Support DirectWrite with sandbox on
This seems to be enough to get DirectWrite working with the sandbox on.
There's two parts:
1. Warmup for three things: the dwrite.dll, creating a font, and
accessing glyph metrics.
2. A renderer sandbox policy allowing readonly fonts directory access.
Manually tested working on Win 8.1, Win 7 Pro SP1 with QFE 2670838,
and Win Home Basic RTM (no SPs or QFEs).
Blink side here: https://codereview.chromium.org/210243004 but can land
independently after this change.
R=brettw@chromium.org, cpu@chromium.org, jam@chromium.org, jschuh@chromium.org, darin@chromium.org
BUG=333029
TEST=Run with --enable-direct-write and http://wikipedia.org/
Review URL: https://codereview.chromium.org/209163002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259434 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/base_paths_win.cc | 7 | ||||
-rw-r--r-- | base/base_paths_win.h | 1 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/render_process_host_impl.cc | 5 | ||||
-rw-r--r-- | content/common/sandbox_win.cc | 24 | ||||
-rw-r--r-- | content/common/sandbox_win.h | 2 | ||||
-rw-r--r-- | content/renderer/renderer_main_platform_delegate_win.cc | 62 |
7 files changed, 99 insertions, 6 deletions
diff --git a/base/base_paths_win.cc b/base/base_paths_win.cc index d4e11ae..509d5fd 100644 --- a/base/base_paths_win.cc +++ b/base/base_paths_win.cc @@ -191,6 +191,13 @@ bool PathProviderWin(int key, FilePath* result) { cur = cur.AppendASCII("User Pinned"); cur = cur.AppendASCII("TaskBar"); break; + case base::DIR_WINDOWS_FONTS: + if (FAILED(SHGetFolderPath( + NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, system_buffer))) { + return false; + } + cur = FilePath(system_buffer); + break; default: return false; } diff --git a/base/base_paths_win.h b/base/base_paths_win.h index 1c44578..b042d08 100644 --- a/base/base_paths_win.h +++ b/base/base_paths_win.h @@ -41,6 +41,7 @@ enum { // of the Default user. DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar via // base::win::TaskbarPinShortcutLink(). + DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts. PATH_WIN_END }; diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index a3ada4e..770c0062 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -84,6 +84,7 @@ #endif #if defined(OS_WIN) #include "content/common/font_cache_dispatcher_win.h" +#include "content/common/sandbox_win.h" #endif #if defined(OS_ANDROID) #include "media/base/android/webaudio_media_codec_bridge.h" @@ -1199,6 +1200,9 @@ void RenderMessageFilter::OnDidLose3DContext( #if defined(OS_WIN) void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font, const base::string16& str) { + // TODO(scottmg): Move this to FontCacheDispatcher, http://crbug.com/356346. + if (!ShouldUseDirectWrite()) + return; // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. // Except that for True Type fonts, // GetTextMetrics will not load the font in memory. diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 0fdf90c..f22d6df 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -758,7 +758,9 @@ void RenderProcessHostImpl::CreateMessageFilters() { #if defined(OS_MACOSX) AddFilter(new TextInputClientMessageFilter(GetID())); #elif defined(OS_WIN) - channel_->AddFilter(new FontCacheDispatcher()); + // The FontCacheDispatcher is required only when we're using GDI rendering. + if (!ShouldUseDirectWrite()) + channel_->AddFilter(new FontCacheDispatcher()); #elif defined(OS_ANDROID) browser_demuxer_android_ = new BrowserDemuxerAndroid(); AddFilter(browser_demuxer_android_); @@ -1223,7 +1225,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kChildCleanExit, #endif #if defined(OS_WIN) - switches::kEnableDirectWrite, switches::kEnableHighResolutionTime, switches::kHighDPISupport, #endif diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index aea5860..0041fda 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc @@ -571,6 +571,16 @@ bool InitTargetServices(sandbox::TargetServices* target_services) { return sandbox::SBOX_ALL_OK == result; } +bool ShouldUseDirectWrite() { + // If the flag is currently on, and we're on Win7 or above, we enable + // DirectWrite. Skia does not require the additions to DirectWrite in QFE + // 2670838, so a Win7 check is sufficient. We do not currently attempt to + // support Vista, where SP2 and the Platform Update are required. + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + return command_line.HasSwitch(switches::kEnableDirectWrite) && + base::win::GetVersion() >= base::win::VERSION_WIN7; +} + base::ProcessHandle StartSandboxedProcess( SandboxedProcessLauncherDelegate* delegate, CommandLine* cmd_line) { @@ -637,7 +647,19 @@ base::ProcessHandle StartSandboxedProcess( if (!disable_default_policy && !AddPolicyForSandboxedProcess(policy)) return 0; - if (type_str != switches::kRendererProcess) { + if (type_str == switches::kRendererProcess) { + if (ShouldUseDirectWrite()) { + AddDirectory(base::DIR_WINDOWS_FONTS, + NULL, + true, + sandbox::TargetPolicy::FILES_ALLOW_READONLY, + policy); + // We do not automatically propagate this from the browser command line, + // and instead only add it when we're actually setting up the sandbox to + // work with DirectWrite. + cmd_line->AppendSwitch(switches::kEnableDirectWrite); + } + } else { // Hack for Google Desktop crash. Trick GD into not injecting its DLL into // this subprocess. See // http://code.google.com/p/chromium/issues/detail?id=25580 diff --git a/content/common/sandbox_win.h b/content/common/sandbox_win.h index ac6ce90..92d8d04 100644 --- a/content/common/sandbox_win.h +++ b/content/common/sandbox_win.h @@ -33,6 +33,8 @@ bool InitBrokerServices(sandbox::BrokerServices* broker_services); bool InitTargetServices(sandbox::TargetServices* target_services); +bool ShouldUseDirectWrite(); + } // namespace content #endif // CONTENT_COMMON_SANDBOX_WIN_H_ diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc index 58fce15..2ed9599 100644 --- a/content/renderer/renderer_main_platform_delegate_win.cc +++ b/content/renderer/renderer_main_platform_delegate_win.cc @@ -8,7 +8,10 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" +#include "base/win/scoped_comptr.h" #include "base/win/win_util.h" +#include "base/win/windows_version.h" +#include "content/common/sandbox_win.h" #include "content/public/common/content_switches.h" #include "content/public/common/injection_test_win.h" #include "content/public/renderer/render_thread.h" @@ -22,10 +25,13 @@ #include "v8/src/third_party/vtune/v8-vtune.h" #endif +#include <dwrite.h> + namespace content { namespace { // Windows-only skia sandbox support +// These are used for GDI-path rendering. void SkiaPreCacheFont(const LOGFONT& logfont) { RenderThread* render_thread = RenderThread::Get(); if (render_thread) { @@ -44,6 +50,51 @@ void SkiaPreCacheFontCharacters(const LOGFONT& logfont, } } +// Windows-only DirectWrite support. These warm up the DirectWrite paths +// before sandbox lock down to allow Skia access to the Font Manager service. +bool CreateDirectWriteFactory(IDWriteFactory** factory) { + typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; + DWriteCreateFactoryProc dwrite_create_factory_proc = + reinterpret_cast<DWriteCreateFactoryProc>( + GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")); + if (!dwrite_create_factory_proc) + return false; + CHECK(SUCCEEDED( + dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast<IUnknown**>(factory)))); + return true; +} + +void WarmupDirectWrite() { + base::win::ScopedComPtr<IDWriteFactory> factory; + if (!CreateDirectWriteFactory(factory.Receive())) + return; + + base::win::ScopedComPtr<IDWriteFontCollection> font_collection; + CHECK(SUCCEEDED( + factory->GetSystemFontCollection(font_collection.Receive(), FALSE))); + base::win::ScopedComPtr<IDWriteFontFamily> font_family; + + UINT32 index; + BOOL exists; + CHECK(SUCCEEDED( + font_collection->FindFamilyName(L"Times New Roman", &index, &exists))); + CHECK(exists); + CHECK( + SUCCEEDED(font_collection->GetFontFamily(index, font_family.Receive()))); + base::win::ScopedComPtr<IDWriteFont> font; + base::win::ScopedComPtr<IDWriteFontFace> font_face; + CHECK(SUCCEEDED(font_family->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + font.Receive()))); + CHECK(SUCCEEDED(font->CreateFontFace(font_face.Receive()))); + DWRITE_GLYPH_METRICS gm; + UINT16 glyph = L'S'; + CHECK(SUCCEEDED(font_face->GetDesignGlyphMetrics(&glyph, 1, &gm))); +} + } // namespace RendererMainPlatformDelegate::RendererMainPlatformDelegate( @@ -75,9 +126,14 @@ void RendererMainPlatformDelegate::PlatformInitialize() { // cached and there's no more need to access the registry. If the sandbox // is disabled, we don't have to make this dummy call. scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); - SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont); - skia::SetSkiaEnsureTypefaceCharactersAccessible( - SkiaPreCacheFontCharacters); + + if (ShouldUseDirectWrite()) { + WarmupDirectWrite(); + } else { + SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont); + skia::SetSkiaEnsureTypefaceCharactersAccessible( + SkiaPreCacheFontCharacters); + } } } |