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

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

Powered by Google App Engine
This is Rietveld 408576698