Index: content/common/child_process_host.cc |
=================================================================== |
--- content/common/child_process_host.cc (revision 112358) |
+++ content/common/child_process_host.cc (working copy) |
@@ -19,6 +19,8 @@ |
#if defined(OS_LINUX) |
#include "base/linux_util.h" |
+#elif defined(OS_WIN) |
+#include "content/common/font_cache_dispatcher_win.h" |
#endif // OS_LINUX |
#if defined(OS_MACOSX) |
@@ -67,17 +69,12 @@ |
} // 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) { |
+#if defined(OS_WIN) |
+ AddFilter(new FontCacheDispatcher()); |
+#endif |
} |
ChildProcessHost::~ChildProcessHost() { |
@@ -139,132 +136,6 @@ |
return child_path; |
} |
-#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 |
-ChildProcessHost::FontCache* ChildProcessHost::FontCache::GetInstance() { |
- return Singleton<ChildProcessHost::FontCache>::get(); |
-} |
- |
-void ChildProcessHost::FontCache::PreCacheFont(LOGFONT font, int process_id) { |
- typedef std::map<string16, ChildProcessHost::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(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; |
- } |
- } |
-} |
- |
-// 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 |
- |
void ChildProcessHost::ForceShutdown() { |
Send(new ChildProcessMsg_Shutdown()); |
} |