From abd97a7513ffd54a682cdded87351914d409eb70 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 11 May 2015 20:14:07 +0800 Subject: [PATCH] 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 e73cc06bc4..ff9d14cf59 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 cc739227aa..06d0c3b82c 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 2c245b62f6..756193d6d4 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 db6d9533cf..7821c174c9 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 b1f09acb9c..ad96dd704f 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)