Skip to content

Commit

Permalink
Complete pdf compositor service
Browse files Browse the repository at this point in the history
Add interfaces and functions to allow passing in and compositing
contents from multiple frames in pdf compositor service.

Each frame is identified by its global unique id (rph id and rfh id).
Content id is a unique id within its process. Each frame may have oop
subframes. The pdf compositor service will keep track of all the frame
contents and their relationship. When all subframes are painted, the
service can composite the entire frame and convert it into PDF format.

Please refer document goo.gl/ACV6VM for more explanations.

BUG=455764

Change-Id: I3213d9ae0ca85d0ea695dd13acb00938499aa73b
Reviewed-on: https://chromium-review.googlesource.com/767912
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Wei Li <weili@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531687}
  • Loading branch information
weili0 authored and Commit Bot committed Jan 24, 2018
1 parent 23d38ad commit 8d73756
Show file tree
Hide file tree
Showing 22 changed files with 886 additions and 212 deletions.
27 changes: 20 additions & 7 deletions chrome/browser/printing/print_preview_message_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@
#include "components/printing/browser/print_composite_client.h"
#include "components/printing/browser/print_manager_utils.h"
#include "components/printing/common/print_messages.h"
#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
#include "components/printing/service/public/cpp/pdf_service_mojo_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "printing/common/pdf_metafile_utils.h"
#include "printing/page_size_margins.h"
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
Expand Down Expand Up @@ -125,6 +129,7 @@ void PrintPreviewMessageHandler::OnDidGetPreviewPageCount(
}

void PrintPreviewMessageHandler::OnDidPreviewPage(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewPage_Params& params) {
int page_number = params.page_number;
if (page_number < FIRST_PAGE_INDEX || !params.data_size)
Expand All @@ -139,8 +144,12 @@ void PrintPreviewMessageHandler::OnDidPreviewPage(
DCHECK(client);

// Use utility process to convert skia metafile to pdf.
client->DoComposite(
params.metafile_data_handle, params.data_size,
client->DoCompositePageToPdf(
params.document_cookie,
GenFrameGuid(render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID()),
params.page_number, params.metafile_data_handle, params.data_size,
ContentToFrameMap(),
base::BindOnce(&PrintPreviewMessageHandler::OnCompositePdfPageDone,
weak_ptr_factory_.GetWeakPtr(), params.page_number,
params.preview_request_id));
Expand All @@ -152,6 +161,7 @@ void PrintPreviewMessageHandler::OnDidPreviewPage(
}

void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewDocument_Params& params) {
// Always try to stop the worker.
StopWorker(params.document_cookie);
Expand All @@ -169,8 +179,11 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
auto* client = PrintCompositeClient::FromWebContents(web_contents());
DCHECK(client);

client->DoComposite(
params.metafile_data_handle, params.data_size,
client->DoCompositeDocumentToPdf(
params.document_cookie,
GenFrameGuid(render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID()),
params.metafile_data_handle, params.data_size, ContentToFrameMap(),
base::BindOnce(&PrintPreviewMessageHandler::OnCompositePdfDocumentDone,
weak_ptr_factory_.GetWeakPtr(),
params.expected_pages_count, params.preview_request_id));
Expand Down Expand Up @@ -294,6 +307,9 @@ bool PrintPreviewMessageHandler::OnMessageReceived(
render_frame_host)
IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
OnRequestPrintPreview)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage)
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
OnMetafileReadyForPrinting)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
if (handled)
Expand All @@ -303,9 +319,6 @@ bool PrintPreviewMessageHandler::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
OnDidGetPreviewPageCount)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage)
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
OnMetafileReadyForPrinting)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed,
OnPrintPreviewFailed)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDefaultPageLayout,
Expand Down
4 changes: 3 additions & 1 deletion chrome/browser/printing/print_preview_message_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ class PrintPreviewMessageHandler
bool has_custom_page_size_style);
void OnDidGetPreviewPageCount(
const PrintHostMsg_DidGetPreviewPageCount_Params& params);
void OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params& params);
void OnDidPreviewPage(content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewPage_Params& params);
void OnMetafileReadyForPrinting(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewDocument_Params& params);
void OnPrintPreviewFailed(int document_cookie);
void OnPrintPreviewCancelled(int document_cookie);
Expand Down
23 changes: 18 additions & 5 deletions chrome/browser/printing/print_view_manager_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "components/printing/browser/print_composite_client.h"
#include "components/printing/browser/print_manager_utils.h"
#include "components/printing/common/print_messages.h"
#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
#include "components/printing/service/public/cpp/pdf_service_mojo_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
Expand Down Expand Up @@ -333,6 +334,7 @@ void PrintViewManagerBase::OnComposePdfDone(
}

