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