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

Unified Diff: content/common/font_cache_dispatcher_win.cc

Issue 8759013: Dispatch the Windows font caching IPCs in one filter. This avoids having the code that calls thos... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/common/font_cache_dispatcher_win.h ('k') | content/content_common.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/common/font_cache_dispatcher_win.cc
===================================================================
--- content/common/font_cache_dispatcher_win.cc (revision 0)
+++ content/common/font_cache_dispatcher_win.cc (revision 0)
@@ -0,0 +1,185 @@
+// Copyright (c) 2011 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/font_cache_dispatcher_win.h"
+
+#include <vector>
+#include <map>
+
+#include "base/logging.h"
+#include "base/string16.h"
+#include "content/common/child_process_messages.h"
+
+namespace {
+typedef std::vector<string16> FontNameVector;
+typedef std::map<FontCacheDispatcher*, FontNameVector> DispatcherToFontNames;
+
+class FontCache {
+ public:
+ static FontCache* GetInstance() {
+ return Singleton<FontCache>::get();
+ }
+
+ void PreCacheFont(LOGFONT font, FontCacheDispatcher* dispatcher) {
+ typedef std::map<string16, FontCache::CacheElement> FontNameToElement;
+
+ 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);
+
+ HGDIOBJ old_font = SelectObject(hdc, font_handle);
+ DCHECK(NULL != old_font);
+
+ TEXTMETRIC tm;
+ BOOL ret = GetTextMetrics(hdc, &tm);
+ DCHECK(ret);
+
+ string16 font_name = font.lfFaceName;
+ int ref_count_inc = 1;
+ FontNameVector::iterator it =
+ std::find(dispatcher_font_map_[dispatcher].begin(),
+ dispatcher_font_map_[dispatcher].end(),
+ font_name);
+ if (it == dispatcher_font_map_[dispatcher].end()) {
+ // Requested font is new to cache.
+ dispatcher_font_map_[dispatcher].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 ReleaseCachedFonts(FontCacheDispatcher* dispatcher) {
+ typedef std::map<string16, FontCache::CacheElement> FontNameToElement;
+
+ base::AutoLock lock(mutex_);
+
+ DispatcherToFontNames::iterator it;
+ it = dispatcher_font_map_.find(dispatcher);
+ if (it == dispatcher_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_);
+ }
+ }
+
+ dispatcher_font_map_.erase(it);
+ for (FontNameToElement::iterator i = cache_.begin(); i != cache_.end(); ) {
+ if (i->second.ref_count_ == 0) {
+ cache_.erase(i++);
+ } else {
+ ++i;
+ }
+ }
+ }
+
+ private:
+ struct CacheElement {
+ CacheElement()
+ : font_(NULL), dc_(NULL), ref_count_(0) {
+ }
+
+ ~CacheElement() {
+ if (font_) {
+ DeleteObject(font_);
+ }
+ if (dc_) {
+ DeleteDC(dc_);
+ }
+ }
+
+ HFONT font_;
+ HDC dc_;
+ int ref_count_;
+ };
+ friend struct DefaultSingletonTraits<FontCache>;
+
+ FontCache() {
+ }
+
+ std::map<string16, CacheElement> cache_;
+ DispatcherToFontNames dispatcher_font_map_;
+ base::Lock mutex_;
+
+ DISALLOW_COPY_AND_ASSIGN(FontCache);
+};
+
+}
+
+FontCacheDispatcher::FontCacheDispatcher()
+ : channel_(NULL) {
+}
+
+FontCacheDispatcher::~FontCacheDispatcher() {
+}
+
+void FontCacheDispatcher::OnFilterAdded(IPC::Channel* channel) {
+ channel_ = channel;
+}
+
+bool FontCacheDispatcher::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(FontCacheDispatcher, message)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_PreCacheFont, OnPreCacheFont)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ReleaseCachedFonts,
+ OnReleaseCachedFonts)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void FontCacheDispatcher::OnChannelClosing() {
+ channel_ = NULL;
+}
+
+bool FontCacheDispatcher::Send(IPC::Message* message) {
+ if (channel_)
+ return channel_->Send(message);
+
+ delete message;
+ return false;
+}
+
+void FontCacheDispatcher::OnPreCacheFont(const 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.
+ // 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.
+ FontCache::GetInstance()->PreCacheFont(font, this);
+}
+
+void FontCacheDispatcher::OnReleaseCachedFonts() {
+ // Release cached fonts that requested from a pid by decrementing the ref
+ // count. When ref count is zero, the handles are released.
+ FontCache::GetInstance()->ReleaseCachedFonts(this);
+}
Property changes on: content\common\font_cache_dispatcher_win.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « content/common/font_cache_dispatcher_win.h ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698