summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-26 01:41:04 +0000
committerscottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-26 01:41:04 +0000
commit3f18e8db464aa841e82b536d85de26f77fd2a2b1 (patch)
tree3d12007f6e43710c1b433c849b21d7d538b4f791
parent6db416a41378f54d8376beb26dc40daac472e690 (diff)
downloadchromium_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.cc7
-rw-r--r--base/base_paths_win.h1
-rw-r--r--content/browser/renderer_host/render_message_filter.cc4
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc5
-rw-r--r--content/common/sandbox_win.cc24
-rw-r--r--content/common/sandbox_win.h2
-rw-r--r--content/renderer/renderer_main_platform_delegate_win.cc62
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);
+ }
}
}