Chromium Code Reviews| Index: chrome/browser/printing/pdf_to_emf_converter.cc |
| diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc |
| index 64dfd014402e59a81918ff4c907530908f204542..81518773a05e2623d2305007c62995f71f8c6be1 100644 |
| --- a/chrome/browser/printing/pdf_to_emf_converter.cc |
| +++ b/chrome/browser/printing/pdf_to_emf_converter.cc |
| @@ -91,6 +91,21 @@ class LazyEmf : public MetafilePlayer { |
| DISALLOW_COPY_AND_ASSIGN(LazyEmf); |
| }; |
| +// Postscript metafile subclass to override SafePlayback. |
| +class PostScriptMetaFile : public LazyEmf { |
| + public: |
| + PostScriptMetaFile(const scoped_refptr<RefCountedTempDir>& temp_dir, |
| + ScopedTempFile file) |
| + : LazyEmf(temp_dir, std::move(file)) {} |
| + ~PostScriptMetaFile() override; |
| + |
| + protected: |
| + // MetafilePlayer: |
| + bool SafePlayback(HDC hdc) const override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PostScriptMetaFile); |
| +}; |
| + |
| // Class for converting PDF to another format for printing (Emf, Postscript). |
| // Class uses 3 threads: UI, IO and FILE. |
| // Internal workflow is following: |
| @@ -160,18 +175,20 @@ class PdfConverterUtilityProcessHostClient |
| ~PdfConverterUtilityProcessHostClient() override; |
| + bool OnMessageReceived(const IPC::Message& message) override; |
| + |
| // Helper functions: must be overridden by subclasses |
| // Set the process name |
| - virtual base::string16 GetName() const = 0; |
| + virtual base::string16 GetName() const; |
| // Create a metafileplayer subclass file from a temporary file. |
| virtual std::unique_ptr<MetafilePlayer> GetFileFromTemp( |
| std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
| - temp_file) = 0; |
| + temp_file); |
| // Send the messages to Start, GetPage, and Stop. |
| - virtual void SendStartMessage(IPC::PlatformFileForTransit transit) = 0; |
| + virtual void SendStartMessage(IPC::PlatformFileForTransit transit); |
| virtual void SendGetPageMessage(int page_number, |
| - IPC::PlatformFileForTransit transit) = 0; |
| - virtual void SendStopMessage() = 0; |
| + IPC::PlatformFileForTransit transit); |
| + virtual void SendStopMessage(); |
| // Message handlers: |
| void OnPageCount(int page_count); |
| @@ -182,6 +199,10 @@ class PdfConverterUtilityProcessHostClient |
| void OnTempFileReady(GetPageCallbackData* callback_data, |
| ScopedTempFile temp_file); |
| + // Additional message handler needed for Pdf to Emf |
| + void OnPreCacheFontCharacters(const LOGFONT& log_font, |
| + const base::string16& characters); |
| + |
| scoped_refptr<RefCountedTempDir> temp_dir_; |
| // Used to suppress callbacks after PdfConverter is deleted. |
| @@ -199,46 +220,35 @@ class PdfConverterUtilityProcessHostClient |
| // Use containers that keeps element pointers valid after push() and pop(). |
| using GetPageCallbacks = std::queue<GetPageCallbackData>; |
| GetPageCallbacks get_page_callbacks_; |
| -}; |
| - |
| -// Converts PDF into Emf. |
| -class PdfToEmfUtilityProcessHostClient |
| - : public PdfConverterUtilityProcessHostClient { |
| - public: |
| - PdfToEmfUtilityProcessHostClient(base::WeakPtr<PdfConverterImpl> converter, |
| - const PdfRenderSettings& settings) |
| - : PdfConverterUtilityProcessHostClient(converter, settings) {} |
| - |
| - bool OnMessageReceived(const IPC::Message& message) override; |
| - private: |
| - ~PdfToEmfUtilityProcessHostClient() override; |
| - // Helpers to send messages and set process name |
| - base::string16 GetName() const override; |
| - std::unique_ptr<MetafilePlayer> GetFileFromTemp( |
| - std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
| - temp_file) override; |
| - void SendStartMessage(IPC::PlatformFileForTransit transit) override; |
| - void SendGetPageMessage(int page_number, |
| - IPC::PlatformFileForTransit transit) override; |
| - void SendStopMessage() override; |
| - |
| - // Additional message handler needed for Pdf to Emf |
| - void OnPreCacheFontCharacters(const LOGFONT& log_font, |
| - const base::string16& characters); |
| - |
| - DISALLOW_COPY_AND_ASSIGN(PdfToEmfUtilityProcessHostClient); |
| + DISALLOW_COPY_AND_ASSIGN(PdfConverterUtilityProcessHostClient); |
| }; |
| +std::unique_ptr<MetafilePlayer> |
| +PdfConverterUtilityProcessHostClient::GetFileFromTemp( |
| + std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
| + temp_file) { |
| + if (settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 || |
| + settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3) { |
| + return base::MakeUnique<PostScriptMetaFile>(temp_dir_, |
| + std::move(temp_file)); |
| + } |
| + return base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_file)); |
| +} |
| + |
| class PdfConverterImpl : public PdfConverter { |
| public: |
| - PdfConverterImpl(); |
| + PdfConverterImpl(); // : weak_ptr_factory_(this) {} |
|
Vitaly Buka (NO REVIEWS)
2017/01/28 01:23:58
please remove comment
rbpotter
2017/01/28 02:02:00
Done.
|
| ~PdfConverterImpl() override; |
| + base::WeakPtr<PdfConverterImpl> GetWeakPtr() { |
| + return weak_ptr_factory_.GetWeakPtr(); |
| + } |
| + |
| void Start(const scoped_refptr<base::RefCountedMemory>& data, |
| const PdfRenderSettings& conversion_settings, |
| - const StartCallback& start_callback) override; |
| + const StartCallback& start_callback); |
| void GetPage(int page_number, |
| const GetPageCallback& get_page_callback) override; |
| @@ -246,27 +256,17 @@ class PdfConverterImpl : public PdfConverter { |
| // Helps to cancel callbacks if this object is destroyed. |
| void RunCallback(const base::Closure& callback); |
| - protected: |
| - scoped_refptr<PdfConverterUtilityProcessHostClient> utility_client_; |
| + void Start( |
| + const scoped_refptr<PdfConverterUtilityProcessHostClient>& utility_client, |
| + const scoped_refptr<base::RefCountedMemory>& data, |
| + const StartCallback& start_callback); |
| private: |
| - DISALLOW_COPY_AND_ASSIGN(PdfConverterImpl); |
| -}; |
| - |
| -class PdfToEmfConverterImpl : public PdfConverterImpl { |
| - public: |
| - PdfToEmfConverterImpl(); |
| - |
| - ~PdfToEmfConverterImpl() override; |
| - |
| - void Start(const scoped_refptr<base::RefCountedMemory>& data, |
| - const PdfRenderSettings& conversion_settings, |
| - const StartCallback& start_callback) override; |
| + scoped_refptr<PdfConverterUtilityProcessHostClient> utility_client_; |
| - private: |
| - base::WeakPtrFactory<PdfToEmfConverterImpl> weak_ptr_factory_; |
| + base::WeakPtrFactory<PdfConverterImpl> weak_ptr_factory_; |
| - DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterImpl); |
| + DISALLOW_COPY_AND_ASSIGN(PdfConverterImpl); |
| }; |
| ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) { |
| @@ -347,6 +347,40 @@ bool LazyEmf::LoadEmf(Emf* emf) const { |
| return emf->InitFromData(data.data(), data.size()); |
| } |
| +PostScriptMetaFile::~PostScriptMetaFile() { |
| +} |
| + |
| +bool PostScriptMetaFile::SafePlayback(HDC hdc) const { |
| + // TODO(thestig): Fix destruction of metafiles. For some reasons |
| + // instances of Emf are not deleted. https://crbug.com/260806 |
| + // It's known that the Emf going to be played just once to a printer. So just |
| + // release |file_| before returning. |
| + Emf emf; |
| + if (!LoadEmf(&emf)) { |
| + Close(); |
| + return false; |
| + } |
| + |
| + { |
| + // Ensure enumerator destruction before calling Close() below. |
| + Emf::Enumerator emf_enum(emf, nullptr, nullptr); |
| + for (const Emf::Record& record : emf_enum) { |
| + auto* emf_record = record.record(); |
| + if (emf_record->iType != EMR_GDICOMMENT) |
| + continue; |
| + |
| + const EMRGDICOMMENT* comment = |
| + reinterpret_cast<const EMRGDICOMMENT*>(emf_record); |
| + const char* data = reinterpret_cast<const char*>(comment->Data); |
| + const uint16_t* ptr = reinterpret_cast<const uint16_t*>(data); |
| + int ret = ExtEscape(hdc, PASSTHROUGH, 2 + *ptr, data, 0, nullptr); |
| + DCHECK_EQ(*ptr, ret); |
| + } |
| + } |
| + Close(); |
| + return true; |
| +} |
| + |
| PdfConverterUtilityProcessHostClient::PdfConverterUtilityProcessHostClient( |
| base::WeakPtr<PdfConverterImpl> converter, |
| const PdfRenderSettings& settings) |
| @@ -464,7 +498,7 @@ void PdfConverterUtilityProcessHostClient::Stop() { |
| if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| - base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this)); |
| + base::Bind(&PdfConverterUtilityProcessHostClient::Stop, this)); |
| return; |
| } |
| SendStopMessage(); |
| @@ -495,10 +529,8 @@ void PdfConverterUtilityProcessHostClient::OnFailed() { |
| utility_process_host_.reset(); |
| } |
| -// PDF to Emf |
| -PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {} |
| -void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( |
| +void PdfConverterUtilityProcessHostClient::OnPreCacheFontCharacters( |
| const LOGFONT& font, |
| const base::string16& str) { |
| // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache |
| @@ -530,10 +562,10 @@ void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( |
| DeleteEnhMetaFile(metafile); |
| } |
| -bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( |
| +bool PdfConverterUtilityProcessHostClient::OnMessageReceived( |
| const IPC::Message& message) { |
| bool handled = true; |
| - IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) |
| + IPC_BEGIN_MESSAGE_MAP(PdfConverterUtilityProcessHostClient, message) |
| IPC_MESSAGE_HANDLER( |
| ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) |
| IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, |
| @@ -545,42 +577,44 @@ bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( |
| return handled; |
| } |
| -base::string16 PdfToEmfUtilityProcessHostClient::GetName() const { |
| - return l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME); |
| +base::string16 PdfConverterUtilityProcessHostClient::GetName() const { |
| + return l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_PDF_CONVERTOR_NAME); |
| } |
| -std::unique_ptr<MetafilePlayer> |
| -PdfToEmfUtilityProcessHostClient::GetFileFromTemp( |
| - std::unique_ptr<base::File, content::BrowserThread::DeleteOnFileThread> |
| - temp_file) { |
| - return base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_file)); |
| -} |
| - |
| -void PdfToEmfUtilityProcessHostClient::SendGetPageMessage( |
| +void PdfConverterUtilityProcessHostClient::SendGetPageMessage( |
| int page_number, |
| IPC::PlatformFileForTransit transit) { |
| Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(page_number, |
| transit)); |
| } |
| -void PdfToEmfUtilityProcessHostClient::SendStartMessage( |
| +void PdfConverterUtilityProcessHostClient::SendStartMessage( |
| IPC::PlatformFileForTransit transit) { |
| Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(transit, settings_)); |
| } |
| -void PdfToEmfUtilityProcessHostClient::SendStopMessage() { |
| +void PdfConverterUtilityProcessHostClient::SendStopMessage() { |
| Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); |
| } |
| - |
| +/*void PdfToPostScriptUtilityProcessHostClient::OnPageDone(bool success) { |
| + PdfConverterUtilityProcessHostClient::OnPageDone(success, 0.0f); |
| +} |
| +*/ |
| // Pdf Converter Impl and subclasses |
| -PdfConverterImpl::PdfConverterImpl() {} |
| +PdfConverterImpl::PdfConverterImpl() : weak_ptr_factory_(this) {} |
| -PdfConverterImpl::~PdfConverterImpl() {} |
| +PdfConverterImpl::~PdfConverterImpl() { |
| + if (utility_client_.get()) |
| + utility_client_->Stop(); |
| +} |
| -void PdfConverterImpl::Start(const scoped_refptr<base::RefCountedMemory>& data, |
| - const PdfRenderSettings& conversion_settings, |
| - const StartCallback& start_callback) { |
| - DCHECK(!utility_client_.get()); |
| +void PdfConverterImpl::Start( |
| + const scoped_refptr<PdfConverterUtilityProcessHostClient>& utility_client, |
| + const scoped_refptr<base::RefCountedMemory>& data, |
| + const StartCallback& start_callback) { |
| + DCHECK(!utility_client_); |
| + utility_client_ = utility_client; |
| + utility_client_->Start(data, start_callback); |
| } |
| void PdfConverterImpl::GetPage(int page_number, |
| @@ -593,30 +627,22 @@ void PdfConverterImpl::RunCallback(const base::Closure& callback) { |
| callback.Run(); |
| } |
| -PdfToEmfConverterImpl::PdfToEmfConverterImpl() : weak_ptr_factory_(this) {} |
| - |
| -PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { |
| - if (utility_client_.get()) |
| - utility_client_->Stop(); |
| -} |
| - |
| -void PdfToEmfConverterImpl::Start( |
| - const scoped_refptr<base::RefCountedMemory>& data, |
| - const PdfRenderSettings& conversion_settings, |
| - const StartCallback& start_callback) { |
| - DCHECK(!utility_client_.get()); |
| - utility_client_ = new PdfToEmfUtilityProcessHostClient( |
| - weak_ptr_factory_.GetWeakPtr(), conversion_settings); |
| - utility_client_->Start(data, start_callback); |
| -} |
| - |
| } // namespace |
| PdfConverter::~PdfConverter() {} |
| // static |
| -std::unique_ptr<PdfConverter> PdfConverter::CreatePdfToEmfConverter() { |
| - return base::MakeUnique<PdfToEmfConverterImpl>(); |
| +std::unique_ptr<PdfConverter> PdfConverter::StartPdfConverter( |
| + const scoped_refptr<base::RefCountedMemory>& data, |
| + const PdfRenderSettings& conversion_settings, |
| + const StartCallback& start_callback) { |
| + std::unique_ptr<PdfConverterImpl> converter = |
| + base::MakeUnique<PdfConverterImpl>(); |
| + converter->Start( |
| + new PdfConverterUtilityProcessHostClient(converter->GetWeakPtr(), |
| + conversion_settings), |
| + data, start_callback); |
| + return std::move(converter); |
| } |
| } // namespace printing |