Commit 8c7a329b authored by xlou's avatar xlou Committed by Commit Bot

Added an interface to the printing Mojo service for N-up conversion.

Added an interface to the existing printing Mojo service for pdf N-up
Conversion for web content.  The service has two main functions:
NupPageConvert(): Convert N PDF pages to a N-up PDF.
NupDocumentConvert(): Convert a PDF document to a N-up PDF document.

In printing, 2-up, 3-up, or more generally N-up refers to a page
layout strategy in which multiple pages are composited onto a
single page.

Bug: 775999
Change-Id: I7c3b78a6d7b2fdaaa3d67e456b6b3b624480897e
Reviewed-on: https://chromium-review.googlesource.com/1172100
Commit-Queue: Shirleen Lou <xlou@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585097}
parent 10d3b3c2
......@@ -3555,6 +3555,8 @@ jumbo_split_static_library("browser") {
sources += [
"printing/background_printing_manager.cc",
"printing/background_printing_manager.h",
"printing/pdf_nup_converter_client.cc",
"printing/pdf_nup_converter_client.h",
"printing/print_dialog_cloud.cc",
"printing/print_dialog_cloud.h",
"printing/print_dialog_cloud_win.cc",
......
// Copyright 2018 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/browser/printing/pdf_nup_converter_client.h"
#include <utility>
#include "base/bind.h"
#include "chrome/services/printing/public/mojom/constants.mojom.h"
#include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h"
#include "content/public/common/service_manager_connection.h"
#include "services/service_manager/public/cpp/connector.h"
namespace printing {
PdfNupConverterClient::PdfNupConverterClient(content::WebContents* web_contents)
: web_contents_(web_contents) {}
PdfNupConverterClient::~PdfNupConverterClient() {}
void PdfNupConverterClient::DoNupPdfConvert(
int document_cookie,
uint32_t pages_per_sheet,
const gfx::Size& page_size,
std::vector<base::ReadOnlySharedMemoryRegion> pdf_page_regions,
mojom::PdfNupConverter::NupPageConvertCallback callback) {
auto& nup_converter = GetPdfNupConverterRequest(document_cookie);
nup_converter->NupPageConvert(pages_per_sheet, page_size,
std::move(pdf_page_regions),
std::move(callback));
}
void PdfNupConverterClient::DoNupPdfDocumentConvert(
int document_cookie,
uint32_t pages_per_sheet,
const gfx::Size& page_size,
base::ReadOnlySharedMemoryRegion src_pdf_document,
mojom::PdfNupConverter::NupDocumentConvertCallback callback) {
auto& nup_converter = GetPdfNupConverterRequest(document_cookie);
nup_converter->NupDocumentConvert(
pages_per_sheet, page_size, std::move(src_pdf_document),
base::BindOnce(&PdfNupConverterClient::OnDidNupPdfDocumentConvert,
base::Unretained(this), document_cookie,
std::move(callback)));
}
void PdfNupConverterClient::OnDidNupPdfDocumentConvert(
int document_cookie,
mojom::PdfNupConverter::NupDocumentConvertCallback callback,
mojom::PdfNupConverter::Status status,
base::ReadOnlySharedMemoryRegion region) {
RemovePdfNupConverterRequest(document_cookie);
std::move(callback).Run(status, std::move(region));
}
mojom::PdfNupConverterPtr& PdfNupConverterClient::GetPdfNupConverterRequest(
int cookie) {
auto iter = pdf_nup_converter_map_.find(cookie);
if (iter != pdf_nup_converter_map_.end()) {
DCHECK(iter->second.is_bound());
return iter->second;
}
auto iterator =
pdf_nup_converter_map_.emplace(cookie, CreatePdfNupConverterRequest())
.first;
return iterator->second;
}
void PdfNupConverterClient::RemovePdfNupConverterRequest(int cookie) {
size_t erased = pdf_nup_converter_map_.erase(cookie);
DCHECK_EQ(erased, 1u);
}
mojom::PdfNupConverterPtr
PdfNupConverterClient::CreatePdfNupConverterRequest() {
if (!connector_) {
service_manager::mojom::ConnectorRequest connector_request;
connector_ = service_manager::Connector::Create(&connector_request);
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->BindConnectorRequest(std::move(connector_request));
}
mojom::PdfNupConverterPtr pdf_nup_converter;
connector_->BindInterface(printing::mojom::kChromePrintingServiceName,
&pdf_nup_converter);
pdf_nup_converter->SetWebContentsURL(web_contents_->GetLastCommittedURL());
return pdf_nup_converter;
}
} // namespace printing
// Copyright 2018 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.
#ifndef CHROME_BROWSER_PRINTING_PDF_NUP_CONVERTER_CLIENT_H_
#define CHROME_BROWSER_PRINTING_PDF_NUP_CONVERTER_CLIENT_H_
#include <map>
#include <memory>
#include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h"
#include "content/public/browser/web_contents_user_data.h"
#include "services/service_manager/public/cpp/connector.h"
namespace printing {
// Class to manage print requests and their communication with pdf N-up
// converter service.
// Each N-up conversion request has a separate interface pointer to connect
// with remote service. The request and its printing results are tracked by its
// document cookie.
class PdfNupConverterClient
: public content::WebContentsUserData<PdfNupConverterClient> {
public:
explicit PdfNupConverterClient(content::WebContents* web_contents);
~PdfNupConverterClient() override;
void DoNupPdfConvert(
int document_cookie,
uint32_t pages_per_sheet,
const gfx::Size& page_size,
std::vector<base::ReadOnlySharedMemoryRegion> pdf_page_regions,
mojom::PdfNupConverter::NupPageConvertCallback callback);
void DoNupPdfDocumentConvert(
int document_cookie,
uint32_t pages_per_sheet,
const gfx::Size& page_size,
base::ReadOnlySharedMemoryRegion src_pdf_document,
mojom::PdfNupConverter::NupDocumentConvertCallback callback);
private:
void OnDidNupPdfDocumentConvert(
int document_cookie,
mojom::PdfNupConverter::NupDocumentConvertCallback callback,
mojom::PdfNupConverter::Status status,
base::ReadOnlySharedMemoryRegion region);
// Get the request or create a new one if none exists.
mojom::PdfNupConverterPtr& GetPdfNupConverterRequest(int cookie);
// Remove an existing request from |pdf_nup_converter_map_|.
void RemovePdfNupConverterRequest(int cookie);
mojom::PdfNupConverterPtr CreatePdfNupConverterRequest();
std::unique_ptr<service_manager::Connector> connector_;
// Stores the mapping between document cookies and their corresponding
// requests.
std::map<int, mojom::PdfNupConverterPtr> pdf_nup_converter_map_;
content::WebContents* web_contents_;
DISALLOW_COPY_AND_ASSIGN(PdfNupConverterClient);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PDF_NUP_CONVERTER_CLIENT_H_
......@@ -7,6 +7,8 @@ import("//services/service_manager/public/service_manifest.gni")
source_set("lib") {
sources = [
"pdf_nup_converter.cc",
"pdf_nup_converter.h",
"pdf_to_pwg_raster_converter.cc",
"pdf_to_pwg_raster_converter.h",
"printing_service.cc",
......@@ -16,6 +18,7 @@ source_set("lib") {
deps = [
"//base",
"//components/pwg_encoder",
"//components/services/pdf_compositor/public/cpp:utils",
"//mojo/public/cpp/bindings",
]
......
include_rules = [
"+components/crash/core/common/crash_key.h",
"+components/pwg_encoder",
"+components/services/pdf_compositor/public/cpp/pdf_service_mojo_utils.h",
]
......@@ -6,6 +6,7 @@
"service_manager:connector": {
"provides": {
"converter": [
"printing.mojom.PdfNupConverter",
"printing.mojom.PdfToEmfConverterFactory",
"printing.mojom.PdfToPwgRasterConverter" ]
},
......@@ -14,4 +15,4 @@
}
}
}
}
\ No newline at end of file
}
// Copyright 2018 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/services/printing/pdf_nup_converter.h"
#include <string>
#include <utility>
#include "base/containers/span.h"
#include "base/logging.h"
#include "components/crash/core/common/crash_key.h"
#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_utils.h"
#include "pdf/pdf.h"
namespace printing {
namespace {
// |pdf_mappings| which has the pdf page data needs to remain valid until
// ConvertPdfPagesToNupPdf completes, since base::span is a reference type.
std::vector<base::span<const uint8_t>> CreatePdfPagesVector(
const std::vector<base::ReadOnlySharedMemoryRegion>& pdf_page_regions,
std::vector<base::ReadOnlySharedMemoryMapping>* pdf_mappings) {
std::vector<base::span<const uint8_t>> pdf_page_span;
for (auto& pdf_page_region : pdf_page_regions) {
base::ReadOnlySharedMemoryMapping pdf_mapping = pdf_page_region.Map();
base::span<const uint8_t> pdf_page =
base::make_span(reinterpret_cast<const uint8_t*>(pdf_mapping.memory()),
pdf_mapping.size());
pdf_page_span.push_back(pdf_page);
pdf_mappings->push_back(std::move(pdf_mapping));
}
return pdf_page_span;
}
} // namespace
PdfNupConverter::PdfNupConverter(
std::unique_ptr<service_manager::ServiceContextRef> service_ref)
: service_ref_(std::move(service_ref)) {}
PdfNupConverter::~PdfNupConverter() {}
void PdfNupConverter::NupPageConvert(
uint32_t pages_per_sheet,
const gfx::Size& page_size,
std::vector<base::ReadOnlySharedMemoryRegion> pdf_page_regions,
NupPageConvertCallback callback) {
std::vector<base::ReadOnlySharedMemoryMapping> pdf_mappings;
std::vector<base::span<const uint8_t>> input_pdf_buffers =
CreatePdfPagesVector(pdf_page_regions, &pdf_mappings);
void* output_pdf_buffer = nullptr;
size_t output_pdf_buffer_size = 0;
base::MappedReadOnlyRegion region_mapping;
if (!chrome_pdf::ConvertPdfPagesToNupPdf(
std::move(input_pdf_buffers), pages_per_sheet, page_size.width(),
page_size.height(), &output_pdf_buffer, &output_pdf_buffer_size)) {
std::move(callback).Run(mojom::PdfNupConverter::Status::CONVERSION_FAILURE,
std::move(region_mapping.region));
return;
}
region_mapping = CreateReadOnlySharedMemoryRegion(output_pdf_buffer_size);
memcpy(region_mapping.mapping.memory(), output_pdf_buffer,
output_pdf_buffer_size);
free(output_pdf_buffer);
std::move(callback).Run(mojom::PdfNupConverter::Status::SUCCESS,
std::move(region_mapping.region));
}
void PdfNupConverter::NupDocumentConvert(
uint32_t pages_per_sheet,
const gfx::Size& page_size,
base::ReadOnlySharedMemoryRegion src_pdf_region,
NupDocumentConvertCallback callback) {
base::ReadOnlySharedMemoryMapping pdf_document_mapping = src_pdf_region.Map();
base::span<const uint8_t> input_pdf_buffer = base::make_span(
static_cast<const uint8_t*>(pdf_document_mapping.memory()),
pdf_document_mapping.size());
void* output_pdf_buffer = nullptr;
size_t output_pdf_buffer_size = 0;
base::MappedReadOnlyRegion region_mapping;
if (!chrome_pdf::ConvertPdfDocumentToNupPdf(
input_pdf_buffer, pages_per_sheet, page_size.width(),
page_size.height(), &output_pdf_buffer, &output_pdf_buffer_size)) {
std::move(callback).Run(mojom::PdfNupConverter::Status::CONVERSION_FAILURE,
std::move(region_mapping.region));
return;
}
region_mapping = CreateReadOnlySharedMemoryRegion(output_pdf_buffer_size);
memcpy(region_mapping.mapping.memory(), output_pdf_buffer,
output_pdf_buffer_size);
free(output_pdf_buffer);
std::move(callback).Run(mojom::PdfNupConverter::Status::SUCCESS,
std::move(region_mapping.region));
}
void PdfNupConverter::SetWebContentsURL(const GURL& url) {
// Record the most recent url we tried to print. This should be sufficient
// for users using print preview by default.
static crash_reporter::CrashKeyString<1024> crash_key("main-frame-url");
crash_key.Set(url.spec());
}
} // namespace printing
// Copyright 2018 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.
#ifndef CHROME_SERVICES_PRINTING_PDF_NUP_CONVERTER_H_
#define CHROME_SERVICES_PRINTING_PDF_NUP_CONVERTER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h"
#include "services/service_manager/public/cpp/service_context_ref.h"
namespace printing {
class PdfNupConverter : public printing::mojom::PdfNupConverter {
public:
explicit PdfNupConverter(
std::unique_ptr<service_manager::ServiceContextRef> service_ref);
~PdfNupConverter() override;
// printing::mojom::PdfNupConverter
void NupPageConvert(
uint32_t pages_per_sheet,
const gfx::Size& page_size,
std::vector<base::ReadOnlySharedMemoryRegion> pdf_page_regions,
NupPageConvertCallback callback) override;
void NupDocumentConvert(uint32_t pages_per_sheet,
const gfx::Size& page_size,
base::ReadOnlySharedMemoryRegion src_pdf_region,
NupDocumentConvertCallback callback) override;
void SetWebContentsURL(const GURL& url) override;
private:
const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
DISALLOW_COPY_AND_ASSIGN(PdfNupConverter);
};
} // namespace printing
#endif // CHROME_SERVICES_PRINTING_PDF_NUP_CONVERTER_H_
......@@ -5,6 +5,7 @@
#include "chrome/services/printing/printing_service.h"
#include "build/build_config.h"
#include "chrome/services/printing/pdf_nup_converter.h"
#include "chrome/services/printing/pdf_to_pwg_raster_converter.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
......@@ -35,6 +36,14 @@ void OnPdfToPwgRasterConverterRequest(
std::move(request));
}
void OnPdfNupConverterRequest(
service_manager::ServiceContextRefFactory* ref_factory,
printing::mojom::PdfNupConverterRequest request) {
mojo::MakeStrongBinding(
std::make_unique<printing::PdfNupConverter>(ref_factory->CreateRef()),
std::move(request));
}
} // namespace
PrintingService::PrintingService() = default;
......@@ -54,6 +63,9 @@ void PrintingService::OnStart() {
#endif
registry_.AddInterface(
base::Bind(&OnPdfToPwgRasterConverterRequest, ref_factory_.get()));
registry_.AddInterface(
base::Bind(&OnPdfNupConverterRequest, ref_factory_.get()));
}
void PrintingService::OnBindInterface(
......
......@@ -7,6 +7,7 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
"constants.mojom",
"pdf_nup_converter.mojom",
"pdf_render_settings.mojom",
"pdf_to_pwg_raster_converter.mojom",
]
......@@ -17,6 +18,7 @@ mojom("mojom") {
public_deps = [
"//mojo/public/mojom/base",
"//url/mojom:url_mojom_gurl",
]
if (is_win) {
......
// Copyright 2018 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.
module printing.mojom;
import "mojo/public/mojom/base/shared_memory.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
import "url/mojom/url.mojom";
// This set of interfaces is used to do Nup PDF conversion.
// Usage:
// - generate a PdfNupConverter.
//
// - call PdfNupConverter.NupPageConvert() to import N PDF pages into one N-up
// PDF page.
//
// - call PdfNupConverter.NupDocumentConvert() to convert a PDF document to a
// N-up PDF document.
//
// - call PdfNupConverter.SetWebContentsURL() to set the URL that is committed
// in the main frame of the WebContents for crash diagnosis.
interface PdfNupConverter {
// The status of PDF conversion execution.
enum Status {
SUCCESS = 0,
CONVERSION_FAILURE = 1,
};
// Convert a list of PDF pages to a N-up PDF.
// |pages_per_sheet| is the number of pages to put on a single sheet.
// |page_size| is the output page size, measured in PDF "user space" units.
// |pdf_page_regions| is a list of pdf pages to be converted to a N-up page.
// The number of items in |pdf_page_regions| can be different from N. It
// will return a N-up PDF document of
// Math.ceil(size of |pdf_page_regions| / N) pages in it.
NupPageConvert(
uint32 pages_per_sheet,
gfx.mojom.Size page_size,
array<mojo_base.mojom.ReadOnlySharedMemoryRegion> pdf_page_regions)
=> (Status status, mojo_base.mojom.ReadOnlySharedMemoryRegion? pdf_region);
// Convert a PDF document to a N-up PDF document.
// |pages_per_sheet| is the number of pages to put on a single sheet.
// |page_size| is the output page size, measured in PDF "user space" units.
NupDocumentConvert(uint32 pages_per_sheet,
gfx.mojom.Size page_size,
mojo_base.mojom.ReadOnlySharedMemoryRegion src_pdf_region)
=> (Status status, mojo_base.mojom.ReadOnlySharedMemoryRegion? pdf_region);
// Sets the URL which is committed in the main frame of the WebContents,
// for use in crash diagnosis.
SetWebContentsURL(url.mojom.Url url);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment