| Index: chrome/browser/printing/print_view_manager_base.cc
|
| diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
| index df471305c8f649bf4f16837138007be6aedf2d9e..0e0958d15b534dd361ca2c44b51dafd1c0a27d87 100644
|
| --- a/chrome/browser/printing/print_view_manager_base.cc
|
| +++ b/chrome/browser/printing/print_view_manager_base.cc
|
| @@ -9,8 +9,11 @@
|
|
|
| #include "base/auto_reset.h"
|
| #include "base/bind.h"
|
| +#include "base/files/file_util.h"
|
| #include "base/location.h"
|
| #include "base/memory/ptr_util.h"
|
| +#include "base/memory/shared_memory.h"
|
| +#include "base/memory/shared_memory_handle.h"
|
| #include "base/run_loop.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| @@ -19,6 +22,7 @@
|
| #include "build/build_config.h"
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| +#include "chrome/browser/printing/print_composite_client.h"
|
| #include "chrome/browser/printing/print_job.h"
|
| #include "chrome/browser/printing/print_job_manager.h"
|
| #include "chrome/browser/printing/printer_query.h"
|
| @@ -34,10 +38,16 @@
|
| #include "content/public/browser/notification_source.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/render_view_host.h"
|
| +#include "content/public/browser/render_widget_host_view.h"
|
| #include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/service_manager_connection.h"
|
| #include "printing/features/features.h"
|
| #include "printing/pdf_metafile_skia.h"
|
| #include "printing/printed_document.h"
|
| +#include "services/pdf_compositor/public/cpp/compositor_data.h"
|
| +#include "services/service_manager/public/cpp/connector.h"
|
| +#include "third_party/skia/include/core/SkDocument.h"
|
| +#include "third_party/skia/include/core/SkStream.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
|
|
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
| @@ -85,6 +95,11 @@ PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents)
|
| prefs::kPrintingEnabled, profile->GetPrefs(),
|
| base::Bind(&PrintViewManagerBase::UpdatePrintingEnabled,
|
| base::Unretained(this)));
|
| + composite_client_ = PrintCompositeClient::FromWebContents(web_contents);
|
| + if (!composite_client_) {
|
| + PrintCompositeClient::CreateForWebContents(web_contents);
|
| + composite_client_ = PrintCompositeClient::FromWebContents(web_contents);
|
| + }
|
| }
|
|
|
| PrintViewManagerBase::~PrintViewManagerBase() {
|
| @@ -126,99 +141,79 @@ void PrintViewManagerBase::OnDidGetPrintedPagesCount(int cookie,
|
| OpportunisticallyCreatePrintJob(cookie);
|
| }
|
|
|
| -void PrintViewManagerBase::OnDidPrintPage(
|
| - const PrintHostMsg_DidPrintPage_Params& params) {
|
| - if (!OpportunisticallyCreatePrintJob(params.document_cookie))
|
| +void PrintViewManagerBase::OnComposePdfDone(
|
| + mojo::ScopedSharedBufferHandle handle) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + if (!handle.is_valid()) {
|
| + NOTREACHED() << "Pdf compositor returned invalid handle";
|
| return;
|
| + }
|
|
|
| - PrintedDocument* document = print_job_->document();
|
| - if (!document || params.document_cookie != document->cookie()) {
|
| - // Out of sync. It may happen since we are completely asynchronous. Old
|
| - // spurious messages can be received if one of the processes is overloaded.
|
| + base::SharedMemoryHandle memory_handle;
|
| + size_t memory_size = 0;
|
| + bool read_only_flag = false;
|
| +
|
| + const MojoResult result = mojo::UnwrapSharedMemoryHandle(
|
| + std::move(handle), &memory_handle, &memory_size, &read_only_flag);
|
| + DCHECK_EQ(MOJO_RESULT_OK, result);
|
| + DCHECK_GT(memory_size, 0u);
|
| +
|
| + std::unique_ptr<base::SharedMemory> shm(
|
| + new base::SharedMemory(memory_handle, true /* read_only */));
|
| + if (!shm->Map(memory_size)) {
|
| + NOTREACHED() << "Composited handle map error";
|
| return;
|
| }
|
|
|
| -#if defined(OS_MACOSX)
|
| - const bool metafile_must_be_valid = true;
|
| -#else
|
| - const bool metafile_must_be_valid = expecting_first_page_;
|
| - expecting_first_page_ = false;
|
| + PrintedDocument* document = print_job_->document();
|
| +
|
| +#if defined(OS_WIN)
|
| + scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(
|
| + (unsigned char*)shm->memory(), shm->mapped_size()));
|
| +
|
| + document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf"));
|
| +
|
| + const auto& settings = document->settings();
|
| + bool print_text_with_gdi =
|
| + settings.print_text_with_gdi() && !settings.printer_is_xps() &&
|
| + base::FeatureList::IsEnabled(features::kGdiTextPrinting);
|
| + print_job_->StartPdfToEmfConversion(bytes, gfx::Size(), gfx::Rect(),
|
| + print_text_with_gdi);
|
| #endif
|
| +}
|
|
|
| - // Only used when |metafile_must_be_valid| is true.
|
| - std::unique_ptr<base::SharedMemory> shared_buf;
|
| - if (metafile_must_be_valid) {
|
| - if (!base::SharedMemory::IsHandleValid(params.metafile_data_handle)) {
|
| - NOTREACHED() << "invalid memory handle";
|
| - web_contents()->Stop();
|
| - return;
|
| - }
|
| - shared_buf =
|
| - base::MakeUnique<base::SharedMemory>(params.metafile_data_handle, true);
|
| - if (!shared_buf->Map(params.data_size)) {
|
| - NOTREACHED() << "couldn't map";
|
| - web_contents()->Stop();
|
| - return;
|
| - }
|
| - } else {
|
| - if (base::SharedMemory::IsHandleValid(params.metafile_data_handle)) {
|
| - NOTREACHED() << "unexpected valid memory handle";
|
| - web_contents()->Stop();
|
| - base::SharedMemory::CloseHandle(params.metafile_data_handle);
|
| - return;
|
| - }
|
| +void PrintViewManagerBase::OnDidPrintPage(
|
| + content::RenderFrameHost* render_frame_host,
|
| + const PrintHostMsg_DidPrintPage_Params& params) {
|
| + const base::SharedMemoryHandle& handle = params.metafile_data_handle;
|
| + if (!base::SharedMemory::IsHandleValid(handle)) {
|
| + NOTREACHED() << "invalid memory handle";
|
| + web_contents()->Stop();
|
| + return;
|
| }
|
|
|
| - std::unique_ptr<PdfMetafileSkia> metafile(
|
| - new PdfMetafileSkia(PDF_SKIA_DOCUMENT_TYPE));
|
| - if (metafile_must_be_valid) {
|
| - if (!metafile->InitFromData(shared_buf->memory(), params.data_size)) {
|
| - NOTREACHED() << "Invalid metafile header";
|
| - web_contents()->Stop();
|
| - return;
|
| - }
|
| + if (params.is_subframe) {
|
| + composite_client_->AddSubFrameContent(render_frame_host->GetRoutingID(),
|
| + handle, params.data_size);
|
| + return;
|
| }
|
|
|
| -#if defined(OS_WIN)
|
| - print_job_->AppendPrintedPage(params.page_number);
|
| - if (metafile_must_be_valid) {
|
| - scoped_refptr<base::RefCountedBytes> bytes = new base::RefCountedBytes(
|
| - reinterpret_cast<const unsigned char*>(shared_buf->memory()),
|
| - params.data_size);
|
| - document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf"));
|
| -
|
| - const auto& settings = document->settings();
|
| - if ((settings.printer_is_ps2() || settings.printer_is_ps3()) &&
|
| - base::FeatureList::IsEnabled(features::kPostScriptPrinting)) {
|
| - print_job_->StartPdfToPostScriptConversion(bytes, params.content_area,
|
| - params.physical_offsets,
|
| - settings.printer_is_ps2());
|
| - } else {
|
| - // TODO(thestig): Figure out why rendering text with GDI results in random
|
| - // missing characters for some users. https://crbug.com/658606
|
| - // Update : The missing letters seem to have been caused by the same
|
| - // problem as https://crbug.com/659604 which was resolved. GDI printing
|
| - // seems to work with the fix for this bug applied.
|
| - bool print_text_with_gdi = settings.print_text_with_gdi() &&
|
| - !settings.printer_is_xps() &&
|
| - base::FeatureList::IsEnabled(
|
| - features::kGdiTextPrinting);
|
| - print_job_->StartPdfToEmfConversion(
|
| - bytes, params.page_size, params.content_area, print_text_with_gdi);
|
| - }
|
| + // Ready to composite. Starting a print job.
|
| + if (!OpportunisticallyCreatePrintJob(params.document_cookie))
|
| + return;
|
| +
|
| + PrintedDocument* document = print_job_->document();
|
| + if (!document || params.document_cookie != document->cookie()) {
|
| + // Out of sync. It may happen since we are completely asynchronous. Old
|
| + // spurious messages can be received if one of the processes is overloaded.
|
| + return;
|
| }
|
| -#else
|
| - // Update the rendered document. It will send notifications to the listener.
|
| - document->SetPage(params.page_number,
|
| - std::move(metafile),
|
| -#if defined(OS_WIN)
|
| - 0.0f /* dummy shrink_factor */,
|
| -#endif
|
| - params.page_size,
|
| - params.content_area);
|
|
|
| - ShouldQuitFromInnerMessageLoop();
|
| -#endif
|
| + composite_client_->DoComposite(
|
| + pdf_compositor::kPageRangeAll, params.metafile_data_handle,
|
| + params.data_size, base::Bind(&PrintViewManagerBase::OnComposePdfDone,
|
| + base::Unretained(this)),
|
| + base::ThreadTaskRunnerHandle::Get());
|
| }
|
|
|
| void PrintViewManagerBase::OnPrintingFailed(int cookie) {
|
| @@ -274,8 +269,15 @@ 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_DidPrintPage, OnDidPrintPage)
|
| + IPC_MESSAGE_UNHANDLED(handled = false)
|
| + IPC_END_MESSAGE_MAP()
|
| + if (handled)
|
| + return true;
|
| +
|
| + IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message)
|
| IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
|
| OnShowInvalidPrinterSettingsError)
|
| IPC_MESSAGE_UNHANDLED(handled = false)
|
| @@ -549,6 +551,7 @@ bool PrintViewManagerBase::PrintNowInternal(
|
| // Don't print / print preview interstitials or crashed tabs.
|
| if (web_contents()->ShowingInterstitialPage() || web_contents()->IsCrashed())
|
| return false;
|
| +
|
| return rfh->Send(message.release());
|
| }
|
|
|
|
|