diff --git a/atom/utility/atom_content_utility_client.cc b/atom/utility/atom_content_utility_client.cc index 4be5a5f3fd7d..37fa7558712f 100644 --- a/atom/utility/atom_content_utility_client.cc +++ b/atom/utility/atom_content_utility_client.cc @@ -4,38 +4,13 @@ #include "atom/utility/atom_content_utility_client.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/time/time.h" -#include "chrome/common/chrome_utility_messages.h" -#include "chrome/utility/utility_message_handler.h" -#include "content/public/common/content_switches.h" -#include "content/public/utility/utility_thread.h" -#include "ipc/ipc_channel.h" -#include "ipc/ipc_message_macros.h" - - #if defined(OS_WIN) #include "chrome/utility/printing_handler_win.h" #endif - -namespace { - -bool Send(IPC::Message* message) { - return content::UtilityThread::Get()->Send(message); -} - -} // namespace - namespace atom { -int64_t AtomContentUtilityClient::max_ipc_message_size_ = - IPC::Channel::kMaximumMessageSize; - -AtomContentUtilityClient::AtomContentUtilityClient() - : filter_messages_(false) { +AtomContentUtilityClient::AtomContentUtilityClient() { #if defined(OS_WIN) handlers_.push_back(new printing::PrintingHandlerWin()); #endif @@ -44,31 +19,4 @@ AtomContentUtilityClient::AtomContentUtilityClient() AtomContentUtilityClient::~AtomContentUtilityClient() { } -void AtomContentUtilityClient::UtilityThreadStarted() { -} - -bool AtomContentUtilityClient::OnMessageReceived( - const IPC::Message& message) { - if (filter_messages_ && - !base::ContainsKey(message_id_whitelist_, message.type())) - return false; - - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(AtomContentUtilityClient, message) - IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - for (auto it = handlers_.begin(); !handled && it != handlers_.end(); ++it) { - handled = (*it)->OnMessageReceived(message); - } - - return handled; -} - -void AtomContentUtilityClient::OnStartupPing() { - Send(new ChromeUtilityHostMsg_ProcessStarted); - // Don't release the process, we assume further messages are on the way. -} - } // namespace atom diff --git a/atom/utility/atom_content_utility_client.h b/atom/utility/atom_content_utility_client.h index ba0fef471a11..d59b3812ff87 100644 --- a/atom/utility/atom_content_utility_client.h +++ b/atom/utility/atom_content_utility_client.h @@ -5,19 +5,11 @@ #ifndef ATOM_UTILITY_ATOM_CONTENT_UTILITY_CLIENT_H_ #define ATOM_UTILITY_ATOM_CONTENT_UTILITY_CLIENT_H_ -#include -#include #include #include "base/compiler_specific.h" #include "base/memory/scoped_vector.h" #include "content/public/utility/content_utility_client.h" -#include "ipc/ipc_platform_file.h" - -namespace base { -class FilePath; -struct FileDescriptor; -} class UtilityMessageHandler; @@ -28,26 +20,10 @@ class AtomContentUtilityClient : public content::ContentUtilityClient { AtomContentUtilityClient(); ~AtomContentUtilityClient() override; - void UtilityThreadStarted() override; - bool OnMessageReceived(const IPC::Message& message) override; - - static void set_max_ipc_message_size_for_test(int64_t max_message_size) { - max_ipc_message_size_ = max_message_size; - } - private: - void OnStartupPing(); - typedef ScopedVector Handlers; Handlers handlers_; - // Flag to enable whitelisting. - bool filter_messages_; - // A list of message_ids to filter. - std::set message_id_whitelist_; - // Maximum IPC msg size (default to kMaximumMessageSize; override for testing) - static int64_t max_ipc_message_size_; - DISALLOW_COPY_AND_ASSIGN(AtomContentUtilityClient); }; diff --git a/chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc b/chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc index 503d192feec5..b06c3a06409d 100644 --- a/chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc +++ b/chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc @@ -4,13 +4,22 @@ #include "chrome/browser/printing/pdf_to_emf_converter.h" +#include +#include + +#include #include +#include +#include #include "base/files/file.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_task_runner_handle.h" #include "chrome/common/chrome_utility_messages.h" #include "chrome/common/print_messages.h" #include "content/public/browser/browser_thread.h" @@ -19,6 +28,7 @@ #include "content/public/browser/utility_process_host_client.h" #include "printing/emf_win.h" #include "printing/pdf_render_settings.h" +#include "ui/base/l10n/l10n_util.h" namespace printing { @@ -59,7 +69,9 @@ typedef std::unique_ptr class LazyEmf : public MetafilePlayer { public: LazyEmf(const scoped_refptr& temp_dir, ScopedTempFile file) - : temp_dir_(temp_dir), file_(std::move(file)) {} + : temp_dir_(temp_dir), file_(std::move(file)) { + CHECK(file_); + } ~LazyEmf() override { Close(); } bool SafePlayback(HDC hdc) const override; @@ -97,6 +109,7 @@ class PdfToEmfUtilityProcessHostClient const PdfRenderSettings& settings); void Start(const scoped_refptr& data, + bool print_text_with_gdi, const PdfToEmfConverter::StartCallback& start_callback); void GetPage(int page_number, @@ -104,10 +117,14 @@ class PdfToEmfUtilityProcessHostClient void Stop(); + // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters + // sync message replies. + bool Send(IPC::Message* msg); + // UtilityProcessHostClient implementation. - virtual void OnProcessCrashed(int exit_code) override; - virtual void OnProcessLaunchFailed(int exit_code) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; + void OnProcessCrashed(int exit_code) override; + void OnProcessLaunchFailed(int exit_code) override; + bool OnMessageReceived(const IPC::Message& message) override; private: class GetPageCallbackData { @@ -138,19 +155,20 @@ class PdfToEmfUtilityProcessHostClient int page_number_; PdfToEmfConverter::GetPageCallback callback_; ScopedTempFile emf_; + + DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); }; - virtual ~PdfToEmfUtilityProcessHostClient(); - - bool Send(IPC::Message* msg); + ~PdfToEmfUtilityProcessHostClient() override; // Message handlers. - void OnProcessStarted(); void OnPageCount(int page_count); void OnPageDone(bool success, float scale_factor); + void OnPreCacheFontCharacters(const LOGFONT& log_font, + const base::string16& characters); void OnFailed(); - void OnTempPdfReady(ScopedTempFile pdf); + void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf); void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); scoped_refptr temp_dir_; @@ -158,7 +176,6 @@ class PdfToEmfUtilityProcessHostClient // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. base::WeakPtr converter_; PdfRenderSettings settings_; - scoped_refptr data_; // Document loaded callback. PdfToEmfConverter::StartCallback start_callback_; @@ -179,14 +196,15 @@ class PdfToEmfConverterImpl : public PdfToEmfConverter { public: PdfToEmfConverterImpl(); - virtual ~PdfToEmfConverterImpl(); + ~PdfToEmfConverterImpl() override; - virtual void Start(const scoped_refptr& data, - const PdfRenderSettings& conversion_settings, - const StartCallback& start_callback) override; + void Start(const scoped_refptr& data, + const PdfRenderSettings& conversion_settings, + bool print_text_with_gdi, + const StartCallback& start_callback) override; - virtual void GetPage(int page_number, - const GetPageCallback& get_page_callback) override; + void GetPage(int page_number, + const GetPageCallback& get_page_callback) override; // Helps to cancel callbacks if this object is destroyed. void RunCallback(const base::Closure& callback); @@ -205,16 +223,21 @@ ScopedTempFile CreateTempFile(scoped_refptr* temp_dir) { if (!(*temp_dir)->IsValid()) return file; base::FilePath path; - if (!base::CreateTemporaryFileInDir((*temp_dir)->GetPath(), &path)) + if (!base::CreateTemporaryFileInDir((*temp_dir)->GetPath(), &path)) { + PLOG(ERROR) << "Failed to create file in " + << (*temp_dir)->GetPath().value(); return file; + } file.reset(new base::File(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | base::File::FLAG_READ | base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_TEMPORARY)); - if (!file->IsValid()) + if (!file->IsValid()) { + PLOG(ERROR) << "Failed to create " << path.value(); file.reset(); + } return file; } @@ -228,6 +251,7 @@ ScopedTempFile CreateTempPdfFile( static_cast(data->size()) != pdf_file->WriteAtCurrentPos(data->front_as(), data->size())) { pdf_file.reset(); + return pdf_file; } pdf_file->Seek(base::File::FROM_BEGIN, 0); return pdf_file; @@ -281,17 +305,15 @@ PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { void PdfToEmfUtilityProcessHostClient::Start( const scoped_refptr& data, + bool print_text_with_gdi, const PdfToEmfConverter::StartCallback& start_callback) { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(&PdfToEmfUtilityProcessHostClient::Start, - this, - data, - start_callback)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data, + print_text_with_gdi, start_callback)); return; } - data_ = data; // Store callback before any OnFailed() call to make it called on failure. start_callback_ = start_callback; @@ -299,37 +321,28 @@ void PdfToEmfUtilityProcessHostClient::Start( // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load // gdiplus.dll, change how rendering happens, and not be able to correctly // generate when sent to a metafile DC. - utility_process_host_ = - content::UtilityProcessHost::Create( - this, base::MessageLoop::current()->task_runner())->AsWeakPtr(); - if (!utility_process_host_) - return OnFailed(); - // Should reply with OnProcessStarted(). - Send(new ChromeUtilityMsg_StartupPing); -} + utility_process_host_ = content::UtilityProcessHost::Create( + this, base::ThreadTaskRunnerHandle::Get()) + ->AsWeakPtr(); + utility_process_host_->SetName(base::ASCIIToUTF16( + "IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME")); -void PdfToEmfUtilityProcessHostClient::OnProcessStarted() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!utility_process_host_) - return OnFailed(); - - scoped_refptr data = data_; - data_ = NULL; BrowserThread::PostTaskAndReplyWithResult( - BrowserThread::FILE, - FROM_HERE, + BrowserThread::FILE, FROM_HERE, base::Bind(&CreateTempPdfFile, data, &temp_dir_), - base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this)); + base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this, + print_text_with_gdi)); } -void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) { +void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi, + ScopedTempFile pdf) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!utility_process_host_ || !pdf) return OnFailed(); // Should reply with OnPageCount(). Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( - IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), - settings_)); + IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_, + print_text_with_gdi)); } void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { @@ -413,6 +426,38 @@ void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success, get_page_callbacks_.pop(); } +void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters( + const LOGFONT& font, + const base::string16& str) { + // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache + // GDI fonts (http://crbug.com/383227), even when using DirectWrite. + // Eventually this shouldn't be added and should be moved to + // FontCacheDispatcher too. http://crbug.com/356346. + + // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. + // Except that for True Type fonts, + // GetTextMetrics will not load the font in memory. + // The only way windows seem to load properly, it is to create a similar + // device (like the one in which we print), then do an ExtTextOut, + // as we do in the printing thread, which is sandboxed. + HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr); + HFONT font_handle = CreateFontIndirect(&font); + DCHECK(font_handle != nullptr); + + HGDIOBJ old_font = SelectObject(hdc, font_handle); + DCHECK(old_font != nullptr); + + ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr); + + SelectObject(hdc, old_font); + DeleteObject(font_handle); + + HENHMETAFILE metafile = CloseEnhMetaFile(hdc); + + if (metafile) + DeleteEnhMetaFile(metafile); +} + void PdfToEmfUtilityProcessHostClient::Stop() { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { BrowserThread::PostTask( @@ -436,11 +481,12 @@ bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted) IPC_MESSAGE_HANDLER( ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, OnPageDone) + IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters, + OnPreCacheFontCharacters) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -473,11 +519,12 @@ PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { void PdfToEmfConverterImpl::Start( const scoped_refptr& data, const PdfRenderSettings& conversion_settings, + bool print_text_with_gdi, const StartCallback& start_callback) { DCHECK(!utility_client_.get()); utility_client_ = new PdfToEmfUtilityProcessHostClient( weak_ptr_factory_.GetWeakPtr(), conversion_settings); - utility_client_->Start(data, start_callback); + utility_client_->Start(data, print_text_with_gdi, start_callback); } void PdfToEmfConverterImpl::GetPage(int page_number, diff --git a/chromium_src/chrome/browser/printing/pdf_to_emf_converter.h b/chromium_src/chrome/browser/printing/pdf_to_emf_converter.h index bd292dd476a1..1f5271527406 100644 --- a/chromium_src/chrome/browser/printing/pdf_to_emf_converter.h +++ b/chromium_src/chrome/browser/printing/pdf_to_emf_converter.h @@ -10,21 +10,18 @@ #include "base/callback.h" #include "base/memory/ref_counted_memory.h" -namespace base { -class FilePath; -} - namespace printing { class MetafilePlayer; -class PdfRenderSettings; +struct PdfRenderSettings; class PdfToEmfConverter { public: typedef base::Callback StartCallback; typedef base::Callback emf)> GetPageCallback; + std::unique_ptr emf)> + GetPageCallback; virtual ~PdfToEmfConverter(); @@ -34,6 +31,7 @@ class PdfToEmfConverter { // with positive |page_count|. |page_count| is 0 if initialization failed. virtual void Start(const scoped_refptr& data, const PdfRenderSettings& conversion_settings, + bool print_text_with_gdi, const StartCallback& start_callback) = 0; // Requests conversion of the page. |page_number| is 0-base page number in diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.cc b/chromium_src/chrome/browser/printing/print_view_manager_base.cc index 67caebb63ecf..fb54bda2c778 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.cc +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.cc @@ -160,13 +160,18 @@ void PrintViewManagerBase::OnDidPrintPage( ShouldQuitFromInnerMessageLoop(); #else if (metafile_must_be_valid) { + bool print_text_with_gdi = + document->settings().print_text_with_gdi() && + !document->settings().printer_is_xps(); + scoped_refptr bytes = new base::RefCountedBytes( reinterpret_cast(shared_buf.memory()), params.data_size); document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf")); print_job_->StartPdfToEmfConversion( - bytes, params.page_size, params.content_area); + bytes, params.page_size, params.content_area, + print_text_with_gdi); } #endif // !OS_WIN } diff --git a/chromium_src/chrome/common/chrome_utility_messages.h b/chromium_src/chrome/common/chrome_utility_messages.h index efcd468c5138..012c9f67509b 100644 --- a/chromium_src/chrome/common/chrome_utility_messages.h +++ b/chromium_src/chrome/common/chrome_utility_messages.h @@ -83,12 +83,6 @@ IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_PatchFileCourgette, base::FilePath /* output_file */) -// Requests the utility process to respond with a -// ChromeUtilityHostMsg_ProcessStarted message once it has started. This may -// be used if the host process needs a handle to the running utility process. -IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_StartupPing) - - #if defined(OS_WIN) // Invokes ui::base::win::OpenFileViaShell from the utility process. IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_OpenFileViaShell, diff --git a/chromium_src/chrome/common/print_messages.h b/chromium_src/chrome/common/print_messages.h index dce74cbe9f24..e74dfafa71aa 100644 --- a/chromium_src/chrome/common/print_messages.h +++ b/chromium_src/chrome/common/print_messages.h @@ -315,9 +315,10 @@ IPC_MESSAGE_ROUTED2(PrintHostMsg_PrintPreviewFailed, // Tell the utility process to start rendering the given PDF into a metafile. // Utility process would be alive until // ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop message. -IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RenderPDFPagesToMetafiles, - IPC::PlatformFileForTransit, /* input_file */ - printing::PdfRenderSettings /* settings */) +IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_RenderPDFPagesToMetafiles, + IPC::PlatformFileForTransit /* input_file */, + printing::PdfRenderSettings /* settings */, + bool /* print_text_with_gdi */) // Requests conversion of the next page. IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage, @@ -336,4 +337,12 @@ IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, bool /* success */, float /* scale_factor */) + +// Request that the given font characters be loaded by the browser so it's +// cached by the OS. Please see +// PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters for details. +IPC_SYNC_MESSAGE_CONTROL2_0(ChromeUtilityHostMsg_PreCacheFontCharacters, + LOGFONT /* font_data */, + base::string16 /* characters */) + #endif diff --git a/chromium_src/chrome/utility/printing_handler_win.cc b/chromium_src/chrome/utility/printing_handler_win.cc index c29dd5f9f694..4265991272af 100644 --- a/chromium_src/chrome/utility/printing_handler_win.cc +++ b/chromium_src/chrome/utility/printing_handler_win.cc @@ -28,9 +28,18 @@ void ReleaseProcessIfNeeded() { content::UtilityThread::Get()->ReleaseProcessIfNeeded(); } +void PreCacheFontCharacters(const LOGFONT* logfont, + const wchar_t* text, + size_t text_length) { + Send(new ChromeUtilityHostMsg_PreCacheFontCharacters( + *logfont, base::string16(text, text_length))); +} + } // namespace -PrintingHandlerWin::PrintingHandlerWin() {} +PrintingHandlerWin::PrintingHandlerWin() { + chrome_pdf::SetPDFEnsureTypefaceCharactersAccessible(PreCacheFontCharacters); +} PrintingHandlerWin::~PrintingHandlerWin() {} @@ -50,8 +59,10 @@ bool PrintingHandlerWin::OnMessageReceived(const IPC::Message& message) { void PrintingHandlerWin::OnRenderPDFPagesToMetafile( IPC::PlatformFileForTransit pdf_transit, - const PdfRenderSettings& settings) { + const PdfRenderSettings& settings, + bool print_text_with_gdi) { pdf_rendering_settings_ = settings; + chrome_pdf::SetPDFUseGDIPrinting(print_text_with_gdi); base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit); int page_count = LoadPDF(std::move(pdf_file)); //int page_count = 1; diff --git a/chromium_src/chrome/utility/printing_handler_win.h b/chromium_src/chrome/utility/printing_handler_win.h index e7fcc5bed158..b4a1902dc714 100644 --- a/chromium_src/chrome/utility/printing_handler_win.h +++ b/chromium_src/chrome/utility/printing_handler_win.h @@ -29,7 +29,8 @@ class PrintingHandlerWin : public UtilityMessageHandler { private: // IPC message handlers. void OnRenderPDFPagesToMetafile(IPC::PlatformFileForTransit pdf_transit, - const PdfRenderSettings& settings); + const PdfRenderSettings& settings, + bool print_text_with_gdi); void OnRenderPDFPagesToMetafileGetPage( int page_number, IPC::PlatformFileForTransit output_file);