diff --git a/atom.gyp b/atom.gyp index 557d53028931..b514e8d9d247 100644 --- a/atom.gyp +++ b/atom.gyp @@ -124,7 +124,9 @@ '<@(libchromiumcontent_shared_v8_libraries)', ], }, { - 'copied_libraries': [], + 'copied_libraries': [ + '<(libchromiumcontent_dir)/pdf.dll', + ], }], ], }, diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index e73cc06bc464..02dd11c81ba0 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -64,6 +64,10 @@ void AtomMainDelegate::PreSandboxStartup() { std::string process_type = command_line->GetSwitchValueASCII( switches::kProcessType); + if (process_type == switches::kUtilityProcess) { + AtomContentUtilityClient::PreSandboxStartup(); + } + // 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..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 } @@ -71,4 +71,11 @@ void AtomContentUtilityClient::OnStartupPing() { // Don't release the process, we assume further messages are on the way. } +// static +void AtomContentUtilityClient::PreSandboxStartup() { +#if defined(OS_WIN) + PrintingHandlerWin::PreSandboxStartup(); +#endif +} + } // 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 deleted file mode 100644 index db6d9533cf51..000000000000 --- a/chromium_src/chrome/utility/printing_handler.cc +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// 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 "base/files/file_util.h" -#include "base/lazy_instance.h" -#include "base/path_service.h" -#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" - -#if defined(OS_WIN) -#include "printing/emf_win.h" -#include "ui/gfx/gdi_util.h" -#endif - - -namespace { - -bool Send(IPC::Message* message) { - return content::UtilityThread::Get()->Send(message); -} - -void ReleaseProcessIfNeeded() { - content::UtilityThread::Get()->ReleaseProcessIfNeeded(); -} - -} // namespace - -PrintingHandler::PrintingHandler() {} - -PrintingHandler::~PrintingHandler() {} - -bool PrintingHandler::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message) -#if defined(OS_WIN) - 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( - IPC::PlatformFileForTransit pdf_transit, - const printing::PdfRenderSettings& settings) { - pdf_rendering_settings_ = settings; - base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit); - int page_count = LoadPDF(pdf_file.Pass()); - //int page_count = 1; - Send( - new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count)); -} - -void PrintingHandler::OnRenderPDFPagesToMetafileGetPage( - int page_number, - IPC::PlatformFileForTransit output_file) { - base::File emf_file = IPC::PlatformFileForTransitToFile(output_file); - float scale_factor = 1.0f; - bool success = - RenderPdfPageToMetafile(page_number, emf_file.Pass(), &scale_factor); - Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone( - success, scale_factor)); -} - -void PrintingHandler::OnRenderPDFPagesToMetafileStop() { - ReleaseProcessIfNeeded(); -} - -int PrintingHandler::LoadPDF(base::File pdf_file) { - int64 length64 = pdf_file.GetLength(); - if (length64 <= 0 || length64 > std::numeric_limits::max()) - return 0; - int length = static_cast(length64); - - pdf_data_.resize(length); - if (length != pdf_file.Read(0, pdf_data_.data(), pdf_data_.size())) - return 0; - - int total_page_count = 0; - if (!chrome_pdf::GetPDFDocInfo( - &pdf_data_.front(), pdf_data_.size(), &total_page_count, NULL)) { - return 0; - } - return total_page_count; -} - -bool PrintingHandler::RenderPdfPageToMetafile(int page_number, - base::File output_file, - float* scale_factor) { - printing::Emf metafile; - metafile.Init(); - - // We need to scale down DC to fit an entire page into DC available area. - // Current metafile is based on screen DC and have current screen size. - // Writing outside of those boundaries will result in the cut-off output. - // On metafiles (this is the case here), scaling down will still record - // original coordinates and we'll be able to print in full resolution. - // Before playback we'll need to counter the scaling up that will happen - // in the service (print_system_win.cc). - *scale_factor = - gfx::CalculatePageScale(metafile.context(), - pdf_rendering_settings_.area().right(), - pdf_rendering_settings_.area().bottom()); - gfx::ScaleDC(metafile.context(), *scale_factor); - - // 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( - &pdf_data_.front(), - pdf_data_.size(), - page_number, - metafile.context(), - pdf_rendering_settings_.dpi(), - pdf_rendering_settings_.area().x(), - pdf_rendering_settings_.area().y(), - pdf_rendering_settings_.area().width(), - pdf_rendering_settings_.area().height(), - true, - false, - true, - true, - pdf_rendering_settings_.autorotate())) { - return false; - } - metafile.FinishPage(); - metafile.FinishDocument(); - return metafile.SaveTo(&output_file); -} - -#endif // OS_WIN diff --git a/chromium_src/chrome/utility/printing_handler_win.cc b/chromium_src/chrome/utility/printing_handler_win.cc new file mode 100644 index 000000000000..705131f348cd --- /dev/null +++ b/chromium_src/chrome/utility/printing_handler_win.cc @@ -0,0 +1,236 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// 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_win.h" + +#include "base/files/file_util.h" +#include "base/lazy_instance.h" +#include "base/path_service.h" +#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" +#include "ui/gfx/gdi_util.h" + +namespace { + +bool Send(IPC::Message* message) { + return content::UtilityThread::Get()->Send(message); +} + +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 + +PrintingHandlerWin::PrintingHandlerWin() {} + +PrintingHandlerWin::~PrintingHandlerWin() {} + +// static +void PrintingHandlerWin::PreSandboxStartup() { + g_pdf_lib.Get().Init(); +} + +bool PrintingHandlerWin::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + 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) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void PrintingHandlerWin::OnRenderPDFPagesToMetafile( + IPC::PlatformFileForTransit pdf_transit, + const printing::PdfRenderSettings& settings) { + pdf_rendering_settings_ = settings; + base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit); + int page_count = LoadPDF(pdf_file.Pass()); + //int page_count = 1; + Send( + new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count)); +} + +void PrintingHandlerWin::OnRenderPDFPagesToMetafileGetPage( + int page_number, + IPC::PlatformFileForTransit output_file) { + base::File emf_file = IPC::PlatformFileForTransitToFile(output_file); + float scale_factor = 1.0f; + bool success = + RenderPdfPageToMetafile(page_number, emf_file.Pass(), &scale_factor); + Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone( + success, scale_factor)); +} + +void PrintingHandlerWin::OnRenderPDFPagesToMetafileStop() { + ReleaseProcessIfNeeded(); +} + +int PrintingHandlerWin::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; + int length = static_cast(length64); + + pdf_data_.resize(length); + if (length != pdf_file.Read(0, pdf_data_.data(), pdf_data_.size())) + return 0; + + int total_page_count = 0; + if (!g_pdf_lib.Get().GetPDFDocInfo( + &pdf_data_.front(), pdf_data_.size(), &total_page_count, NULL)) { + return 0; + } + return total_page_count; +} + +bool PrintingHandlerWin::RenderPdfPageToMetafile(int page_number, + base::File output_file, + float* scale_factor) { + printing::Emf metafile; + metafile.Init(); + + // We need to scale down DC to fit an entire page into DC available area. + // Current metafile is based on screen DC and have current screen size. + // Writing outside of those boundaries will result in the cut-off output. + // On metafiles (this is the case here), scaling down will still record + // original coordinates and we'll be able to print in full resolution. + // Before playback we'll need to counter the scaling up that will happen + // in the service (print_system_win.cc). + *scale_factor = + gfx::CalculatePageScale(metafile.context(), + pdf_rendering_settings_.area().right(), + pdf_rendering_settings_.area().bottom()); + gfx::ScaleDC(metafile.context(), *scale_factor); + + // The underlying metafile is of type Emf and ignores the arguments passed + // to StartPage. + metafile.StartPage(gfx::Size(), gfx::Rect(), 1); + if (!g_pdf_lib.Get().RenderPDFPageToDC( + &pdf_data_.front(), + pdf_data_.size(), + page_number, + metafile.context(), + pdf_rendering_settings_.dpi(), + pdf_rendering_settings_.area().x(), + pdf_rendering_settings_.area().y(), + pdf_rendering_settings_.area().width(), + pdf_rendering_settings_.area().height(), + true, + false, + true, + true, + pdf_rendering_settings_.autorotate())) { + return false; + } + metafile.FinishPage(); + metafile.FinishDocument(); + return metafile.SaveTo(&output_file); +} diff --git a/chromium_src/chrome/utility/printing_handler.h b/chromium_src/chrome/utility/printing_handler_win.h similarity index 70% rename from chromium_src/chrome/utility/printing_handler.h rename to chromium_src/chrome/utility/printing_handler_win.h index b1f09acb9cc9..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,38 +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 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/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)`. 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',