diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn index ee856f777d0eb..dd3b5f7ed8fb8 100644 --- a/chromium_src/BUILD.gn +++ b/chromium_src/BUILD.gn @@ -232,6 +232,8 @@ static_library("chrome") { "//chrome/browser/printing/printing_service.h", "//components/printing/browser/print_to_pdf/pdf_print_job.cc", "//components/printing/browser/print_to_pdf/pdf_print_job.h", + "//components/printing/browser/print_to_pdf/pdf_print_result.cc", + "//components/printing/browser/print_to_pdf/pdf_print_result.h", "//components/printing/browser/print_to_pdf/pdf_print_utils.cc", "//components/printing/browser/print_to_pdf/pdf_print_utils.h", ] diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 8974439bd7719..8b3482f82eceb 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -172,6 +172,7 @@ #if BUILDFLAG(ENABLE_PRINTING) #include "chrome/browser/printing/print_view_manager_base.h" #include "components/printing/browser/print_manager_utils.h" +#include "components/printing/browser/print_to_pdf/pdf_print_result.h" #include "components/printing/browser/print_to_pdf/pdf_print_utils.h" #include "printing/backend/print_backend.h" // nogncheck #include "printing/mojom/print.mojom.h" // nogncheck @@ -2900,12 +2901,12 @@ v8::Local WebContents::PrintToPDF(const base::Value& settings) { void WebContents::OnPDFCreated( gin_helper::Promise> promise, - PrintViewManagerElectron::PrintResult print_result, + print_to_pdf::PdfPrintResult print_result, scoped_refptr data) { - if (print_result != PrintViewManagerElectron::PrintResult::kPrintSuccess) { + if (print_result != print_to_pdf::PdfPrintResult::kPrintSuccess) { promise.RejectWithErrorMessage( "Failed to generate PDF: " + - PrintViewManagerElectron::PrintResultToString(print_result)); + print_to_pdf::PdfPrintResultToString(print_result)); return; } diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index 79f1182672a00..e838d0a3256f6 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -46,6 +46,7 @@ #include "ui/gfx/image/image.h" #if BUILDFLAG(ENABLE_PRINTING) +#include "components/printing/browser/print_to_pdf/pdf_print_result.h" #include "shell/browser/printing/print_view_manager_electron.h" #endif @@ -227,7 +228,7 @@ class WebContents : public ExclusiveAccessContext, // Print current page as PDF. v8::Local PrintToPDF(const base::Value& settings); void OnPDFCreated(gin_helper::Promise> promise, - PrintViewManagerElectron::PrintResult print_result, + print_to_pdf::PdfPrintResult print_result, scoped_refptr data); #endif diff --git a/shell/browser/printing/print_view_manager_electron.cc b/shell/browser/printing/print_view_manager_electron.cc index 3b0fb78348d69..fbb646cd9f0f8 100644 --- a/shell/browser/printing/print_view_manager_electron.cc +++ b/shell/browser/printing/print_view_manager_electron.cc @@ -60,124 +60,36 @@ void PrintViewManagerElectron::BindPrintManagerHost( print_manager->BindReceiver(std::move(receiver), rfh); } -// static -std::string PrintViewManagerElectron::PrintResultToString(PrintResult result) { - switch (result) { - case kPrintSuccess: - return std::string(); // no error message - case kPrintFailure: - return "Printing failed"; - case kInvalidPrinterSettings: - return "Show invalid printer settings error"; - case kInvalidMemoryHandle: - return "Invalid memory handle"; - case kMetafileMapError: - return "Map to shared memory error"; - case kMetafileInvalidHeader: - return "Invalid metafile header"; - case kMetafileGetDataError: - return "Get data from metafile error"; - case kSimultaneousPrintActive: - return "The previous printing job hasn't finished"; - case kPageRangeSyntaxError: - return "Page range syntax error"; - case kPageRangeInvalidRange: - return "Page range is invalid (start > end)"; - case kPageCountExceeded: - return "Page range exceeds page count"; - case kPrintingInProgress: - return "Page is already being printed"; - default: - NOTREACHED(); - return "Unknown PrintResult"; - } +void PrintViewManagerElectron::DidPrintToPdf( + int cookie, + PrintToPdfCallback callback, + print_to_pdf::PdfPrintResult result, + scoped_refptr memory) { + base::Erase(pdf_jobs_, cookie); + std::move(callback).Run(result, memory); } void PrintViewManagerElectron::PrintToPdf( content::RenderFrameHost* rfh, const std::string& page_ranges, printing::mojom::PrintPagesParamsPtr print_pages_params, - PrintToPDFCallback callback) { - DCHECK(callback); - - if (callback_) { - std::move(callback).Run(kSimultaneousPrintActive, - base::MakeRefCounted()); - return; - } - - if (!rfh->IsRenderFrameLive()) { - std::move(callback).Run(kPrintFailure, - base::MakeRefCounted()); - return; - } - - absl::variant - parsed_ranges = print_to_pdf::TextPageRangesToPageRanges(page_ranges); - if (absl::holds_alternative(parsed_ranges)) { - DCHECK_NE(absl::get(parsed_ranges), - print_to_pdf::PdfPrintResult::kPrintSuccess); - std::move(callback).Run( - static_cast( - absl::get(parsed_ranges)), - base::MakeRefCounted()); - return; - } - - printing_rfh_ = rfh; - print_pages_params->pages = absl::get(parsed_ranges); - headless_jobs_.emplace_back(print_pages_params->params->document_cookie); - callback_ = std::move(callback); - - // There is no need for a weak pointer here since the mojo proxy is held - // in the base class. If we're gone, mojo will discard the callback. - GetPrintRenderFrame(rfh)->PrintWithParams( + PrintToPdfCallback callback) { + // Store cookie in order to track job uniqueness and differentiate + // between regular and headless print jobs. + int cookie = print_pages_params->params->document_cookie; + pdf_jobs_.emplace_back(cookie); + + print_to_pdf::PdfPrintJob::StartJob( + web_contents(), rfh, GetPrintRenderFrame(rfh), page_ranges, std::move(print_pages_params), - base::BindOnce(&PrintViewManagerElectron::OnDidPrintWithParams, - base::Unretained(this))); -} - -void PrintViewManagerElectron::OnDidPrintWithParams( - printing::mojom::PrintWithParamsResultPtr result) { - if (result->is_failure_reason()) { - switch (result->get_failure_reason()) { - case printing::mojom::PrintFailureReason::kGeneralFailure: - FailJob(kPrintFailure); - return; - case printing::mojom::PrintFailureReason::kInvalidPageRange: - FailJob(kPageCountExceeded); - return; - case printing::mojom::PrintFailureReason::kPrintingInProgress: - FailJob(kPrintingInProgress); - return; - } - } - - printing::mojom::DidPrintDocumentParamsPtr& params = result->get_params(); - - auto& content = *params->content; - if (!content.metafile_data_region.IsValid()) { - FailJob(kInvalidMemoryHandle); - return; - } - - base::ReadOnlySharedMemoryMapping map = content.metafile_data_region.Map(); - if (!map.IsValid()) { - FailJob(kMetafileMapError); - return; - } - - std::string data = - std::string(static_cast(map.memory()), map.size()); - std::move(callback_).Run(kPrintSuccess, - base::RefCountedString::TakeString(&data)); - base::Erase(headless_jobs_, params->document_cookie); - Reset(); + base::BindOnce(&PrintViewManagerElectron::DidPrintToPdf, + weak_factory_.GetWeakPtr(), cookie, std::move(callback))); } void PrintViewManagerElectron::GetDefaultPrintSettings( GetDefaultPrintSettingsCallback callback) { - if (printing_rfh_) { + // This isn't ideal, but we're not able to access the document cookie here. + if (pdf_jobs_.size() > 0) { LOG(ERROR) << "Scripted print is not supported"; std::move(callback).Run(printing::mojom::PrintParams::New()); } else { @@ -188,9 +100,8 @@ void PrintViewManagerElectron::GetDefaultPrintSettings( void PrintViewManagerElectron::ScriptedPrint( printing::mojom::ScriptedPrintParamsPtr params, ScriptedPrintCallback callback) { - auto entry = - std::find(headless_jobs_.begin(), headless_jobs_.end(), params->cookie); - if (entry == headless_jobs_.end()) { + auto entry = std::find(pdf_jobs_.begin(), pdf_jobs_.end(), params->cookie); + if (entry == pdf_jobs_.end()) { PrintViewManagerBase::ScriptedPrint(std::move(params), std::move(callback)); return; } @@ -201,22 +112,13 @@ void PrintViewManagerElectron::ScriptedPrint( std::move(callback).Run(std::move(default_param), /*cancelled*/ false); } -void PrintViewManagerElectron::ShowInvalidPrinterSettingsError() { - if (headless_jobs_.size() == 0) { - PrintViewManagerBase::ShowInvalidPrinterSettingsError(); - return; - } - - FailJob(kInvalidPrinterSettings); -} - #if BUILDFLAG(ENABLE_PRINT_PREVIEW) void PrintViewManagerElectron::UpdatePrintSettings( int32_t cookie, base::Value::Dict job_settings, UpdatePrintSettingsCallback callback) { - auto entry = std::find(headless_jobs_.begin(), headless_jobs_.end(), cookie); - if (entry == headless_jobs_.end()) { + auto entry = std::find(pdf_jobs_.begin(), pdf_jobs_.end(), cookie); + if (entry == pdf_jobs_.end()) { PrintViewManagerBase::UpdatePrintSettings(cookie, std::move(job_settings), std::move(callback)); return; @@ -247,40 +149,14 @@ void PrintViewManagerElectron::CheckForCancel(int32_t preview_ui_id, } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) -void PrintViewManagerElectron::RenderFrameDeleted( - content::RenderFrameHost* render_frame_host) { - PrintViewManagerBase::RenderFrameDeleted(render_frame_host); - - if (printing_rfh_ != render_frame_host) - return; - - FailJob(kPrintFailure); -} - void PrintViewManagerElectron::DidGetPrintedPagesCount(int32_t cookie, uint32_t number_pages) { - auto entry = std::find(headless_jobs_.begin(), headless_jobs_.end(), cookie); - if (entry == headless_jobs_.end()) { + auto entry = std::find(pdf_jobs_.begin(), pdf_jobs_.end(), cookie); + if (entry == pdf_jobs_.end()) { PrintViewManagerBase::DidGetPrintedPagesCount(cookie, number_pages); } } -void PrintViewManagerElectron::Reset() { - printing_rfh_ = nullptr; - callback_.Reset(); - data_.clear(); -} - -void PrintViewManagerElectron::FailJob(PrintResult result) { - DCHECK_NE(result, kPrintSuccess); - if (callback_) { - std::move(callback_).Run(result, - base::MakeRefCounted()); - } - - Reset(); -} - WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintViewManagerElectron); } // namespace electron diff --git a/shell/browser/printing/print_view_manager_electron.h b/shell/browser/printing/print_view_manager_electron.h index a0b7eb28e6d7b..115c07fa39407 100644 --- a/shell/browser/printing/print_view_manager_electron.h +++ b/shell/browser/printing/print_view_manager_electron.h @@ -13,6 +13,7 @@ #include "base/memory/ref_counted_memory.h" #include "build/build_config.h" #include "chrome/browser/printing/print_view_manager_base.h" +#include "components/printing/browser/print_to_pdf/pdf_print_job.h" #include "components/printing/common/print.mojom.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents_observer.h" @@ -21,29 +22,12 @@ namespace electron { +using PrintToPdfCallback = print_to_pdf::PdfPrintJob::PrintToPdfCallback; + class PrintViewManagerElectron : public printing::PrintViewManagerBase, public content::WebContentsUserData { public: - enum PrintResult { - kPrintSuccess, - kPrintFailure, - kInvalidPrinterSettings, - kInvalidMemoryHandle, - kMetafileMapError, - kMetafileInvalidHeader, - kMetafileGetDataError, - kSimultaneousPrintActive, - kPageRangeSyntaxError, - kPageRangeInvalidRange, - kPageCountExceeded, - kPrintingInProgress - }; - - using PrintToPDFCallback = - base::OnceCallback)>; - ~PrintViewManagerElectron() override; PrintViewManagerElectron(const PrintViewManagerElectron&) = delete; @@ -54,30 +38,26 @@ class PrintViewManagerElectron receiver, content::RenderFrameHost* rfh); - static std::string PrintResultToString(PrintResult result); - + void DidPrintToPdf(int cookie, + PrintToPdfCallback callback, + print_to_pdf::PdfPrintResult result, + scoped_refptr memory); void PrintToPdf(content::RenderFrameHost* rfh, const std::string& page_ranges, printing::mojom::PrintPagesParamsPtr print_page_params, - PrintToPDFCallback callback); + PrintToPdfCallback callback); private: friend class content::WebContentsUserData; explicit PrintViewManagerElectron(content::WebContents* web_contents); - void OnDidPrintWithParams(printing::mojom::PrintWithParamsResultPtr result); - - // WebContentsObserver overrides (via PrintManager): - void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; - // printing::mojom::PrintManagerHost: void DidGetPrintedPagesCount(int32_t cookie, uint32_t number_pages) override; void GetDefaultPrintSettings( GetDefaultPrintSettingsCallback callback) override; void ScriptedPrint(printing::mojom::ScriptedPrintParamsPtr params, ScriptedPrintCallback callback) override; - void ShowInvalidPrinterSettingsError() override; #if BUILDFLAG(ENABLE_PRINT_PREVIEW) void UpdatePrintSettings(int32_t cookie, base::Value::Dict job_settings, @@ -91,14 +71,9 @@ class PrintViewManagerElectron int32_t request_id, CheckForCancelCallback callback) override; #endif + std::vector pdf_jobs_; - void FailJob(PrintResult result); - void Reset(); - - raw_ptr printing_rfh_ = nullptr; - PrintToPDFCallback callback_; - std::string data_; - std::vector headless_jobs_; + base::WeakPtrFactory weak_factory_{this}; WEB_CONTENTS_USER_DATA_KEY_DECL(); };