From abd97a7513ffd54a682cdded87351914d409eb70 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 11 May 2015 20:14:07 +0800 Subject: [PATCH 1/6] Load pdf component dynamically. Ship pdf as dll library, electron only loads pdf.dll when calling print API. In this way, the developer who don't need print feature can safe remove the pdf.dll in saving their binary size. --- atom/app/atom_main_delegate.cc | 6 + atom/utility/atom_content_utility_client.cc | 5 + atom/utility/atom_content_utility_client.h | 1 + .../chrome/utility/printing_handler.cc | 107 +++++++++++++++++- .../chrome/utility/printing_handler.h | 2 + 5 files changed, 118 insertions(+), 3 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index e73cc06bc464..ff9d14cf593a 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -64,6 +64,12 @@ void AtomMainDelegate::PreSandboxStartup() { std::string process_type = command_line->GetSwitchValueASCII( switches::kProcessType); +#if defined(OS_WIN) + if (process_type == switches::kUtilityProcess) { + AtomContentUtilityClient::PreSandboxStartup(); + } +#endif + // Only append arguments for browser process. if (!process_type.empty()) return; diff --git a/atom/utility/atom_content_utility_client.cc b/atom/utility/atom_content_utility_client.cc index cc739227aad8..06d0c3b82cfd 100644 --- a/atom/utility/atom_content_utility_client.cc +++ b/atom/utility/atom_content_utility_client.cc @@ -71,4 +71,9 @@ void AtomContentUtilityClient::OnStartupPing() { // Don't release the process, we assume further messages are on the way. } +// static +void AtomContentUtilityClient::PreSandboxStartup() { + PrintingHandler::PreSandboxStartup(); +} + } // namespace atom diff --git a/atom/utility/atom_content_utility_client.h b/atom/utility/atom_content_utility_client.h index 2c245b62f61e..756193d6d44c 100644 --- a/atom/utility/atom_content_utility_client.h +++ b/atom/utility/atom_content_utility_client.h @@ -31,6 +31,7 @@ class AtomContentUtilityClient : public content::ContentUtilityClient { void UtilityThreadStarted() override; bool OnMessageReceived(const IPC::Message& message) override; + static void PreSandboxStartup(); static void set_max_ipc_message_size_for_test(int64_t max_message_size) { max_ipc_message_size_ = max_message_size; diff --git a/chromium_src/chrome/utility/printing_handler.cc b/chromium_src/chrome/utility/printing_handler.cc index db6d9533cf51..7821c174c950 100644 --- a/chromium_src/chrome/utility/printing_handler.cc +++ b/chromium_src/chrome/utility/printing_handler.cc @@ -10,7 +10,6 @@ #include "base/scoped_native_library.h" #include "chrome/common/print_messages.h" #include "content/public/utility/utility_thread.h" -#include "pdf/pdf.h" #include "printing/page_range.h" #include "printing/pdf_render_settings.h" @@ -30,12 +29,111 @@ void ReleaseProcessIfNeeded() { content::UtilityThread::Get()->ReleaseProcessIfNeeded(); } +class PdfFunctions { + public: + PdfFunctions() : get_pdf_doc_info_func_(NULL), + render_pdf_to_dc_func_(NULL) {} + + bool Init() { + base::FilePath pdf_module_path(FILE_PATH_LITERAL("pdf.dll")); + pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL)); + if (!pdf_lib_.is_valid()) { + LOG(WARNING) << "Couldn't load PDF plugin"; + return false; + } + + get_pdf_doc_info_func_ = + reinterpret_cast( + pdf_lib_.GetFunctionPointer("GetPDFDocInfo")); + LOG_IF(WARNING, !get_pdf_doc_info_func_) << "Missing GetPDFDocInfo"; + + render_pdf_to_dc_func_ = + reinterpret_cast( + pdf_lib_.GetFunctionPointer("RenderPDFPageToDC")); + LOG_IF(WARNING, !render_pdf_to_dc_func_) << "Missing RenderPDFPageToDC"; + + if (!get_pdf_doc_info_func_ || !render_pdf_to_dc_func_) { + Reset(); + } + + return IsValid(); + } + + bool IsValid() const { + return pdf_lib_.is_valid(); + } + + void Reset() { + pdf_lib_.Reset(NULL); + } + + bool GetPDFDocInfo(const void* pdf_buffer, + int buffer_size, + int* page_count, + double* max_page_width) { + if (!get_pdf_doc_info_func_) + return false; + return get_pdf_doc_info_func_(pdf_buffer, buffer_size, page_count, + max_page_width); + } + + bool RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, + int page_number, + HDC dc, + int dpi, + int bounds_origin_x, + int bounds_origin_y, + int bounds_width, + int bounds_height, + bool fit_to_bounds, + bool stretch_to_bounds, + bool keep_aspect_ratio, + bool center_in_bounds, + bool autorotate) { + if (!render_pdf_to_dc_func_) + return false; + return render_pdf_to_dc_func_(pdf_buffer, buffer_size, page_number, + dc, dpi, bounds_origin_x, + bounds_origin_y, bounds_width, bounds_height, + fit_to_bounds, stretch_to_bounds, + keep_aspect_ratio, center_in_bounds, + autorotate); + } + + private: + // Exported by PDF plugin. + typedef bool (*GetPDFDocInfoProc)(const void* pdf_buffer, + int buffer_size, int* page_count, + double* max_page_width); + typedef bool (*RenderPDFPageToDCProc)( + const void* pdf_buffer, int buffer_size, int page_number, HDC dc, + int dpi, int bounds_origin_x, int bounds_origin_y, + int bounds_width, int bounds_height, bool fit_to_bounds, + bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds, + bool autorotate); + + RenderPDFPageToDCProc render_pdf_to_dc_func_; + GetPDFDocInfoProc get_pdf_doc_info_func_; + + base::ScopedNativeLibrary pdf_lib_; + + DISALLOW_COPY_AND_ASSIGN(PdfFunctions); +}; + +base::LazyInstance g_pdf_lib = LAZY_INSTANCE_INITIALIZER; + } // namespace PrintingHandler::PrintingHandler() {} PrintingHandler::~PrintingHandler() {} +// static +void PrintingHandler::PreSandboxStartup() { + g_pdf_lib.Get().Init(); +} + bool PrintingHandler::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message) @@ -80,6 +178,9 @@ void PrintingHandler::OnRenderPDFPagesToMetafileStop() { } int PrintingHandler::LoadPDF(base::File pdf_file) { + if (!g_pdf_lib.Get().IsValid()) + return 0; + int64 length64 = pdf_file.GetLength(); if (length64 <= 0 || length64 > std::numeric_limits::max()) return 0; @@ -90,7 +191,7 @@ int PrintingHandler::LoadPDF(base::File pdf_file) { return 0; int total_page_count = 0; - if (!chrome_pdf::GetPDFDocInfo( + if (!g_pdf_lib.Get().GetPDFDocInfo( &pdf_data_.front(), pdf_data_.size(), &total_page_count, NULL)) { return 0; } @@ -119,7 +220,7 @@ bool PrintingHandler::RenderPdfPageToMetafile(int page_number, // The underlying metafile is of type Emf and ignores the arguments passed // to StartPage. metafile.StartPage(gfx::Size(), gfx::Rect(), 1); - if (!chrome_pdf::RenderPDFPageToDC( + if (!g_pdf_lib.Get().RenderPDFPageToDC( &pdf_data_.front(), pdf_data_.size(), page_number, diff --git a/chromium_src/chrome/utility/printing_handler.h b/chromium_src/chrome/utility/printing_handler.h index b1f09acb9cc9..ad96dd704ffe 100644 --- a/chromium_src/chrome/utility/printing_handler.h +++ b/chromium_src/chrome/utility/printing_handler.h @@ -30,6 +30,8 @@ class PrintingHandler : public UtilityMessageHandler { // IPC::Listener: bool OnMessageReceived(const IPC::Message& message) override; + static void PrintingHandler::PreSandboxStartup(); + private: // IPC message handlers. #if defined(OS_WIN) From 5ede62459cb76dd74c782661ceac4763c0ceac9d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 11 May 2015 20:57:07 +0800 Subject: [PATCH 2/6] Rename PrintHandler to PrintHandlerWin since only used on Windows. --- atom/utility/atom_content_utility_client.cc | 8 ++-- ...ing_handler.cc => printing_handler_win.cc} | 37 +++++++------------ ...nting_handler.h => printing_handler_win.h} | 26 ++++--------- filenames.gypi | 4 +- 4 files changed, 29 insertions(+), 46 deletions(-) rename chromium_src/chrome/utility/{printing_handler.cc => printing_handler_win.cc} (90%) rename chromium_src/chrome/utility/{printing_handler.h => printing_handler_win.h} (68%) diff --git a/atom/utility/atom_content_utility_client.cc b/atom/utility/atom_content_utility_client.cc index 06d0c3b82cfd..2e591f2c6a8d 100644 --- a/atom/utility/atom_content_utility_client.cc +++ b/atom/utility/atom_content_utility_client.cc @@ -17,7 +17,7 @@ #if defined(OS_WIN) -#include "chrome/utility/printing_handler.h" +#include "chrome/utility/printing_handler_win.h" #endif @@ -37,7 +37,7 @@ int64_t AtomContentUtilityClient::max_ipc_message_size_ = AtomContentUtilityClient::AtomContentUtilityClient() : filter_messages_(false) { #if defined(OS_WIN) - handlers_.push_back(new PrintingHandler()); + handlers_.push_back(new PrintingHandlerWin()); #endif } @@ -73,7 +73,9 @@ void AtomContentUtilityClient::OnStartupPing() { // static void AtomContentUtilityClient::PreSandboxStartup() { - PrintingHandler::PreSandboxStartup(); +#if defined(OS_WIN) + PrintingHandlerWin::PreSandboxStartup(); +#endif } } // namespace atom diff --git a/chromium_src/chrome/utility/printing_handler.cc b/chromium_src/chrome/utility/printing_handler_win.cc similarity index 90% rename from chromium_src/chrome/utility/printing_handler.cc rename to chromium_src/chrome/utility/printing_handler_win.cc index 7821c174c950..705131f348cd 100644 --- a/chromium_src/chrome/utility/printing_handler.cc +++ b/chromium_src/chrome/utility/printing_handler_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/utility/printing_handler.h" +#include "chrome/utility/printing_handler_win.h" #include "base/files/file_util.h" #include "base/lazy_instance.h" @@ -10,14 +10,10 @@ #include "base/scoped_native_library.h" #include "chrome/common/print_messages.h" #include "content/public/utility/utility_thread.h" +#include "printing/emf_win.h" #include "printing/page_range.h" #include "printing/pdf_render_settings.h" - -#if defined(OS_WIN) -#include "printing/emf_win.h" #include "ui/gfx/gdi_util.h" -#endif - namespace { @@ -125,33 +121,30 @@ base::LazyInstance g_pdf_lib = LAZY_INSTANCE_INITIALIZER; } // namespace -PrintingHandler::PrintingHandler() {} +PrintingHandlerWin::PrintingHandlerWin() {} -PrintingHandler::~PrintingHandler() {} +PrintingHandlerWin::~PrintingHandlerWin() {} // static -void PrintingHandler::PreSandboxStartup() { +void PrintingHandlerWin::PreSandboxStartup() { g_pdf_lib.Get().Init(); } -bool PrintingHandler::OnMessageReceived(const IPC::Message& message) { +bool PrintingHandlerWin::OnMessageReceived(const IPC::Message& message) { bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message) -#if defined(OS_WIN) + IPC_BEGIN_MESSAGE_MAP(PrintingHandlerWin, message) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles, OnRenderPDFPagesToMetafile) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage, OnRenderPDFPagesToMetafileGetPage) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop, OnRenderPDFPagesToMetafileStop) -#endif // OS_WIN IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } -#if defined(OS_WIN) -void PrintingHandler::OnRenderPDFPagesToMetafile( +void PrintingHandlerWin::OnRenderPDFPagesToMetafile( IPC::PlatformFileForTransit pdf_transit, const printing::PdfRenderSettings& settings) { pdf_rendering_settings_ = settings; @@ -162,7 +155,7 @@ void PrintingHandler::OnRenderPDFPagesToMetafile( new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count)); } -void PrintingHandler::OnRenderPDFPagesToMetafileGetPage( +void PrintingHandlerWin::OnRenderPDFPagesToMetafileGetPage( int page_number, IPC::PlatformFileForTransit output_file) { base::File emf_file = IPC::PlatformFileForTransitToFile(output_file); @@ -173,11 +166,11 @@ void PrintingHandler::OnRenderPDFPagesToMetafileGetPage( success, scale_factor)); } -void PrintingHandler::OnRenderPDFPagesToMetafileStop() { +void PrintingHandlerWin::OnRenderPDFPagesToMetafileStop() { ReleaseProcessIfNeeded(); } -int PrintingHandler::LoadPDF(base::File pdf_file) { +int PrintingHandlerWin::LoadPDF(base::File pdf_file) { if (!g_pdf_lib.Get().IsValid()) return 0; @@ -198,9 +191,9 @@ int PrintingHandler::LoadPDF(base::File pdf_file) { return total_page_count; } -bool PrintingHandler::RenderPdfPageToMetafile(int page_number, - base::File output_file, - float* scale_factor) { +bool PrintingHandlerWin::RenderPdfPageToMetafile(int page_number, + base::File output_file, + float* scale_factor) { printing::Emf metafile; metafile.Init(); @@ -241,5 +234,3 @@ bool PrintingHandler::RenderPdfPageToMetafile(int page_number, metafile.FinishDocument(); return metafile.SaveTo(&output_file); } - -#endif // OS_WIN diff --git a/chromium_src/chrome/utility/printing_handler.h b/chromium_src/chrome/utility/printing_handler_win.h similarity index 68% rename from chromium_src/chrome/utility/printing_handler.h rename to chromium_src/chrome/utility/printing_handler_win.h index ad96dd704ffe..5b8c5e970f15 100644 --- a/chromium_src/chrome/utility/printing_handler.h +++ b/chromium_src/chrome/utility/printing_handler_win.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_UTILITY_PRINTING_HANDLER_H_ -#define CHROME_UTILITY_PRINTING_HANDLER_H_ +#ifndef CHROME_UTILITY_PRINTING_HANDLER_WIN_H_ +#define CHROME_UTILITY_PRINTING_HANDLER_WIN_H_ #include "base/compiler_specific.h" #include "base/macros.h" @@ -11,10 +11,6 @@ #include "ipc/ipc_platform_file.h" #include "printing/pdf_render_settings.h" -#if !defined(ENABLE_PRINT_PREVIEW) && !defined(OS_WIN) -#error "Windows or full printing must be enabled" -#endif - namespace printing { class PdfRenderSettings; struct PwgRasterSettings; @@ -22,40 +18,34 @@ struct PageRange; } // Dispatches IPCs for printing. -class PrintingHandler : public UtilityMessageHandler { +class PrintingHandlerWin : public UtilityMessageHandler { public: - PrintingHandler(); - ~PrintingHandler() override; + PrintingHandlerWin(); + ~PrintingHandlerWin() override; // IPC::Listener: bool OnMessageReceived(const IPC::Message& message) override; - static void PrintingHandler::PreSandboxStartup(); + static void PrintingHandlerWin::PreSandboxStartup(); private: // IPC message handlers. -#if defined(OS_WIN) void OnRenderPDFPagesToMetafile(IPC::PlatformFileForTransit pdf_transit, const printing::PdfRenderSettings& settings); void OnRenderPDFPagesToMetafileGetPage( int page_number, IPC::PlatformFileForTransit output_file); void OnRenderPDFPagesToMetafileStop(); -#endif // OS_WIN -#if defined(OS_WIN) int LoadPDF(base::File pdf_file); bool RenderPdfPageToMetafile(int page_number, base::File output_file, float* scale_factor); -#endif // OS_WIN -#if defined(OS_WIN) std::vector pdf_data_; printing::PdfRenderSettings pdf_rendering_settings_; -#endif - DISALLOW_COPY_AND_ASSIGN(PrintingHandler); + DISALLOW_COPY_AND_ASSIGN(PrintingHandlerWin); }; -#endif // CHROME_UTILITY_PRINTING_HANDLER_H_ +#endif // CHROME_UTILITY_PRINTING_HANDLER_WIN_H_ diff --git a/filenames.gypi b/filenames.gypi index 5ba27229e321..13b75d79fa61 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -381,8 +381,8 @@ 'chromium_src/chrome/browser/ui/views/color_chooser_win.cc', 'chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc', 'chromium_src/chrome/browser/printing/pdf_to_emf_converter.h', - 'chromium_src/chrome/utility/printing_handler.cc', - 'chromium_src/chrome/utility/printing_handler.h', + 'chromium_src/chrome/utility/printing_handler_win.cc', + 'chromium_src/chrome/utility/printing_handler_win.h', ], 'framework_sources': [ 'atom/app/atom_library_main.h', From f1f801b7a260559427dddffb7a7fbd8ba6499564 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 13 May 2015 08:04:27 +0800 Subject: [PATCH 3/6] Copy pdf.dll to build directory. --- atom.gyp | 1 + 1 file changed, 1 insertion(+) diff --git a/atom.gyp b/atom.gyp index 557d53028931..69d4b2f46f5d 100644 --- a/atom.gyp +++ b/atom.gyp @@ -134,6 +134,7 @@ '<(libchromiumcontent_dir)/ffmpegsumo.dll', '<(libchromiumcontent_dir)/libEGL.dll', '<(libchromiumcontent_dir)/libGLESv2.dll', + '<(libchromiumcontent_dir)/pdf.dll', '<(libchromiumcontent_dir)/icudtl.dat', '<(libchromiumcontent_dir)/content_resources_200_percent.pak', '<(libchromiumcontent_dir)/content_shell.pak', From bf5f85645ec3d019b4cf3bb1a6c7e92957658a76 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 13 May 2015 09:50:56 +0800 Subject: [PATCH 4/6] Remove the multiple rules generate pdf.dll warning in GYP during debug build. --- atom.gyp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/atom.gyp b/atom.gyp index 69d4b2f46f5d..b514e8d9d247 100644 --- a/atom.gyp +++ b/atom.gyp @@ -124,7 +124,9 @@ '<@(libchromiumcontent_shared_v8_libraries)', ], }, { - 'copied_libraries': [], + 'copied_libraries': [ + '<(libchromiumcontent_dir)/pdf.dll', + ], }], ], }, @@ -134,7 +136,6 @@ '<(libchromiumcontent_dir)/ffmpegsumo.dll', '<(libchromiumcontent_dir)/libEGL.dll', '<(libchromiumcontent_dir)/libGLESv2.dll', - '<(libchromiumcontent_dir)/pdf.dll', '<(libchromiumcontent_dir)/icudtl.dat', '<(libchromiumcontent_dir)/content_resources_200_percent.pak', '<(libchromiumcontent_dir)/content_shell.pak', From c3791bba78aa5fb7563b25843712148bc61d803c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 21 May 2015 15:01:36 +0800 Subject: [PATCH 5/6] Remove duplicated macro. --- atom/app/atom_main_delegate.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index ff9d14cf593a..02dd11c81ba0 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -64,11 +64,9 @@ void AtomMainDelegate::PreSandboxStartup() { std::string process_type = command_line->GetSwitchValueASCII( switches::kProcessType); -#if defined(OS_WIN) if (process_type == switches::kUtilityProcess) { AtomContentUtilityClient::PreSandboxStartup(); } -#endif // Only append arguments for browser process. if (!process_type.empty()) From fdad5892d9f5b41657298982a09b5b245ba86103 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sat, 23 May 2015 21:39:59 +0800 Subject: [PATCH 6/6] :memo: Add `pdf.dll` note doc. --- docs/api/browser-window.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index cc68f2008b9e..ef92d5b37afd 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -543,6 +543,10 @@ up system's default printer and default settings for printing. Calling `window.print()` in web page is equivalent to call `BrowserWindow.print({silent: false, printBackground: false})`. +**Note:** On Windows, the print API relies on `pdf.dll`. If your application +doesn't need print feature, you can safely remove `pdf.dll` in saving binary +size. + ### BrowserWindow.loadUrl(url) Same with `webContents.loadUrl(url)`.