summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarthurhsu@chromium.org <arthurhsu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-20 03:33:21 +0000
committerarthurhsu@chromium.org <arthurhsu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-20 03:33:21 +0000
commit79fff8227ab720a8bf309107ef96f57ae93592c1 (patch)
treecb9c7d286ece595404e5dde9ab381820017b40dc
parentf354e25b2905341d67166e20709a71163004de73 (diff)
downloadchromium_src-79fff8227ab720a8bf309107ef96f57ae93592c1.zip
chromium_src-79fff8227ab720a8bf309107ef96f57ae93592c1.tar.gz
chromium_src-79fff8227ab720a8bf309107ef96f57ae93592c1.tar.bz2
New implementation of font precache on Windows.
BUG=94421 TEST=none Review URL: http://codereview.chromium.org/7866019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101911 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/common/chrome_utility_messages.h7
-rw-r--r--chrome/renderer/chrome_render_process_observer.cc1
-rw-r--r--chrome/service/service_utility_process_host.cc12
-rw-r--r--chrome/service/service_utility_process_host.h3
-rw-r--r--chrome/utility/chrome_content_utility_client.cc6
-rw-r--r--content/browser/renderer_host/render_message_filter.cc17
-rw-r--r--content/browser/renderer_host/render_message_filter.h6
-rw-r--r--content/common/child_process_host.cc137
-rw-r--r--content/common/child_process_host.h35
-rw-r--r--content/common/child_process_messages.h10
-rw-r--r--content/common/view_messages.h7
-rw-r--r--content/renderer/render_thread.cc10
-rw-r--r--content/renderer/render_thread.h3
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.cc4
14 files changed, 212 insertions, 46 deletions
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index c993653..d808f8d 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -143,13 +143,6 @@ IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Succeeded,
// Reply when an error occured rendering the PDF.
IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed)
-#if defined(OS_WIN)
-// Request that the given font be loaded by the host so it's cached by the
-// OS. Please see ChildProcessHost::PreCacheFont for details.
-IPC_SYNC_MESSAGE_CONTROL1_0(ChromeUtilityHostMsg_PreCacheFont,
- LOGFONT /* font data */)
-#endif // defined(OS_WIN)
-
// Reply when the utility process successfully parsed a JSON string.
//
// WARNING: The result can be of any Value subclass type, but we can't easily
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc
index 1ab4815..a1ec2b3 100644
--- a/chrome/renderer/chrome_render_process_observer.cc
+++ b/chrome/renderer/chrome_render_process_observer.cc
@@ -165,6 +165,7 @@ DWORD WINAPI GetFontDataPatch(HDC hdc,
std::vector<char> font_data;
if (RenderThread::PreCacheFont(logfont))
rv = GetFontData(hdc, table, offset, buffer, length);
+ RenderThread::ReleaseCachedFonts();
}
}
return rv;
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index 0c4e88c..760fc23 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -20,6 +20,7 @@
#if defined(OS_WIN)
#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_handle.h"
+#include "content/common/child_process_messages.h"
#include "printing/emf_win.h"
#endif
@@ -29,6 +30,7 @@ ServiceUtilityProcessHost::ServiceUtilityProcessHost(
client_(client),
client_message_loop_proxy_(client_message_loop_proxy),
waiting_for_reply_(false) {
+ process_id_ = ChildProcessInfo::GenerateChildProcessUniqueId();
}
ServiceUtilityProcessHost::~ServiceUtilityProcessHost() {
@@ -144,7 +146,9 @@ bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
bool msg_is_ok = false;
IPC_BEGIN_MESSAGE_MAP_EX(ServiceUtilityProcessHost, message, msg_is_ok)
#if defined(OS_WIN) // This hack is Windows-specific.
- IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFont, OnPreCacheFont)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_PreCacheFont, OnPreCacheFont)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ReleaseCachedFonts,
+ OnReleaseCachedFonts)
#endif
IPC_MESSAGE_HANDLER(
ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Succeeded,
@@ -166,7 +170,11 @@ bool ServiceUtilityProcessHost::MessageForClient(const IPC::Message& message) {
#if defined(OS_WIN) // This hack is Windows-specific.
void ServiceUtilityProcessHost::OnPreCacheFont(const LOGFONT& font) {
- PreCacheFont(font);
+ PreCacheFont(font, process_id_);
+}
+
+void ServiceUtilityProcessHost::OnReleaseCachedFonts() {
+ ReleaseCachedFonts(process_id_);
}
#endif // OS_WIN
diff --git a/chrome/service/service_utility_process_host.h b/chrome/service/service_utility_process_host.h
index b3802f9..f24bd3a 100644
--- a/chrome/service/service_utility_process_host.h
+++ b/chrome/service/service_utility_process_host.h
@@ -131,6 +131,7 @@ class ServiceUtilityProcessHost : public ServiceChildProcessHost {
#if defined(OS_WIN) // This hack is Windows-specific.
void OnPreCacheFont(const LOGFONT& font);
+ void OnReleaseCachedFonts();
#endif // defined(OS_WIN)
// A pointer to our client interface, who will be informed of progress.
@@ -141,6 +142,8 @@ class ServiceUtilityProcessHost : public ServiceChildProcessHost {
FilePath metafile_path_;
// The temporary folder created for the metafile.
scoped_ptr<ScopedTempDir> scratch_metafile_dir_;
+ // The unique id created for the process.
+ int process_id_;
DISALLOW_COPY_AND_ASSIGN(ServiceUtilityProcessHost);
};
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index 2f1b895..8beb181 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -27,6 +27,7 @@
#include "base/path_service.h"
#include "base/win/iat_patch_function.h"
#include "base/win/scoped_handle.h"
+#include "content/common/child_process_messages.h"
#include "content/common/content_switches.h"
#include "content/common/sandbox_init_wrapper.h"
#include "printing/emf_win.h"
@@ -223,8 +224,11 @@ DWORD WINAPI UtilityProcess_GetFontDataPatch(
if (GetObject(font, sizeof(LOGFONT), &logfont)) {
std::vector<char> font_data;
if (UtilityThread::current()->Send(
- new ChromeUtilityHostMsg_PreCacheFont(logfont)))
+ new ChildProcessHostMsg_PreCacheFont(logfont))) {
rv = GetFontData(hdc, table, offset, buffer, length);
+ UtilityThread::current()->Send(
+ new ChildProcessHostMsg_ReleaseCachedFonts());
+ }
}
}
return rv;
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 25eb0d2..d64b464 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -64,6 +64,7 @@
#endif
#if defined(OS_WIN)
#include "content/common/child_process_host.h"
+#include "content/common/child_process_messages.h"
#endif
using net::CookieStore;
@@ -285,6 +286,12 @@ void RenderMessageFilter::OnChannelClosing() {
plugin_host_clients_.clear();
}
+#if defined (OS_WIN)
+void RenderMessageFilter::OnChannelError() {
+ ChildProcessHost::ReleaseCachedFonts(render_process_id_);
+}
+#endif
+
void RenderMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
BrowserThread::ID* thread) {
switch (message.type()) {
@@ -313,7 +320,9 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnGetRootWindowRect)
// This hack is Windows-specific.
- IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_PreCacheFont, OnPreCacheFont)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ReleaseCachedFonts,
+ OnReleaseCachedFonts)
#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID)
@@ -494,7 +503,11 @@ void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
#if defined(OS_WIN) // This hack is Windows-specific.
void RenderMessageFilter::OnPreCacheFont(const LOGFONT& font) {
- ChildProcessHost::PreCacheFont(font);
+ ChildProcessHost::PreCacheFont(font, render_process_id_);
+}
+
+void RenderMessageFilter::OnReleaseCachedFonts() {
+ ChildProcessHost::ReleaseCachedFonts(render_process_id_);
}
#endif // OS_WIN
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 70a0d8f..4079134 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -78,6 +78,9 @@ class RenderMessageFilter : public BrowserMessageFilter {
// IPC::ChannelProxy::MessageFilter methods:
virtual void OnChannelClosing() OVERRIDE;
+#if defined (OS_WIN)
+ virtual void OnChannelError() OVERRIDE;
+#endif
// BrowserMessageFilter methods:
virtual void OverrideThreadForMessage(const IPC::Message& message,
@@ -148,6 +151,9 @@ class RenderMessageFilter : public BrowserMessageFilter {
// Cache fonts for the renderer. See RenderMessageFilter::OnPreCacheFont
// implementation for more details.
void OnPreCacheFont(const LOGFONT& font);
+
+ // Release fonts cached for renderer.
+ void OnReleaseCachedFonts();
#endif
void OnGetPlugins(bool refresh,
diff --git a/content/common/child_process_host.cc b/content/common/child_process_host.cc
index b8a3b95..65a9b7a 100644
--- a/content/common/child_process_host.cc
+++ b/content/common/child_process_host.cc
@@ -66,6 +66,14 @@ FilePath TransformPathForFeature(const FilePath& path,
} // namespace
#endif // OS_MACOSX
+#if defined (OS_WIN)
+// Types used in PreCacheFont
+namespace {
+typedef std::vector<string16> FontNameVector;
+typedef std::map<int, FontNameVector> PidToFontNames;
+}
+#endif // OS_WIN
+
ChildProcessHost::ChildProcessHost()
: ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
opening_channel_(false) {
@@ -131,27 +139,39 @@ FilePath ChildProcessHost::GetChildPath(int flags) {
}
#if defined(OS_WIN)
+ChildProcessHost::FontCache::CacheElement::CacheElement()
+ : font_(NULL), dc_(NULL), ref_count_(0) {
+}
+
+ChildProcessHost::FontCache::CacheElement::~CacheElement() {
+ if (font_) {
+ DeleteObject(font_);
+ }
+ if (dc_) {
+ DeleteDC(dc_);
+ }
+}
+
+ChildProcessHost::FontCache::FontCache() {
+}
+
+ChildProcessHost::FontCache::~FontCache() {
+}
+
// static
-void ChildProcessHost::PreCacheFont(LOGFONT font) {
- // If a child process is running in a sandbox, GetTextMetrics()
- // can sometimes fail. If a font has not been loaded
- // previously, GetTextMetrics() will try to load the font
- // from the font file. However, the sandboxed process does
- // not have permissions to access any font files and
- // the call fails. So we make the browser pre-load the
- // font for us by using a dummy call to GetTextMetrics of
- // the same font.
+ChildProcessHost::FontCache* ChildProcessHost::FontCache::GetInstance() {
+ return Singleton<ChildProcessHost::FontCache>::get();
+}
- // Maintain a circular queue for the fonts and DCs to be cached.
- // font_index maintains next available location in the queue.
- static const int kFontCacheSize = 32;
- static HFONT fonts[kFontCacheSize] = {0};
- static HDC hdcs[kFontCacheSize] = {0};
- static size_t font_index = 0;
+void ChildProcessHost::FontCache::PreCacheFont(LOGFONT font, int process_id) {
+ typedef std::map<string16, ChildProcessHost::FontCache::CacheElement>
+ FontNameToElement;
- UMA_HISTOGRAM_COUNTS_100("Memory.CachedFontAndDC",
- fonts[kFontCacheSize-1] ? kFontCacheSize : static_cast<int>(font_index));
+ base::AutoLock lock(mutex_);
+ // Fetch the font into memory.
+ // No matter the font is cached or not, we load it to avoid GDI swapping out
+ // that font file.
HDC hdc = GetDC(NULL);
HFONT font_handle = CreateFontIndirect(&font);
DCHECK(NULL != font_handle);
@@ -163,15 +183,84 @@ void ChildProcessHost::PreCacheFont(LOGFONT font) {
BOOL ret = GetTextMetrics(hdc, &tm);
DCHECK(ret);
- if (fonts[font_index] || hdcs[font_index]) {
- // We already have too many fonts, we will delete one and take it's place.
- DeleteObject(fonts[font_index]);
- ReleaseDC(NULL, hdcs[font_index]);
+ string16 font_name = font.lfFaceName;
+ int ref_count_inc = 1;
+ FontNameVector::iterator it =
+ std::find(process_id_font_map_[process_id].begin(),
+ process_id_font_map_[process_id].end(),
+ font_name);
+ if (it == process_id_font_map_[process_id].end()) {
+ // Requested font is new to cache.
+ process_id_font_map_[process_id].push_back(font_name);
+ } else {
+ ref_count_inc = 0;
+ }
+
+ if (cache_[font_name].ref_count_ == 0) { // Requested font is new to cache.
+ cache_[font_name].ref_count_ = 1;
+ } else { // Requested font is already in cache, release old handles.
+ DeleteObject(cache_[font_name].font_);
+ DeleteDC(cache_[font_name].dc_);
}
+ cache_[font_name].font_ = font_handle;
+ cache_[font_name].dc_ = hdc;
+ cache_[font_name].ref_count_ += ref_count_inc;
+}
+
+void ChildProcessHost::FontCache::ReleaseCachedFonts(int process_id) {
+ typedef std::map<string16, ChildProcessHost::FontCache::CacheElement>
+ FontNameToElement;
+
+ base::AutoLock lock(mutex_);
+
+ PidToFontNames::iterator it;
+ it = process_id_font_map_.find(process_id);
+ if (it == process_id_font_map_.end()) {
+ return;
+ }
+
+ for (FontNameVector::iterator i = it->second.begin(), e = it->second.end();
+ i != e; ++i) {
+ FontNameToElement::iterator element;
+ element = cache_.find(*i);
+ if (element != cache_.end()) {
+ --((*element).second.ref_count_);
+ }
+ }
+
+ process_id_font_map_.erase(it);
+ for (FontNameToElement::iterator i = cache_.begin(); i != cache_.end(); ) {
+ if (i->second.ref_count_ == 0) {
+ cache_.erase(i++);
+ } else {
+ ++i;
+ }
+ }
+}
- fonts[font_index] = font_handle;
- hdcs[font_index] = hdc;
- font_index = (font_index + 1) % kFontCacheSize;
+// static
+void ChildProcessHost::PreCacheFont(LOGFONT font, int pid) {
+ // If a child process is running in a sandbox, GetTextMetrics()
+ // can sometimes fail. If a font has not been loaded
+ // previously, GetTextMetrics() will try to load the font
+ // from the font file. However, the sandboxed process does
+ // not have permissions to access any font files and
+ // the call fails. So we make the browser pre-load the
+ // font for us by using a dummy call to GetTextMetrics of
+ // the same font.
+ // This means the browser process just loads the font into memory so that
+ // when GDI attempt to query that font info in child process, it does not
+ // need to load that file, hence no permission issues there. Therefore,
+ // when a font is asked to be cached, we always recreates the font object
+ // to avoid the case that an in-cache font is swapped out by GDI.
+ ChildProcessHost::FontCache::GetInstance()->PreCacheFont(font, pid);
+}
+
+// static
+void ChildProcessHost::ReleaseCachedFonts(int pid) {
+ // Release cached fonts that requested from a pid by decrementing the ref
+ // count. When ref count is zero, the handles are released.
+ ChildProcessHost::FontCache::GetInstance()->ReleaseCachedFonts(pid);
}
#endif // OS_WIN
diff --git a/content/common/child_process_host.h b/content/common/child_process_host.h
index 5b965b9..a4a7c55 100644
--- a/content/common/child_process_host.h
+++ b/content/common/child_process_host.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include <map>
#include "build/build_config.h"
@@ -17,6 +18,8 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
+#include "base/string16.h"
#include "content/common/content_export.h"
#include "content/common/content_notification_types.h"
#include "ipc/ipc_channel_proxy.h"
@@ -87,7 +90,8 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Channel::Listener,
#if defined(OS_WIN)
// See comments in the cc file. This is a common hack needed for a process
// hosting a sandboxed child process. Hence it lives in this file.
- static void PreCacheFont(LOGFONT font);
+ static void PreCacheFont(LOGFONT font, int pid);
+ static void ReleaseCachedFonts(int pid);
#endif // defined(OS_WIN)
// IPC::Message::Sender implementation.
@@ -156,6 +160,35 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Channel::Listener,
ListenerHook listener_;
+#if defined (OS_WIN)
+ class FontCache {
+ public:
+ static FontCache* GetInstance();
+ void PreCacheFont(LOGFONT font, int process_id);
+ void ReleaseCachedFonts(int process_id);
+
+ private:
+ struct CacheElement {
+ CacheElement();
+ ~CacheElement();
+
+ HFONT font_;
+ HDC dc_;
+ int ref_count_;
+ };
+ friend struct DefaultSingletonTraits<FontCache>;
+
+ FontCache();
+ ~FontCache();
+
+ std::map<string16, CacheElement> cache_;
+ std::map<int, std::vector<string16> > process_id_font_map_;
+ base::Lock mutex_;
+
+ DISALLOW_COPY_AND_ASSIGN(FontCache);
+ };
+#endif
+
bool opening_channel_; // True while we're waiting the channel to be opened.
scoped_ptr<IPC::Channel> channel_;
std::string channel_id_;
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h
index a503423..32ff20b 100644
--- a/content/common/child_process_messages.h
+++ b/content/common/child_process_messages.h
@@ -59,3 +59,13 @@ IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TraceDataCollected,
// Reply to ChildProcessMsg_GetTraceBufferPercentFull.
IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TraceBufferPercentFullReply,
float /*trace buffer percent full*/)
+
+#if defined(OS_WIN)
+// Request that the given font be loaded by the host so it's cached by the
+// OS. Please see ChildProcessHost::PreCacheFont for details.
+IPC_SYNC_MESSAGE_CONTROL1_0(ChildProcessHostMsg_PreCacheFont,
+ LOGFONT /* font data */)
+
+// Release the cached font
+IPC_MESSAGE_CONTROL0(ChildProcessHostMsg_ReleaseCachedFonts)
+#endif // defined(OS_WIN)
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 05e72c6..695ffc2 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1784,13 +1784,6 @@ IPC_SYNC_MESSAGE_CONTROL1_3(ViewHostMsg_LoadFont,
uint32 /* font id */)
#endif
-#if defined(OS_WIN)
-// Request that the given font be loaded by the browser so it's cached by the
-// OS. Please see ChildProcessHost::PreCacheFont for details.
-IPC_SYNC_MESSAGE_CONTROL1_0(ViewHostMsg_PreCacheFont,
- LOGFONT /* font data */)
-#endif // defined(OS_WIN)
-
// Returns WebScreenInfo corresponding to the view.
// TODO(shess): Provide a mapping from reply_msg->routing_id() to
// HWND so that we can eliminate the NativeViewId parameter.
diff --git a/content/renderer/render_thread.cc b/content/renderer/render_thread.cc
index 3e11f98..d50ec17 100644
--- a/content/renderer/render_thread.cc
+++ b/content/renderer/render_thread.cc
@@ -71,6 +71,7 @@
// TODO(port)
#if defined(OS_WIN)
+#include "content/common/child_process_messages.h"
#include "content/plugin/plugin_channel.h"
#else
#include "base/memory/scoped_handle.h"
@@ -519,7 +520,14 @@ void RenderThread::RecordUserMetrics(const std::string& action) {
#if defined(OS_WIN)
// static
bool RenderThread::PreCacheFont(const LOGFONT& log_font) {
- return RenderThread::current()->Send(new ViewHostMsg_PreCacheFont(log_font));
+ return RenderThread::current()->Send(
+ new ChildProcessHostMsg_PreCacheFont(log_font));
+}
+
+// static
+bool RenderThread::ReleaseCachedFonts() {
+ return RenderThread::current()->Send(
+ new ChildProcessHostMsg_ReleaseCachedFonts());
}
#endif // OS_WIN
diff --git a/content/renderer/render_thread.h b/content/renderer/render_thread.h
index 9c5a471..8fb9e03 100644
--- a/content/renderer/render_thread.h
+++ b/content/renderer/render_thread.h
@@ -227,6 +227,9 @@ class CONTENT_EXPORT RenderThread : public RenderThreadBase,
// Request that the given font be loaded by the browser so it's cached by the
// OS. Please see ChildProcessHost::PreCacheFont for details.
static bool PreCacheFont(const LOGFONT& log_font);
+
+ // Release cached font.
+ static bool ReleaseCachedFonts();
#endif // OS_WIN
private:
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 6d459e9..2ca0e7c 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -47,6 +47,7 @@
#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
#if defined(OS_WIN)
+#include "content/common/child_process_messages.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebSandboxSupport.h"
#endif
@@ -444,7 +445,8 @@ bool RendererWebKitPlatformSupportImpl::SandboxSupport::ensureFontLoaded(
HFONT font) {
LOGFONT logfont;
GetObject(font, sizeof(LOGFONT), &logfont);
- return RenderThread::current()->Send(new ViewHostMsg_PreCacheFont(logfont));
+ return RenderThread::current()->Send(
+ new ChildProcessHostMsg_PreCacheFont(logfont));
}
#elif defined(OS_MACOSX)