OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/printing/pdf_to_emf_converter.h" | 5 #include "chrome/browser/printing/pdf_to_emf_converter.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <windows.h> |
8 | 9 |
9 #include <memory> | 10 #include <memory> |
10 #include <queue> | 11 #include <queue> |
11 #include <utility> | 12 #include <utility> |
12 | 13 |
13 #include "base/files/file.h" | 14 #include "base/files/file.h" |
14 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
15 #include "base/files/scoped_temp_dir.h" | 16 #include "base/files/scoped_temp_dir.h" |
16 #include "base/logging.h" | 17 #include "base/logging.h" |
17 #include "base/macros.h" | 18 #include "base/macros.h" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 // All these steps work sequentially, so no data should be accessed | 99 // All these steps work sequentially, so no data should be accessed |
99 // simultaneously by several threads. | 100 // simultaneously by several threads. |
100 class PdfToEmfUtilityProcessHostClient | 101 class PdfToEmfUtilityProcessHostClient |
101 : public content::UtilityProcessHostClient { | 102 : public content::UtilityProcessHostClient { |
102 public: | 103 public: |
103 PdfToEmfUtilityProcessHostClient( | 104 PdfToEmfUtilityProcessHostClient( |
104 base::WeakPtr<PdfToEmfConverterImpl> converter, | 105 base::WeakPtr<PdfToEmfConverterImpl> converter, |
105 const PdfRenderSettings& settings); | 106 const PdfRenderSettings& settings); |
106 | 107 |
107 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 108 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
| 109 bool print_text_with_gdi, |
108 const PdfToEmfConverter::StartCallback& start_callback); | 110 const PdfToEmfConverter::StartCallback& start_callback); |
109 | 111 |
110 void GetPage(int page_number, | 112 void GetPage(int page_number, |
111 const PdfToEmfConverter::GetPageCallback& get_page_callback); | 113 const PdfToEmfConverter::GetPageCallback& get_page_callback); |
112 | 114 |
113 void Stop(); | 115 void Stop(); |
114 | 116 |
| 117 // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters |
| 118 // sync message replies. |
| 119 bool Send(IPC::Message* msg); |
| 120 |
115 // UtilityProcessHostClient implementation. | 121 // UtilityProcessHostClient implementation. |
116 void OnProcessCrashed(int exit_code) override; | 122 void OnProcessCrashed(int exit_code) override; |
117 void OnProcessLaunchFailed(int exit_code) override; | 123 void OnProcessLaunchFailed(int exit_code) override; |
118 bool OnMessageReceived(const IPC::Message& message) override; | 124 bool OnMessageReceived(const IPC::Message& message) override; |
119 | 125 |
120 private: | 126 private: |
121 class GetPageCallbackData { | 127 class GetPageCallbackData { |
122 public: | 128 public: |
123 GetPageCallbackData(int page_number, | 129 GetPageCallbackData(int page_number, |
124 PdfToEmfConverter::GetPageCallback callback) | 130 PdfToEmfConverter::GetPageCallback callback) |
(...skipping 20 matching lines...) Expand all Loading... |
145 private: | 151 private: |
146 int page_number_; | 152 int page_number_; |
147 PdfToEmfConverter::GetPageCallback callback_; | 153 PdfToEmfConverter::GetPageCallback callback_; |
148 ScopedTempFile emf_; | 154 ScopedTempFile emf_; |
149 | 155 |
150 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); | 156 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); |
151 }; | 157 }; |
152 | 158 |
153 ~PdfToEmfUtilityProcessHostClient() override; | 159 ~PdfToEmfUtilityProcessHostClient() override; |
154 | 160 |
155 bool Send(IPC::Message* msg); | |
156 | |
157 // Message handlers. | 161 // Message handlers. |
158 void OnPageCount(int page_count); | 162 void OnPageCount(int page_count); |
159 void OnPageDone(bool success, float scale_factor); | 163 void OnPageDone(bool success, float scale_factor); |
| 164 void OnPreCacheFontCharacters(const LOGFONT& log_font, |
| 165 const base::string16& characters); |
160 | 166 |
161 void OnFailed(); | 167 void OnFailed(); |
162 void OnTempPdfReady(ScopedTempFile pdf); | 168 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); |
163 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); | 169 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); |
164 | 170 |
165 scoped_refptr<RefCountedTempDir> temp_dir_; | 171 scoped_refptr<RefCountedTempDir> temp_dir_; |
166 | 172 |
167 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. | 173 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. |
168 base::WeakPtr<PdfToEmfConverterImpl> converter_; | 174 base::WeakPtr<PdfToEmfConverterImpl> converter_; |
169 PdfRenderSettings settings_; | 175 PdfRenderSettings settings_; |
170 | 176 |
171 // Document loaded callback. | 177 // Document loaded callback. |
172 PdfToEmfConverter::StartCallback start_callback_; | 178 PdfToEmfConverter::StartCallback start_callback_; |
(...skipping 11 matching lines...) Expand all Loading... |
184 }; | 190 }; |
185 | 191 |
186 class PdfToEmfConverterImpl : public PdfToEmfConverter { | 192 class PdfToEmfConverterImpl : public PdfToEmfConverter { |
187 public: | 193 public: |
188 PdfToEmfConverterImpl(); | 194 PdfToEmfConverterImpl(); |
189 | 195 |
190 ~PdfToEmfConverterImpl() override; | 196 ~PdfToEmfConverterImpl() override; |
191 | 197 |
192 void Start(const scoped_refptr<base::RefCountedMemory>& data, | 198 void Start(const scoped_refptr<base::RefCountedMemory>& data, |
193 const PdfRenderSettings& conversion_settings, | 199 const PdfRenderSettings& conversion_settings, |
| 200 bool print_text_with_gdi, |
194 const StartCallback& start_callback) override; | 201 const StartCallback& start_callback) override; |
195 | 202 |
196 void GetPage(int page_number, | 203 void GetPage(int page_number, |
197 const GetPageCallback& get_page_callback) override; | 204 const GetPageCallback& get_page_callback) override; |
198 | 205 |
199 // Helps to cancel callbacks if this object is destroyed. | 206 // Helps to cancel callbacks if this object is destroyed. |
200 void RunCallback(const base::Closure& callback); | 207 void RunCallback(const base::Closure& callback); |
201 | 208 |
202 private: | 209 private: |
203 scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_; | 210 scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 base::WeakPtr<PdfToEmfConverterImpl> converter, | 290 base::WeakPtr<PdfToEmfConverterImpl> converter, |
284 const PdfRenderSettings& settings) | 291 const PdfRenderSettings& settings) |
285 : converter_(converter), settings_(settings) { | 292 : converter_(converter), settings_(settings) { |
286 } | 293 } |
287 | 294 |
288 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { | 295 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { |
289 } | 296 } |
290 | 297 |
291 void PdfToEmfUtilityProcessHostClient::Start( | 298 void PdfToEmfUtilityProcessHostClient::Start( |
292 const scoped_refptr<base::RefCountedMemory>& data, | 299 const scoped_refptr<base::RefCountedMemory>& data, |
| 300 bool print_text_with_gdi, |
293 const PdfToEmfConverter::StartCallback& start_callback) { | 301 const PdfToEmfConverter::StartCallback& start_callback) { |
294 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 302 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
295 BrowserThread::PostTask(BrowserThread::IO, | 303 BrowserThread::PostTask( |
296 FROM_HERE, | 304 BrowserThread::IO, FROM_HERE, |
297 base::Bind(&PdfToEmfUtilityProcessHostClient::Start, | 305 base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data, |
298 this, | 306 print_text_with_gdi, start_callback)); |
299 data, | |
300 start_callback)); | |
301 return; | 307 return; |
302 } | 308 } |
303 | 309 |
304 // Store callback before any OnFailed() call to make it called on failure. | 310 // Store callback before any OnFailed() call to make it called on failure. |
305 start_callback_ = start_callback; | 311 start_callback_ = start_callback; |
306 | 312 |
307 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load | 313 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load |
308 // gdiplus.dll, change how rendering happens, and not be able to correctly | 314 // gdiplus.dll, change how rendering happens, and not be able to correctly |
309 // generate when sent to a metafile DC. | 315 // generate when sent to a metafile DC. |
310 utility_process_host_ = content::UtilityProcessHost::Create( | 316 utility_process_host_ = content::UtilityProcessHost::Create( |
311 this, base::ThreadTaskRunnerHandle::Get()) | 317 this, base::ThreadTaskRunnerHandle::Get()) |
312 ->AsWeakPtr(); | 318 ->AsWeakPtr(); |
313 utility_process_host_->SetName(l10n_util::GetStringUTF16( | 319 utility_process_host_->SetName(l10n_util::GetStringUTF16( |
314 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); | 320 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); |
315 | 321 |
316 BrowserThread::PostTaskAndReplyWithResult( | 322 BrowserThread::PostTaskAndReplyWithResult( |
317 BrowserThread::FILE, | 323 BrowserThread::FILE, FROM_HERE, |
318 FROM_HERE, | |
319 base::Bind(&CreateTempPdfFile, data, &temp_dir_), | 324 base::Bind(&CreateTempPdfFile, data, &temp_dir_), |
320 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this)); | 325 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, |
| 326 print_text_with_gdi)); |
321 } | 327 } |
322 | 328 |
323 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) { | 329 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, |
| 330 ScopedTempFile pdf) { |
324 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 331 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
325 if (!utility_process_host_ || !pdf) | 332 if (!utility_process_host_ || !pdf) |
326 return OnFailed(); | 333 return OnFailed(); |
327 // Should reply with OnPageCount(). | 334 // Should reply with OnPageCount(). |
328 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( | 335 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( |
329 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), | 336 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_, |
330 settings_)); | 337 print_text_with_gdi)); |
331 } | 338 } |
332 | 339 |
333 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { | 340 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { |
334 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 341 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
335 if (start_callback_.is_null()) | 342 if (start_callback_.is_null()) |
336 return OnFailed(); | 343 return OnFailed(); |
337 BrowserThread::PostTask(BrowserThread::UI, | 344 BrowserThread::PostTask(BrowserThread::UI, |
338 FROM_HERE, | 345 FROM_HERE, |
339 base::Bind(&PdfToEmfConverterImpl::RunCallback, | 346 base::Bind(&PdfToEmfConverterImpl::RunCallback, |
340 converter_, | 347 converter_, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 FROM_HERE, | 411 FROM_HERE, |
405 base::Bind(&PdfToEmfConverterImpl::RunCallback, | 412 base::Bind(&PdfToEmfConverterImpl::RunCallback, |
406 converter_, | 413 converter_, |
407 base::Bind(data.callback(), | 414 base::Bind(data.callback(), |
408 data.page_number(), | 415 data.page_number(), |
409 scale_factor, | 416 scale_factor, |
410 base::Passed(&emf)))); | 417 base::Passed(&emf)))); |
411 get_page_callbacks_.pop(); | 418 get_page_callbacks_.pop(); |
412 } | 419 } |
413 | 420 |
| 421 void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( |
| 422 const LOGFONT& font, |
| 423 const base::string16& str) { |
| 424 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache |
| 425 // GDI fonts (http://crbug.com/383227), even when using DirectWrite. |
| 426 // Eventually this shouldn't be added and should be moved to |
| 427 // FontCacheDispatcher too. http://crbug.com/356346. |
| 428 |
| 429 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. |
| 430 // Except that for True Type fonts, |
| 431 // GetTextMetrics will not load the font in memory. |
| 432 // The only way windows seem to load properly, it is to create a similar |
| 433 // device (like the one in which we print), then do an ExtTextOut, |
| 434 // as we do in the printing thread, which is sandboxed. |
| 435 HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr); |
| 436 HFONT font_handle = CreateFontIndirect(&font); |
| 437 DCHECK(font_handle != nullptr); |
| 438 |
| 439 HGDIOBJ old_font = SelectObject(hdc, font_handle); |
| 440 DCHECK(old_font != nullptr); |
| 441 |
| 442 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr); |
| 443 |
| 444 SelectObject(hdc, old_font); |
| 445 DeleteObject(font_handle); |
| 446 |
| 447 HENHMETAFILE metafile = CloseEnhMetaFile(hdc); |
| 448 |
| 449 if (metafile) |
| 450 DeleteEnhMetaFile(metafile); |
| 451 } |
| 452 |
414 void PdfToEmfUtilityProcessHostClient::Stop() { | 453 void PdfToEmfUtilityProcessHostClient::Stop() { |
415 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 454 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
416 BrowserThread::PostTask( | 455 BrowserThread::PostTask( |
417 BrowserThread::IO, | 456 BrowserThread::IO, |
418 FROM_HERE, | 457 FROM_HERE, |
419 base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this)); | 458 base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this)); |
420 return; | 459 return; |
421 } | 460 } |
422 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); | 461 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); |
423 } | 462 } |
424 | 463 |
425 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) { | 464 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) { |
426 OnFailed(); | 465 OnFailed(); |
427 } | 466 } |
428 | 467 |
429 void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed(int exit_code) { | 468 void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed(int exit_code) { |
430 OnFailed(); | 469 OnFailed(); |
431 } | 470 } |
432 | 471 |
433 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( | 472 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( |
434 const IPC::Message& message) { | 473 const IPC::Message& message) { |
435 bool handled = true; | 474 bool handled = true; |
436 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) | 475 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) |
437 IPC_MESSAGE_HANDLER( | 476 IPC_MESSAGE_HANDLER( |
438 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) | 477 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) |
439 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, | 478 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, |
440 OnPageDone) | 479 OnPageDone) |
| 480 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters, |
| 481 OnPreCacheFontCharacters) |
441 IPC_MESSAGE_UNHANDLED(handled = false) | 482 IPC_MESSAGE_UNHANDLED(handled = false) |
442 IPC_END_MESSAGE_MAP() | 483 IPC_END_MESSAGE_MAP() |
443 return handled; | 484 return handled; |
444 } | 485 } |
445 | 486 |
446 bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) { | 487 bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) { |
447 if (utility_process_host_) | 488 if (utility_process_host_) |
448 return utility_process_host_->Send(msg); | 489 return utility_process_host_->Send(msg); |
449 delete msg; | 490 delete msg; |
450 return false; | 491 return false; |
(...skipping 12 matching lines...) Expand all Loading... |
463 } | 504 } |
464 | 505 |
465 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { | 506 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { |
466 if (utility_client_.get()) | 507 if (utility_client_.get()) |
467 utility_client_->Stop(); | 508 utility_client_->Stop(); |
468 } | 509 } |
469 | 510 |
470 void PdfToEmfConverterImpl::Start( | 511 void PdfToEmfConverterImpl::Start( |
471 const scoped_refptr<base::RefCountedMemory>& data, | 512 const scoped_refptr<base::RefCountedMemory>& data, |
472 const PdfRenderSettings& conversion_settings, | 513 const PdfRenderSettings& conversion_settings, |
| 514 bool print_text_with_gdi, |
473 const StartCallback& start_callback) { | 515 const StartCallback& start_callback) { |
474 DCHECK(!utility_client_.get()); | 516 DCHECK(!utility_client_.get()); |
475 utility_client_ = new PdfToEmfUtilityProcessHostClient( | 517 utility_client_ = new PdfToEmfUtilityProcessHostClient( |
476 weak_ptr_factory_.GetWeakPtr(), conversion_settings); | 518 weak_ptr_factory_.GetWeakPtr(), conversion_settings); |
477 utility_client_->Start(data, start_callback); | 519 utility_client_->Start(data, print_text_with_gdi, start_callback); |
478 } | 520 } |
479 | 521 |
480 void PdfToEmfConverterImpl::GetPage(int page_number, | 522 void PdfToEmfConverterImpl::GetPage(int page_number, |
481 const GetPageCallback& get_page_callback) { | 523 const GetPageCallback& get_page_callback) { |
482 utility_client_->GetPage(page_number, get_page_callback); | 524 utility_client_->GetPage(page_number, get_page_callback); |
483 } | 525 } |
484 | 526 |
485 void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) { | 527 void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) { |
486 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 528 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
487 callback.Run(); | 529 callback.Run(); |
488 } | 530 } |
489 | 531 |
490 } // namespace | 532 } // namespace |
491 | 533 |
492 PdfToEmfConverter::~PdfToEmfConverter() { | 534 PdfToEmfConverter::~PdfToEmfConverter() { |
493 } | 535 } |
494 | 536 |
495 // static | 537 // static |
496 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { | 538 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { |
497 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); | 539 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); |
498 } | 540 } |
499 | 541 |
500 } // namespace printing | 542 } // namespace printing |
OLD | NEW |