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

Side by Side Diff: content/common/child_process_host.cc

Issue 7866019: New implementation of font precache on Windows. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Update per code review Created 9 years, 3 months 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
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"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 // intolerant of a non-executable heap to work properly on 10.7. This 124 // intolerant of a non-executable heap to work properly on 10.7. This
125 // results in Chromium Helper EH.app or Google Chrome Helper EH.app. 125 // results in Chromium Helper EH.app or Google Chrome Helper EH.app.
126 child_path = TransformPathForFeature(child_path, "EH"); 126 child_path = TransformPathForFeature(child_path, "EH");
127 } 127 }
128 #endif 128 #endif
129 129
130 return child_path; 130 return child_path;
131 } 131 }
132 132
133 #if defined(OS_WIN) 133 #if defined(OS_WIN)
134 ChildProcessHost::FontCache::CacheElement::CacheElement()
135 : font_(NULL), dc_(NULL), ref_count_(0) {
136 }
137
138 ChildProcessHost::FontCache::CacheElement::~CacheElement() {
139 if (font_) {
140 DeleteObject(font_);
141 }
142 if (dc_) {
143 DeleteDC(dc_);
144 }
145 }
146
134 // static 147 // static
135 void ChildProcessHost::PreCacheFont(LOGFONT font) { 148 ChildProcessHost::FontCache* ChildProcessHost::FontCache::GetInstance() {
136 // If a child process is running in a sandbox, GetTextMetrics() 149 return Singleton<ChildProcessHost::FontCache>::get();
137 // can sometimes fail. If a font has not been loaded 150 }
138 // previously, GetTextMetrics() will try to load the font
139 // from the font file. However, the sandboxed process does
140 // not have permissions to access any font files and
141 // the call fails. So we make the browser pre-load the
142 // font for us by using a dummy call to GetTextMetrics of
143 // the same font.
144 151
145 // Maintain a circular queue for the fonts and DCs to be cached. 152 void ChildProcessHost::FontCache::PreCacheFont(LOGFONT font, int pid) {
146 // font_index maintains next available location in the queue. 153 typedef std::map<std::wstring, ChildProcessHost::FontCache::CacheElement>
147 static const int kFontCacheSize = 32; 154 FontNameToElement;
148 static HFONT fonts[kFontCacheSize] = {0};
149 static HDC hdcs[kFontCacheSize] = {0};
150 static size_t font_index = 0;
151 155
152 UMA_HISTOGRAM_COUNTS_100("Memory.CachedFontAndDC", 156 base::AutoLock lock(mutex_);
153 fonts[kFontCacheSize-1] ? kFontCacheSize : static_cast<int>(font_index));
154 157
158 // Fetch the font into memory
155 HDC hdc = GetDC(NULL); 159 HDC hdc = GetDC(NULL);
156 HFONT font_handle = CreateFontIndirect(&font); 160 HFONT font_handle = CreateFontIndirect(&font);
157 DCHECK(NULL != font_handle); 161 DCHECK(NULL != font_handle);
158 162
159 HGDIOBJ old_font = SelectObject(hdc, font_handle); 163 HGDIOBJ old_font = SelectObject(hdc, font_handle);
160 DCHECK(NULL != old_font); 164 DCHECK(NULL != old_font);
161 165
162 TEXTMETRIC tm; 166 TEXTMETRIC tm;
163 BOOL ret = GetTextMetrics(hdc, &tm); 167 BOOL ret = GetTextMetrics(hdc, &tm);
164 DCHECK(ret); 168 DCHECK(ret);
165 169
166 if (fonts[font_index] || hdcs[font_index]) { 170 std::wstring font_name = font.lfFaceName;
167 // We already have too many fonts, we will delete one and take it's place. 171 int ref_count_inc = 1;
168 DeleteObject(fonts[font_index]); 172 FontNameVector::iterator it = std::find(pid_font_map_[pid].begin(),
169 ReleaseDC(NULL, hdcs[font_index]); 173 pid_font_map_[pid].end(),
174 font_name);
175 if (it == pid_font_map_[pid].end()) { // New font
176 pid_font_map_[pid].push_back(font_name);
177 } else {
178 ref_count_inc = 0;
170 } 179 }
171 180
172 fonts[font_index] = font_handle; 181 if (cache_[font_name].ref_count_ == 0) { // New element
173 hdcs[font_index] = hdc; 182 cache_[font_name].ref_count_ = 1;
174 font_index = (font_index + 1) % kFontCacheSize; 183 } else {
184 DeleteObject(cache_[font_name].font_);
185 DeleteDC(cache_[font_name].dc_);
186 }
187 cache_[font_name].font_ = font_handle;
188 cache_[font_name].dc_ = hdc;
189 cache_[font_name].ref_count_ += ref_count_inc;
190 }
191
192 void ChildProcessHost::FontCache::ReleaseCachedFont(int pid) {
193 typedef std::map<std::wstring, ChildProcessHost::FontCache::CacheElement>
194 FontNameToElement;
195
196 base::AutoLock lock(mutex_);
197
198 PidToFontNames::iterator it;
199 it = pid_font_map_.find(pid);
200 if (it == pid_font_map_.end()) {
201 return;
202 }
203
204 for (FontNameVector::iterator i = it->second.begin(), e = it->second.end();
205 i != e; ++i) {
206 FontNameToElement::iterator element;
207 element = cache_.find(*i);
208 if (element != cache_.end()) {
209 --((*element).second.ref_count_);
210 }
211 }
212
213 pid_font_map_.erase(it);
214 for (FontNameToElement::iterator i = cache_.begin(); i != cache_.end(); ) {
215 if (i->second.ref_count_ == 0) {
216 cache_.erase(i++);
217 } else {
218 ++i;
219 }
220 }
221 }
222
223 // static
224 void ChildProcessHost::PreCacheFont(LOGFONT font, int pid) {
225 // If a child process is running in a sandbox, GetTextMetrics()
226 // can sometimes fail. If a font has not been loaded
227 // previously, GetTextMetrics() will try to load the font
228 // from the font file. However, the sandboxed process does
229 // not have permissions to access any font files and
230 // the call fails. So we make the browser pre-load the
231 // font for us by using a dummy call to GetTextMetrics of
232 // the same font.
233 ChildProcessHost::FontCache::GetInstance()->PreCacheFont(font, pid);
234 }
235
236 // static
237 void ChildProcessHost::ReleaseCachedFont(int pid) {
238 ChildProcessHost::FontCache::GetInstance()->ReleaseCachedFont(pid);
175 } 239 }
176 #endif // OS_WIN 240 #endif // OS_WIN
177 241
178 242
179 bool ChildProcessHost::CreateChannel() { 243 bool ChildProcessHost::CreateChannel() {
180 channel_id_ = ChildProcessInfo::GenerateRandomChannelID(this); 244 channel_id_ = ChildProcessInfo::GenerateRandomChannelID(this);
181 channel_.reset(new IPC::Channel( 245 channel_.reset(new IPC::Channel(
182 channel_id_, IPC::Channel::MODE_SERVER, &listener_)); 246 channel_id_, IPC::Channel::MODE_SERVER, &listener_));
183 if (!channel_->Connect()) 247 if (!channel_->Connect())
184 return false; 248 return false;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 for (size_t i = 0; i < host_->filters_.size(); ++i) 364 for (size_t i = 0; i < host_->filters_.size(); ++i)
301 host_->filters_[i]->OnChannelError(); 365 host_->filters_[i]->OnChannelError();
302 366
303 // This will delete host_, which will also destroy this! 367 // This will delete host_, which will also destroy this!
304 host_->OnChildDied(); 368 host_->OnChildDied();
305 } 369 }
306 370
307 void ChildProcessHost::ForceShutdown() { 371 void ChildProcessHost::ForceShutdown() {
308 Send(new ChildProcessMsg_Shutdown()); 372 Send(new ChildProcessMsg_Shutdown());
309 } 373 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698