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

Side by Side Diff: content/common/child_process_host.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 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/common/child_process_host.h ('k') | content/common/font_cache_dispatcher_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/child_process_host.h" 5 #include "content/common/child_process_host.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/file_path.h" 8 #include "base/file_path.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "base/process_util.h" 12 #include "base/process_util.h"
13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
14 #include "content/common/child_process_info.h" 14 #include "content/common/child_process_info.h"
15 #include "content/common/child_process_messages.h" 15 #include "content/common/child_process_messages.h"
16 #include "content/public/common/content_paths.h" 16 #include "content/public/common/content_paths.h"
17 #include "content/public/common/content_switches.h" 17 #include "content/public/common/content_switches.h"
18 #include "ipc/ipc_logging.h" 18 #include "ipc/ipc_logging.h"
19 19
20 #if defined(OS_LINUX) 20 #if defined(OS_LINUX)
21 #include "base/linux_util.h" 21 #include "base/linux_util.h"
22 #elif defined(OS_WIN)
23 #include "content/common/font_cache_dispatcher_win.h"
22 #endif // OS_LINUX 24 #endif // OS_LINUX
23 25
24 #if defined(OS_MACOSX) 26 #if defined(OS_MACOSX)
25 namespace { 27 namespace {
26 28
27 // Given |path| identifying a Mac-style child process executable path, adjusts 29 // Given |path| identifying a Mac-style child process executable path, adjusts
28 // it to correspond to |feature|. For a child process path such as 30 // it to correspond to |feature|. For a child process path such as
29 // ".../Chromium Helper.app/Contents/MacOS/Chromium Helper", the transformed 31 // ".../Chromium Helper.app/Contents/MacOS/Chromium Helper", the transformed
30 // path for feature "NP" would be 32 // path for feature "NP" would be
31 // ".../Chromium Helper NP.app/Contents/MacOS/Chromium Helper NP". The new 33 // ".../Chromium Helper NP.app/Contents/MacOS/Chromium Helper NP". The new
(...skipping 28 matching lines...) Expand all
60 .Append(kContentsName) 62 .Append(kContentsName)
61 .Append(kMacOSName) 63 .Append(kMacOSName)
62 .Append(new_basename); 64 .Append(new_basename);
63 65
64 return new_path; 66 return new_path;
65 } 67 }
66 68
67 } // namespace 69 } // namespace
68 #endif // OS_MACOSX 70 #endif // OS_MACOSX
69 71
70 #if defined (OS_WIN)
71 // Types used in PreCacheFont
72 namespace {
73 typedef std::vector<string16> FontNameVector;
74 typedef std::map<int, FontNameVector> PidToFontNames;
75 }
76 #endif // OS_WIN
77
78 ChildProcessHost::ChildProcessHost() 72 ChildProcessHost::ChildProcessHost()
79 : ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)), 73 : ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
80 opening_channel_(false) { 74 opening_channel_(false) {
75 #if defined(OS_WIN)
76 AddFilter(new FontCacheDispatcher());
77 #endif
81 } 78 }
82 79
83 ChildProcessHost::~ChildProcessHost() { 80 ChildProcessHost::~ChildProcessHost() {
84 for (size_t i = 0; i < filters_.size(); ++i) { 81 for (size_t i = 0; i < filters_.size(); ++i) {
85 filters_[i]->OnChannelClosing(); 82 filters_[i]->OnChannelClosing();
86 filters_[i]->OnFilterRemoved(); 83 filters_[i]->OnFilterRemoved();
87 } 84 }
88 listener_.Shutdown(); 85 listener_.Shutdown();
89 } 86 }
90 87
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // non-executable heap, but the "EH" feature is provided to allow code 129 // non-executable heap, but the "EH" feature is provided to allow code
133 // intolerant of a non-executable heap to work properly on 10.7. This 130 // intolerant of a non-executable heap to work properly on 10.7. This
134 // results in Chromium Helper EH.app or Google Chrome Helper EH.app. 131 // results in Chromium Helper EH.app or Google Chrome Helper EH.app.
135 child_path = TransformPathForFeature(child_path, "EH"); 132 child_path = TransformPathForFeature(child_path, "EH");
136 } 133 }
137 #endif 134 #endif
138 135
139 return child_path; 136 return child_path;
140 } 137 }
141 138
142 #if defined(OS_WIN)
143 ChildProcessHost::FontCache::CacheElement::CacheElement()
144 : font_(NULL), dc_(NULL), ref_count_(0) {
145 }
146
147 ChildProcessHost::FontCache::CacheElement::~CacheElement() {
148 if (font_) {
149 DeleteObject(font_);
150 }
151 if (dc_) {
152 DeleteDC(dc_);
153 }
154 }
155
156 ChildProcessHost::FontCache::FontCache() {
157 }
158
159 ChildProcessHost::FontCache::~FontCache() {
160 }
161
162 // static
163 ChildProcessHost::FontCache* ChildProcessHost::FontCache::GetInstance() {
164 return Singleton<ChildProcessHost::FontCache>::get();
165 }
166
167 void ChildProcessHost::FontCache::PreCacheFont(LOGFONT font, int process_id) {
168 typedef std::map<string16, ChildProcessHost::FontCache::CacheElement>
169 FontNameToElement;
170
171 base::AutoLock lock(mutex_);
172
173 // Fetch the font into memory.
174 // No matter the font is cached or not, we load it to avoid GDI swapping out
175 // that font file.
176 HDC hdc = GetDC(NULL);
177 HFONT font_handle = CreateFontIndirect(&font);
178 DCHECK(NULL != font_handle);
179
180 HGDIOBJ old_font = SelectObject(hdc, font_handle);
181 DCHECK(NULL != old_font);
182
183 TEXTMETRIC tm;
184 BOOL ret = GetTextMetrics(hdc, &tm);
185 DCHECK(ret);
186
187 string16 font_name = font.lfFaceName;
188 int ref_count_inc = 1;
189 FontNameVector::iterator it =
190 std::find(process_id_font_map_[process_id].begin(),
191 process_id_font_map_[process_id].end(),
192 font_name);
193 if (it == process_id_font_map_[process_id].end()) {
194 // Requested font is new to cache.
195 process_id_font_map_[process_id].push_back(font_name);
196 } else {
197 ref_count_inc = 0;
198 }
199
200 if (cache_[font_name].ref_count_ == 0) { // Requested font is new to cache.
201 cache_[font_name].ref_count_ = 1;
202 } else { // Requested font is already in cache, release old handles.
203 DeleteObject(cache_[font_name].font_);
204 DeleteDC(cache_[font_name].dc_);
205 }
206 cache_[font_name].font_ = font_handle;
207 cache_[font_name].dc_ = hdc;
208 cache_[font_name].ref_count_ += ref_count_inc;
209 }
210
211 void ChildProcessHost::FontCache::ReleaseCachedFonts(int process_id) {
212 typedef std::map<string16, ChildProcessHost::FontCache::CacheElement>
213 FontNameToElement;
214
215 base::AutoLock lock(mutex_);
216
217 PidToFontNames::iterator it;
218 it = process_id_font_map_.find(process_id);
219 if (it == process_id_font_map_.end()) {
220 return;
221 }
222
223 for (FontNameVector::iterator i = it->second.begin(), e = it->second.end();
224 i != e; ++i) {
225 FontNameToElement::iterator element;
226 element = cache_.find(*i);
227 if (element != cache_.end()) {
228 --((*element).second.ref_count_);
229 }
230 }
231
232 process_id_font_map_.erase(it);
233 for (FontNameToElement::iterator i = cache_.begin(); i != cache_.end(); ) {
234 if (i->second.ref_count_ == 0) {
235 cache_.erase(i++);
236 } else {
237 ++i;
238 }
239 }
240 }
241
242 // static
243 void ChildProcessHost::PreCacheFont(LOGFONT font, int pid) {
244 // If a child process is running in a sandbox, GetTextMetrics()
245 // can sometimes fail. If a font has not been loaded
246 // previously, GetTextMetrics() will try to load the font
247 // from the font file. However, the sandboxed process does
248 // not have permissions to access any font files and
249 // the call fails. So we make the browser pre-load the
250 // font for us by using a dummy call to GetTextMetrics of
251 // the same font.
252 // This means the browser process just loads the font into memory so that
253 // when GDI attempt to query that font info in child process, it does not
254 // need to load that file, hence no permission issues there. Therefore,
255 // when a font is asked to be cached, we always recreates the font object
256 // to avoid the case that an in-cache font is swapped out by GDI.
257 ChildProcessHost::FontCache::GetInstance()->PreCacheFont(font, pid);
258 }
259
260 // static
261 void ChildProcessHost::ReleaseCachedFonts(int pid) {
262 // Release cached fonts that requested from a pid by decrementing the ref
263 // count. When ref count is zero, the handles are released.
264 ChildProcessHost::FontCache::GetInstance()->ReleaseCachedFonts(pid);
265 }
266 #endif // OS_WIN
267
268 void ChildProcessHost::ForceShutdown() { 139 void ChildProcessHost::ForceShutdown() {
269 Send(new ChildProcessMsg_Shutdown()); 140 Send(new ChildProcessMsg_Shutdown());
270 } 141 }
271 142
272 bool ChildProcessHost::CreateChannel() { 143 bool ChildProcessHost::CreateChannel() {
273 channel_id_ = ChildProcessInfo::GenerateRandomChannelID(this); 144 channel_id_ = ChildProcessInfo::GenerateRandomChannelID(this);
274 channel_.reset(new IPC::Channel( 145 channel_.reset(new IPC::Channel(
275 channel_id_, IPC::Channel::MODE_SERVER, &listener_)); 146 channel_id_, IPC::Channel::MODE_SERVER, &listener_));
276 if (!channel_->Connect()) 147 if (!channel_->Connect())
277 return false; 148 return false;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 uint32 buffer_size, 295 uint32 buffer_size,
425 base::SharedMemoryHandle* handle) { 296 base::SharedMemoryHandle* handle) {
426 ChildProcessHost::OnAllocateSharedMemory( 297 ChildProcessHost::OnAllocateSharedMemory(
427 buffer_size, peer_handle_, handle); 298 buffer_size, peer_handle_, handle);
428 } 299 }
429 300
430 void ChildProcessHost::ListenerHook::OnShutdownRequest() { 301 void ChildProcessHost::ListenerHook::OnShutdownRequest() {
431 if (host_->CanShutdown()) 302 if (host_->CanShutdown())
432 host_->Send(new ChildProcessMsg_Shutdown()); 303 host_->Send(new ChildProcessMsg_Shutdown());
433 } 304 }
OLDNEW
« no previous file with comments | « content/common/child_process_host.h ('k') | content/common/font_cache_dispatcher_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698