void PrintViewManagerBase::OnDidPrintDocument(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPrintDocument_Params& params) {
PrintedDocument* document = GetDocument(params.document_cookie);
if (!document)
Expand All @@ -347,12 +349,15 @@ void PrintViewManagerBase::OnDidPrintDocument(
auto* client = PrintCompositeClient::FromWebContents(web_contents());
if (IsOopifEnabled() && !client->for_preview() &&
document->settings().is_modifiable()) {
client->DoComposite(params.metafile_data_handle, params.data_size,
base::BindOnce(&PrintViewManagerBase::OnComposePdfDone,
weak_ptr_factory_.GetWeakPtr(), params));
client->DoCompositeDocumentToPdf(
params.document_cookie,
GenFrameGuid(render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID()),
params.metafile_data_handle, params.data_size, ContentToFrameMap(),
base::BindOnce(&PrintViewManagerBase::OnComposePdfDone,
weak_ptr_factory_.GetWeakPtr(), params));
return;
}

std::unique_ptr<base::SharedMemory> shared_buf =
std::make_unique<base::SharedMemory>(params.metafile_data_handle, true);
if (!shared_buf->Map(params.data_size)) {
Expand Down Expand Up @@ -435,8 +440,16 @@ bool PrintViewManagerBase::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message)
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintViewManagerBase, message,
render_frame_host)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintDocument, OnDidPrintDocument)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
if (handled)
return true;

handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
OnShowInvalidPrinterSettingsError)
IPC_MESSAGE_UNHANDLED(handled = false)
Expand Down
3 changes: 2 additions & 1 deletion chrome/browser/printing/print_view_manager_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class PrintViewManagerBase : public content::NotificationObserver,
void OnDidGetPrintedPagesCount(int cookie, int number_pages) override;
void OnPrintingFailed(int cookie) override;
void OnShowInvalidPrinterSettingsError();
void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params);
void OnDidPrintDocument(content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPrintDocument_Params& params);

