144 lines
5.1 KiB
C++
144 lines
5.1 KiB
C++
|
// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/browser/printing/print_util.h"
|
||
|
|
||
|
#include "libcef/browser/thread_util.h"
|
||
|
|
||
|
#include "base/files/file_util.h"
|
||
|
#include "chrome/browser/printing/print_view_manager.h"
|
||
|
#include "chrome/browser/printing/print_view_manager_common.h"
|
||
|
#include "components/printing/browser/print_to_pdf/pdf_print_utils.h"
|
||
|
|
||
|
namespace print_util {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
// Write the PDF file to disk.
|
||
|
void SavePdfFile(const CefString& path,
|
||
|
CefRefPtr<CefPdfPrintCallback> callback,
|
||
|
scoped_refptr<base::RefCountedMemory> data) {
|
||
|
CEF_REQUIRE_BLOCKING();
|
||
|
DCHECK_GT(data->size(), 0U);
|
||
|
|
||
|
const bool ok =
|
||
|
base::WriteFile(path, reinterpret_cast<const char*>(data->data()),
|
||
|
data->size()) == static_cast<int>(data->size());
|
||
|
|
||
|
if (callback) {
|
||
|
CEF_POST_TASK(CEF_UIT,
|
||
|
base::BindOnce(&CefPdfPrintCallback::OnPdfPrintFinished,
|
||
|
callback, path, ok));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OnPDFCreated(const CefString& path,
|
||
|
CefRefPtr<CefPdfPrintCallback> callback,
|
||
|
print_to_pdf::PdfPrintResult print_result,
|
||
|
scoped_refptr<base::RefCountedMemory> data) {
|
||
|
if (print_result != print_to_pdf::PdfPrintResult::kPrintSuccess) {
|
||
|
LOG(ERROR) << "PrintToPDF failed with error: "
|
||
|
<< print_to_pdf::PdfPrintResultToString(print_result);
|
||
|
callback->OnPdfPrintFinished(CefString(), false);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Save the PDF file to disk and then execute the callback.
|
||
|
CEF_POST_USER_VISIBLE_TASK(
|
||
|
base::BindOnce(&SavePdfFile, path, callback, std::move(data)));
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
void Print(content::WebContents* web_contents, bool print_preview_disabled) {
|
||
|
// Like chrome::Print() but specifying the WebContents.
|
||
|
printing::StartPrint(web_contents,
|
||
|
/*print_renderer=*/mojo::NullAssociatedRemote(),
|
||
|
print_preview_disabled,
|
||
|
/*has_selection=*/false);
|
||
|
}
|
||
|
|
||
|
// Implementation based on PageHandler::PrintToPDF.
|
||
|
void PrintToPDF(content::WebContents* web_contents,
|
||
|
const CefString& path,
|
||
|
const CefPdfPrintSettings& settings,
|
||
|
CefRefPtr<CefPdfPrintCallback> callback) {
|
||
|
const bool display_header_footer = !!settings.display_header_footer;
|
||
|
|
||
|
// Defaults to no header/footer.
|
||
|
absl::optional<std::string> header_template, footer_template;
|
||
|
if (display_header_footer) {
|
||
|
if (settings.header_template.length > 0)
|
||
|
header_template = CefString(&settings.header_template);
|
||
|
if (settings.footer_template.length > 0)
|
||
|
footer_template = CefString(&settings.footer_template);
|
||
|
}
|
||
|
|
||
|
// Defaults to 1.0.
|
||
|
absl::optional<double> scale;
|
||
|
if (settings.scale > 0) {
|
||
|
scale = settings.scale;
|
||
|
}
|
||
|
|
||
|
// Defaults to letter size.
|
||
|
absl::optional<double> paper_width, paper_height;
|
||
|
if (settings.paper_width > 0 && settings.paper_height > 0) {
|
||
|
paper_width = settings.paper_width;
|
||
|
paper_height = settings.paper_height;
|
||
|
}
|
||
|
|
||
|
// Defaults to kDefaultMarginInInches.
|
||
|
absl::optional<double> margin_top, margin_bottom, margin_left, margin_right;
|
||
|
if (settings.margin_type == PDF_PRINT_MARGIN_NONE) {
|
||
|
margin_top = 0;
|
||
|
margin_bottom = 0;
|
||
|
margin_left = 0;
|
||
|
margin_right = 0;
|
||
|
} else if (settings.margin_type == PDF_PRINT_MARGIN_CUSTOM) {
|
||
|
if (settings.margin_top >= 0)
|
||
|
margin_top = settings.margin_top;
|
||
|
if (settings.margin_bottom >= 0)
|
||
|
margin_bottom = settings.margin_bottom;
|
||
|
if (settings.margin_left >= 0)
|
||
|
margin_left = settings.margin_left;
|
||
|
if (settings.margin_right >= 0)
|
||
|
margin_right = settings.margin_right;
|
||
|
}
|
||
|
|
||
|
absl::variant<printing::mojom::PrintPagesParamsPtr, std::string>
|
||
|
print_pages_params = print_to_pdf::GetPrintPagesParams(
|
||
|
web_contents->GetPrimaryMainFrame()->GetLastCommittedURL(),
|
||
|
!!settings.landscape, display_header_footer,
|
||
|
!!settings.print_background, scale, paper_width, paper_height,
|
||
|
margin_top, margin_bottom, margin_left, margin_right,
|
||
|
CefString(&settings.header_template),
|
||
|
CefString(&settings.footer_template),
|
||
|
!!settings.prefer_css_page_size);
|
||
|
|
||
|
if (absl::holds_alternative<std::string>(print_pages_params)) {
|
||
|
LOG(ERROR) << "PrintToPDF failed with error: "
|
||
|
<< absl::get<std::string>(print_pages_params);
|
||
|
callback->OnPdfPrintFinished(CefString(), false);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DCHECK(absl::holds_alternative<printing::mojom::PrintPagesParamsPtr>(
|
||
|
print_pages_params));
|
||
|
|
||
|
if (auto* print_manager =
|
||
|
printing::PrintViewManager::FromWebContents(web_contents)) {
|
||
|
print_manager->PrintToPdf(
|
||
|
web_contents->GetPrimaryMainFrame(), CefString(&settings.page_ranges),
|
||
|
std::move(absl::get<printing::mojom::PrintPagesParamsPtr>(
|
||
|
print_pages_params)),
|
||
|
base::BindOnce(&OnPDFCreated, path, callback));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LOG(ERROR) << "PrintToPDF was not handled.";
|
||
|
callback->OnPdfPrintFinished(CefString(), false);
|
||
|
}
|
||
|
|
||
|
} // namespace print_util
|