// IPC message handlers for service.
void OnComposePdfDone(const PrintHostMsg_DidPrintDocument_Params& params,
Expand Down
2 changes: 1 addition & 1 deletion components/printing/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static_library("browser") {
deps = [
"//base",
"//components/printing/common",
"//components/printing/service/public/cpp:client",
"//components/printing/service/public/interfaces",
"//printing",
"//services/service_manager/public/cpp",
]
Expand Down
2 changes: 1 addition & 1 deletion components/printing/browser/DEPS
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
include_rules = [
"+components/printing/service/public/cpp",
"+components/printing/service/public/interfaces",
"+content/public/browser",
"+mojo/public/cpp/system",
"+services/service_manager/public/cpp",
Expand Down
119 changes: 105 additions & 14 deletions components/printing/browser/print_composite_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,132 @@

#include "components/printing/browser/print_composite_client.h"

#include <memory>
#include <utility>

#include "base/threading/thread_task_runner_handle.h"
#include "base/bind.h"
#include "base/memory/shared_memory_handle.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/service_manager/public/cpp/connector.h"

DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintCompositeClient);

namespace printing {

PrintCompositeClient::PrintCompositeClient(content::WebContents* web_contents)
: for_preview_(false) {}
: for_preview_(false) {
DCHECK(web_contents);
}

PrintCompositeClient::~PrintCompositeClient() {}

void PrintCompositeClient::CreateConnectorRequest() {
connector_ = service_manager::Connector::Create(&connector_request_);
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->BindConnectorRequest(std::move(connector_request_));
void PrintCompositeClient::DoCompositePageToPdf(
int document_cookie,
uint64_t frame_guid,
int page_num,
base::SharedMemoryHandle handle,
uint32_t data_size,
const ContentToFrameMap& subframe_content_map,
mojom::PdfCompositor::CompositePageToPdfCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto& compositor = GetCompositeRequest(document_cookie, page_num);

DCHECK(data_size);
mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
handle, data_size,
mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
// Since this class owns compositor, compositor will be gone when this class
// is destructed. Mojo won't call its callback in that case so it is safe to
// use unretained |this| pointer here.
compositor->CompositePageToPdf(
frame_guid, page_num, std::move(buffer_handle), subframe_content_map,
base::BindOnce(&PrintCompositeClient::OnDidCompositePageToPdf,
base::Unretained(this), page_num, document_cookie,
std::move(callback)));
}

void PrintCompositeClient::DoComposite(
void PrintCompositeClient::DoCompositeDocumentToPdf(
int document_cookie,
uint64_t frame_guid,
base::SharedMemoryHandle handle,
uint32_t data_size,
mojom::PdfCompositor::CompositePdfCallback callback) {
const ContentToFrameMap& subframe_content_map,
mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto& compositor = GetCompositeRequest(document_cookie, base::nullopt);

DCHECK(data_size);
mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
handle, data_size,
mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
// Since this class owns compositor, compositor will be gone when this class
// is destructed. Mojo won't call its callback in that case so it is safe to
// use unretained |this| pointer here.
compositor->CompositeDocumentToPdf(
frame_guid, std::move(buffer_handle), subframe_content_map,
base::BindOnce(&PrintCompositeClient::OnDidCompositeDocumentToPdf,
base::Unretained(this), document_cookie,
std::move(callback)));
}

void PrintCompositeClient::OnDidCompositePageToPdf(
int page_num,
int document_cookie,
printing::mojom::PdfCompositor::CompositePageToPdfCallback callback,
printing::mojom::PdfCompositor::Status status,
mojo::ScopedSharedBufferHandle handle) {
RemoveCompositeRequest(document_cookie, page_num);
std::move(callback).Run(status, std::move(handle));
}

void PrintCompositeClient::OnDidCompositeDocumentToPdf(
int document_cookie,
printing::mojom::PdfCompositor::CompositeDocumentToPdfCallback callback,
printing::mojom::PdfCompositor::Status status,
mojo::ScopedSharedBufferHandle handle) {
RemoveCompositeRequest(document_cookie, base::nullopt);
std::move(callback).Run(status, std::move(handle));
}

mojom::PdfCompositorPtr& PrintCompositeClient::GetCompositeRequest(
int cookie,
base::Optional<int> page_num) {
int page_no =
page_num == base::nullopt ? kPageNumForWholeDoc : page_num.value();
std::pair<int, int> key = std::make_pair(cookie, page_no);
auto iter = compositor_map_.find(key);
if (iter != compositor_map_.end())
return iter->second;

auto iterator = compositor_map_.emplace(key, CreateCompositeRequest()).first;
return iterator->second;
}

void PrintCompositeClient::RemoveCompositeRequest(
int cookie,
base::Optional<int> page_num) {
int page_no =
page_num == base::nullopt ? kPageNumForWholeDoc : page_num.value();
std::pair<int, int> key = std::make_pair(cookie, page_no);
auto iter = compositor_map_.find(key);
if (iter == compositor_map_.end())
return;

compositor_map_.erase(iter);
}

if (!connector_)
CreateConnectorRequest();
Composite(connector_.get(), handle, data_size, std::move(callback),
base::ThreadTaskRunnerHandle::Get());
mojom::PdfCompositorPtr PrintCompositeClient::CreateCompositeRequest() {
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::PdfCompositorPtr compositor;
connector_->BindInterface(mojom::kServiceName, &compositor);
return compositor;
}

} // namespace printing
Loading

0 comments on commit 8d73756

Please sign in to comment.