refactor: move printing out of chromium_src (#15023)

* remove printing related things from chromium_src

* chore: add printing build flag and patch

* fix: include PrintingService on other platforms too

* fix: printing_handler is only needed on Windows

* fix: format BUILD.gn properly

* fix: rename printing build flag to avoid conflict with chromium

* fix: place previously missed printing calls behind build flag

* fix: accidentally renamed flag in patch file

* fix: don't include all printing strings

* fix: allow ShowItemInFolder and OpenItem to block, fixing a DCHECK crash

* fix: make things compile, some changes got lost while rebasing

* fix: remove rogue line from BUILD.gn

* chore: update patch description

* style: lint fix

* chore: use chromium printing buildflag, move node related stuff out of patch

* revert: remove ScopedAllowBlockingForTesting call

* fix: fix my rebase blooper

* fix: re-add header lost during rebase, update patch

* fix: add <map> include, tweak the patch a bit

* revert: remove rogue diff from patch

* fix: clean up after rebase
This commit is contained in:
Heilig Benedek 2018-10-13 03:57:04 +02:00 committed by Samuel Attard
parent c806c465fa
commit a82bcc7e3c
53 changed files with 1398 additions and 7358 deletions

View file

@ -206,11 +206,11 @@ static_library("electron_lib") {
"native_mate",
"//base",
"//base:i18n",
"//chrome/common",
"//components/certificate_transparency",
"//components/net_log",
"//components/network_session_configurator/common",
"//components/prefs",
"//components/printing/common",
"//components/viz/service",
"//content/public/app:both",
"//content/public/child",
@ -221,7 +221,6 @@ static_library("electron_lib") {
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/shared_impl",
"//printing",
"//services/proxy_resolver:lib",
"//skia",
"//third_party/blink/public:blink",
@ -358,10 +357,10 @@ static_library("electron_lib") {
# Disable warnings for g_settings_list_schemas.
"GLIB_DISABLE_DEPRECATION_WARNINGS",
]
sources += filenames.lib_sources_nss
}
if (is_win) {
sources += filenames.lib_sources_win
libs += [ "dwmapi.lib" ]
}
if (is_linux || is_win) {
@ -428,6 +427,65 @@ static_library("electron_lib") {
]
}
if (enable_basic_printing) {
deps += [
"//chrome/common:mojo_bindings",
"//chrome/services/printing:lib",
"//components/printing/browser",
"//components/printing/common",
"//components/printing/renderer",
"//components/services/pdf_compositor/public/cpp:utils",
"//components/services/pdf_compositor/public/interfaces",
"//printing",
]
sources += [
"//chrome/browser/printing/print_job.cc",
"//chrome/browser/printing/print_job.h",
"//chrome/browser/printing/print_job_manager.cc",
"//chrome/browser/printing/print_job_manager.h",
"//chrome/browser/printing/print_job_worker.cc",
"//chrome/browser/printing/print_job_worker.h",
"//chrome/browser/printing/print_preview_message_handler.cc",
"//chrome/browser/printing/print_preview_message_handler.h",
"//chrome/browser/printing/print_view_manager_base.cc",
"//chrome/browser/printing/print_view_manager_base.h",
"//chrome/browser/printing/print_view_manager_basic.cc",
"//chrome/browser/printing/print_view_manager_basic.h",
"//chrome/browser/printing/print_view_manager_common.cc",
"//chrome/browser/printing/print_view_manager_common.h",
"//chrome/browser/printing/printer_manager_dialog.h",
"//chrome/browser/printing/printer_manager_dialog_linux.cc",
"//chrome/browser/printing/printer_manager_dialog_mac.mm",
"//chrome/browser/printing/printer_manager_dialog_win.cc",
"//chrome/browser/printing/printer_query.cc",
"//chrome/browser/printing/printer_query.h",
"//chrome/browser/printing/printing_message_filter.cc",
"//chrome/browser/printing/printing_message_filter.h",
"//chrome/renderer/prerender/prerender_dispatcher.cc",
"//chrome/renderer/prerender/prerender_dispatcher.h",
"//chrome/renderer/prerender/prerender_extra_data.cc",
"//chrome/renderer/prerender/prerender_extra_data.h",
"//chrome/renderer/prerender/prerender_helper.cc",
"//chrome/renderer/prerender/prerender_helper.h",
"//chrome/renderer/prerender/prerenderer_client.cc",
"//chrome/renderer/prerender/prerenderer_client.h",
"//chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc",
"//chrome/renderer/printing/chrome_print_render_frame_helper_delegate.h",
"//electron/atom/browser/atom_print_preview_message_handler.cc",
"//electron/atom/browser/atom_print_preview_message_handler.h",
]
if (is_win) {
sources += [
"//chrome/browser/printing/pdf_to_emf_converter.cc",
"//chrome/browser/printing/pdf_to_emf_converter.h",
"//chrome/utility/printing_handler.cc",
"//chrome/utility/printing_handler.h",
]
}
}
if (enable_pepper_flash) {
deps += [ "components/pepper_flash" ]
}
@ -770,7 +828,6 @@ group("chromium_unittests") {
"//mojo:mojo_unittests",
"//net:net_unittests",
"//ppapi:ppapi_unittests",
"//printing:printing_unittests",
"//skia:skia_unittests",
"//sql:sql_unittests",
"//storage:storage_unittests",
@ -788,6 +845,10 @@ group("chromium_unittests") {
"//v8/test/unittests:unittests",
]
if (enable_basic_printing) {
deps += [ "//printing:printing_unittests" ]
}
if (is_linux) {
deps += [
"//net:disk_cache_memory_test",
@ -929,6 +990,10 @@ group("electron_content_manifest_overlays") {
service_manifest("electron_content_packaged_services_manifest_overlay") {
source = "//electron/manifests/electron_content_packaged_services_manifest_overlay.json"
packaged_services = [ "//services/proxy_resolver:proxy_resolver_manifest" ]
if (enable_basic_printing) {
packaged_services += [ "//chrome/services/printing:manifest" ]
}
}
service_manifest("electron_content_browser_manifest_overlay") {

View file

@ -51,8 +51,6 @@
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/ssl/security_state_tab_helper.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
@ -81,6 +79,7 @@
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/url_request/url_request_context.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/web/web_find_options.h"
#include "ui/display/screen.h"
@ -101,6 +100,11 @@
#include "ui/gfx/font_render_params.h"
#endif
#if BUILDFLAG(ENABLE_PRINTING)
#include "atom/browser/atom_print_preview_message_handler.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#endif
#include "atom/common/node_includes.h"
namespace {
@ -110,6 +114,7 @@ struct PrintSettings {
bool print_background;
base::string16 device_name;
};
} // namespace
namespace mate {
@ -1423,6 +1428,7 @@ bool WebContents::IsCurrentlyAudible() {
}
void WebContents::Print(mate::Arguments* args) {
#if BUILDFLAG(ENABLE_PRINTING)
PrintSettings settings = {false, false, base::string16()};
if (args->Length() >= 1 && !args->GetNext(&settings)) {
args->ThrowError();
@ -1441,20 +1447,29 @@ void WebContents::Print(mate::Arguments* args) {
print_view_manager_basic_ptr->PrintNow(
web_contents()->GetMainFrame(), settings.silent,
settings.print_background, settings.device_name);
#else
LOG(ERROR) << "Printing is disabled";
#endif
}
std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
std::vector<printing::PrinterBasicInfo> printers;
#if BUILDFLAG(ENABLE_PRINTING)
auto print_backend = printing::PrintBackend::CreateInstance(nullptr);
base::ThreadRestrictions::ScopedAllowIO allow_io;
print_backend->EnumeratePrinters(&printers);
#endif
return printers;
}
void WebContents::PrintToPDF(const base::DictionaryValue& setting,
const PrintToPDFCallback& callback) {
printing::PrintPreviewMessageHandler::FromWebContents(web_contents())
#if BUILDFLAG(ENABLE_PRINTING)
AtomPrintPreviewMessageHandler::FromWebContents(web_contents())
->PrintToPDF(setting, callback);
#endif
}
void WebContents::AddWorkSpace(mate::Arguments* args,

View file

@ -59,6 +59,7 @@
#include "net/base/escape.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "ppapi/host/ppapi_host.h"
#include "printing/buildflags/buildflags.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
@ -88,6 +89,10 @@
#include "chrome/browser/speech/tts_message_filter.h"
#endif // BUILDFLAG(ENABLE_TTS)
#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/services/printing/public/mojom/constants.mojom.h"
#endif // BUILDFLAG(ENABLE_PRINTING)
using content::BrowserThread;
namespace atom {
@ -209,7 +214,9 @@ void AtomBrowserClient::RenderProcessWillLaunch(
if (IsProcessObserved(process_id))
return;
#if BUILDFLAG(ENABLE_PRINTING)
host->AddFilter(new printing::PrintingMessageFilter(process_id));
#endif
#if BUILDFLAG(ENABLE_TTS)
host->AddFilter(new TtsMessageFilter(host->GetBrowserContext()));
@ -535,6 +542,12 @@ void AtomBrowserClient::RegisterOutOfProcessServices(
(*services)[proxy_resolver::mojom::kProxyResolverServiceName] =
base::BindRepeating(&l10n_util::GetStringUTF16,
IDS_UTILITY_PROCESS_PROXY_RESOLVER_NAME);
#if BUILDFLAG(ENABLE_PRINTING)
(*services)[printing::mojom::kChromePrintingServiceName] =
base::BindRepeating(&l10n_util::GetStringUTF16,
IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME);
#endif
}
std::unique_ptr<base::Value> AtomBrowserClient::GetServiceManifestOverlay(

View file

@ -0,0 +1,134 @@
// Copyright (c) 2012 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 "atom/browser/atom_print_preview_message_handler.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/shared_memory.h"
#include "base/memory/shared_memory_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/print_preview_dialog_controller.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#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/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
#include "components/services/pdf_compositor/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/page_size_margins.h"
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
#include "atom/common/node_includes.h"
using content::BrowserThread;
using content::WebContents;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::AtomPrintPreviewMessageHandler);
namespace atom {
namespace {
char* CopyPDFDataOnIOThread(
const PrintHostMsg_DidPreviewDocument_Params& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const PrintHostMsg_DidPrintContent_Params& content = params.content;
std::unique_ptr<base::SharedMemory> shared_buf(
new base::SharedMemory(content.metafile_data_handle, true));
if (!shared_buf->Map(content.data_size))
return nullptr;
char* pdf_data = new char[content.data_size];
memcpy(pdf_data, shared_buf->memory(), content.data_size);
return pdf_data;
}
void FreeNodeBufferData(char* data, void* hint) {
delete[] data;
}
} // namespace
AtomPrintPreviewMessageHandler::AtomPrintPreviewMessageHandler(
WebContents* web_contents)
: printing::PrintPreviewMessageHandler(web_contents),
weak_ptr_factory_(this) {
DCHECK(web_contents);
}
AtomPrintPreviewMessageHandler::~AtomPrintPreviewMessageHandler() {}
void AtomPrintPreviewMessageHandler::OnMetafileReadyForPrinting(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewDocument_Params& params,
const PrintHostMsg_PreviewIds& ids) {
printing::PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
render_frame_host, params, ids);
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO, FROM_HERE, base::Bind(&CopyPDFDataOnIOThread, params),
base::Bind(&AtomPrintPreviewMessageHandler::RunPrintToPDFCallback,
base::Unretained(this), ids.request_id,
params.content.data_size));
}
void AtomPrintPreviewMessageHandler::OnPrintPreviewFailed(
int document_cookie,
const PrintHostMsg_PreviewIds& ids) {
printing::PrintPreviewMessageHandler::OnPrintPreviewFailed(document_cookie,
ids);
RunPrintToPDFCallback(ids.request_id, 0, nullptr);
}
void AtomPrintPreviewMessageHandler::PrintToPDF(
const base::DictionaryValue& options,
const PrintToPDFCallback& callback) {
int request_id;
options.GetInteger(printing::kPreviewRequestID, &request_id);
print_to_pdf_callback_map_[request_id] = callback;
content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options));
}
void AtomPrintPreviewMessageHandler::RunPrintToPDFCallback(int request_id,
uint32_t data_size,
char* data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (data) {
v8::Local<v8::Value> buffer =
node::Buffer::New(isolate, data, static_cast<size_t>(data_size),
&FreeNodeBufferData, nullptr)
.ToLocalChecked();
print_to_pdf_callback_map_[request_id].Run(v8::Null(isolate), buffer);
} else {
v8::Local<v8::String> error_message =
v8::String::NewFromUtf8(isolate, "Failed to generate PDF");
print_to_pdf_callback_map_[request_id].Run(
v8::Exception::Error(error_message), v8::Null(isolate));
}
print_to_pdf_callback_map_.erase(request_id);
}
} // namespace atom

View file

@ -0,0 +1,52 @@
// Copyright (c) 2012 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 ATOM_BROWSER_ATOM_PRINT_PREVIEW_MESSAGE_HANDLER_H_
#define ATOM_BROWSER_ATOM_PRINT_PREVIEW_MESSAGE_HANDLER_H_
#include <map>
#include "base/memory/weak_ptr.h"
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "content/public/browser/web_contents_user_data.h"
#include "v8/include/v8.h"
namespace atom {
// Manages the print preview handling for a WebContents.
class AtomPrintPreviewMessageHandler
: public printing::PrintPreviewMessageHandler,
public content::WebContentsUserData<AtomPrintPreviewMessageHandler> {
public:
~AtomPrintPreviewMessageHandler() override;
using PrintToPDFCallback =
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
void PrintToPDF(const base::DictionaryValue& options,
const PrintToPDFCallback& callback);
private:
explicit AtomPrintPreviewMessageHandler(content::WebContents* web_contents);
friend class content::WebContentsUserData<AtomPrintPreviewMessageHandler>;
typedef std::map<int, PrintToPDFCallback> PrintToPDFCallbackMap;
void OnMetafileReadyForPrinting(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewDocument_Params& params,
const PrintHostMsg_PreviewIds& ids) override;
void OnPrintPreviewFailed(int document_cookie,
const PrintHostMsg_PreviewIds& ids) override;
void RunPrintToPDFCallback(int request_id, uint32_t data_size, char* data);
PrintToPDFCallbackMap print_to_pdf_callback_map_;
base::WeakPtrFactory<PrintPreviewMessageHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AtomPrintPreviewMessageHandler);
};
} // namespace atom
#endif // ATOM_BROWSER_ATOM_PRINT_PREVIEW_MESSAGE_HANDLER_H_

View file

@ -21,8 +21,6 @@
#include "base/json/json_reader.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/ssl/security_state_tab_helper.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/common/pref_names.h"
@ -38,12 +36,18 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/security_style_explanation.h"
#include "content/public/browser/security_style_explanations.h"
#include "printing/buildflags/buildflags.h"
#include "storage/browser/fileapi/isolated_context.h"
#if BUILDFLAG(ENABLE_OSR)
#include "atom/browser/osr/osr_render_widget_host_view.h"
#endif
#if BUILDFLAG(ENABLE_PRINTING)
#include "atom/browser/atom_print_preview_message_handler.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#endif
using content::BrowserThread;
namespace atom {
@ -173,8 +177,10 @@ void CommonWebContentsDelegate::InitWithWebContents(
browser_context_ = browser_context;
web_contents->SetDelegate(this);
#if BUILDFLAG(ENABLE_PRINTING)
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents);
AtomPrintPreviewMessageHandler::CreateForWebContents(web_contents);
#endif
// Determien whether the WebContents is offscreen.
auto* web_preferences = WebContentsPreferences::From(web_contents);

View file

@ -5,5 +5,3 @@
// Multiply-included file, no traditional include guard.
#include "atom/common/api/api_messages.h"
#include "chrome/common/chrome_utility_printing_messages.h"
#include "chrome/common/print_messages.h"

View file

@ -18,7 +18,6 @@
#include "base/path_service.h"
#include "base/process/process_handle.h"
#include "brightray/common/application_info.h"
#include "chrome/renderer/printing/print_web_view_helper.h"
#include "content/public/renderer/render_frame.h"
#include "native_mate/dictionary.h"
#include "third_party/blink/public/web/blink.h"

View file

@ -19,13 +19,13 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "chrome/renderer/printing/print_web_view_helper.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "electron/buildflags/buildflags.h"
#include "native_mate/dictionary.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_custom_element.h" // NOLINT(build/include_alpha)
#include "third_party/blink/public/web/web_frame_widget.h"
@ -54,6 +54,11 @@
#include "chrome/renderer/tts_dispatcher.h"
#endif // BUILDFLAG(ENABLE_TTS)
#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/renderer/printing/chrome_print_render_frame_helper_delegate.h"
#include "components/printing/renderer/print_render_frame_helper.h"
#endif // BUILDFLAG(ENABLE_PRINTING)
namespace atom {
namespace {
@ -173,7 +178,10 @@ void RendererClientBase::RenderFrameCreated(
new PepperHelper(render_frame);
#endif
new ContentSettingsObserver(render_frame);
new printing::PrintWebViewHelper(render_frame);
#if BUILDFLAG(ENABLE_PRINTING)
new printing::PrintRenderFrameHelper(
render_frame, std::make_unique<ChromePrintRenderFrameHelperDelegate>());
#endif
#if BUILDFLAG(ENABLE_PDF_VIEWER)
// Allow access to file scheme from pdf viewer.

View file

@ -4,30 +4,79 @@
#include "atom/utility/atom_content_utility_client.h"
#include <utility>
#include "base/command_line.h"
#include "content/public/child/child_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/simple_connection_filter.h"
#include "services/proxy_resolver/proxy_resolver_service.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
#include "services/service_manager/sandbox/switches.h"
#if BUILDFLAG(ENABLE_PRINTING)
#include "chrome/services/printing/printing_service.h"
#include "chrome/services/printing/public/mojom/constants.mojom.h"
#if defined(OS_WIN)
#include "chrome/utility/printing_handler_win.h"
#endif
#include "chrome/services/printing/pdf_to_emf_converter_factory.h"
#include "chrome/utility/printing_handler.h"
#endif // defined(OS_WIN)
#endif // BUILDFLAG(ENABLE_PRINTING)
namespace atom {
AtomContentUtilityClient::AtomContentUtilityClient() {
#if defined(OS_WIN)
handlers_.push_back(std::make_unique<printing::PrintingHandlerWin>());
AtomContentUtilityClient::AtomContentUtilityClient() : elevated_(false) {
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
printing_handler_ = std::make_unique<printing::PrintingHandler>();
#endif
}
AtomContentUtilityClient::~AtomContentUtilityClient() {}
bool AtomContentUtilityClient::OnMessageReceived(const IPC::Message& message) {
// The guts of this came from the chromium implementation
// https://cs.chromium.org/chromium/src/chrome/utility/
// chrome_content_utility_client.cc?sq=package:chromium&dr=CSs&g=0&l=142
void AtomContentUtilityClient::UtilityThreadStarted() {
#if defined(OS_WIN)
for (const auto& handler : handlers_) {
if (handler->OnMessageReceived(message))
return true;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
elevated_ = command_line->HasSwitch(
service_manager::switches::kNoSandboxAndElevatedPrivileges);
#endif
content::ServiceManagerConnection* connection =
content::ChildThread::Get()->GetServiceManagerConnection();
// NOTE: Some utility process instances are not connected to the Service
// Manager. Nothing left to do in that case.
if (!connection)
return;
auto registry = std::make_unique<service_manager::BinderRegistry>();
// If our process runs with elevated privileges, only add elevated Mojo
// interfaces to the interface registry.
if (!elevated_) {
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
// TODO(crbug.com/798782): remove when the Cloud print chrome/service is
// removed.
registry->AddInterface(
base::BindRepeating(printing::PdfToEmfConverterFactory::Create),
base::ThreadTaskRunnerHandle::Get());
#endif
}
connection->AddConnectionFilter(
std::make_unique<content::SimpleConnectionFilter>(std::move(registry)));
}
bool AtomContentUtilityClient::OnMessageReceived(const IPC::Message& message) {
if (elevated_)
return false;
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
if (printing_handler_->OnMessageReceived(message))
return true;
#endif
return false;
@ -41,6 +90,13 @@ void AtomContentUtilityClient::RegisterServices(StaticServiceMap* services) {
base::BindRepeating(&proxy_resolver::ProxyResolverService::CreateService);
services->emplace(proxy_resolver::mojom::kProxyResolverServiceName,
proxy_resolver_info);
#if BUILDFLAG(ENABLE_PRINTING)
service_manager::EmbeddedServiceInfo printing_info;
printing_info.factory =
base::BindRepeating(&printing::PrintingService::CreateService);
services->emplace(printing::mojom::kChromePrintingServiceName, printing_info);
#endif
}
} // namespace atom

View file

@ -10,8 +10,11 @@
#include "base/compiler_specific.h"
#include "content/public/utility/content_utility_client.h"
#include "printing/buildflags/buildflags.h"
class UtilityMessageHandler;
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
#include "chrome/utility/printing_handler.h"
#endif
namespace atom {
@ -20,15 +23,17 @@ class AtomContentUtilityClient : public content::ContentUtilityClient {
AtomContentUtilityClient();
~AtomContentUtilityClient() override;
void UtilityThreadStarted() override;
bool OnMessageReceived(const IPC::Message& message) override;
void RegisterServices(StaticServiceMap* services) override;
private:
#if defined(OS_WIN)
typedef std::vector<std::unique_ptr<UtilityMessageHandler>> Handlers;
Handlers handlers_;
#if BUILDFLAG(ENABLE_PRINTING) && defined(OS_WIN)
std::unique_ptr<printing::PrintingHandler> printing_handler_;
#endif
bool elevated_;
DISALLOW_COPY_AND_ASSIGN(AtomContentUtilityClient);
};

View file

@ -10,4 +10,6 @@ enable_cdm_host_verification = false
proprietary_codecs = true
ffmpeg_branding = "Chrome"
enable_basic_printing = true
is_cfi = false

View file

@ -5,10 +5,13 @@
#include "chrome/browser/browser_process_impl.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
BrowserProcessImpl::BrowserProcessImpl()
: print_job_manager_(new printing::PrintJobManager) {
BrowserProcessImpl::BrowserProcessImpl() : print_job_manager_(nullptr) {
#if BUILDFLAG(ENABLE_PRINTING)
print_job_manager_.reset(new printing::PrintJobManager());
#endif
g_browser_process = this;
}

View file

@ -1,684 +0,0 @@
// Copyright 2014 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_to_emf_converter.h"
#include <stdint.h>
#include <windows.h>
#include <memory>
#include <queue>
#include <utility>
#include <vector>
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/sequenced_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/common/chrome_utility_printing_messages.h"
#include "content/browser/utility_process_host.h"
#include "content/browser/utility_process_host_client.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "printing/emf_win.h"
#include "printing/pdf_render_settings.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
namespace printing {
namespace {
void CloseFileOnBlockingTaskRunner(base::File temp_file) {
base::AssertBlockingAllowed();
temp_file.Close();
}
class PdfConverterImpl;
// Allows to delete temporary directory after all temporary files created inside
// are closed. Windows cannot delete directory with opened files. Directory is
// used to store PDF and metafiles. PDF should be gone by the time utility
// process exits. Metafiles should be gone when all LazyEmf destroyed.
class RefCountedTempDir
: public base::RefCountedDeleteOnSequence<RefCountedTempDir> {
public:
RefCountedTempDir()
: base::RefCountedDeleteOnSequence<RefCountedTempDir>(
base::SequencedTaskRunnerHandle::Get()) {
ignore_result(temp_dir_.CreateUniqueTempDir());
}
bool IsValid() const { return temp_dir_.IsValid(); }
const base::FilePath& GetPath() const { return temp_dir_.GetPath(); }
private:
friend class base::RefCountedDeleteOnSequence<RefCountedTempDir>;
friend class base::DeleteHelper<RefCountedTempDir>;
~RefCountedTempDir() {}
base::ScopedTempDir temp_dir_;
DISALLOW_COPY_AND_ASSIGN(RefCountedTempDir);
};
class TempFile {
public:
explicit TempFile(base::File file)
: file_(std::move(file)),
blocking_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
base::AssertBlockingAllowed();
}
~TempFile() {
blocking_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&CloseFileOnBlockingTaskRunner,
base::Passed(std::move(file_))));
}
base::File& file() { return file_; }
private:
base::File file_;
const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
DISALLOW_COPY_AND_ASSIGN(TempFile);
};
using ScopedTempFile = std::unique_ptr<TempFile>;
// Wrapper for Emf to keep only file handle in memory, and load actual data only
// on playback. Emf::InitFromFile() can play metafile directly from disk, but it
// can't open file handles. We need file handles to reliably delete temporary
// files, and to efficiently interact with utility process.
class LazyEmf : public MetafilePlayer {
public:
LazyEmf(const scoped_refptr<RefCountedTempDir>& temp_dir, ScopedTempFile file)
: temp_dir_(temp_dir), file_(std::move(file)) {
CHECK(file_);
}
~LazyEmf() override { Close(); }
protected:
// MetafilePlayer:
bool SafePlayback(HDC hdc) const override;
void Close() const;
bool LoadEmf(Emf* emf) const;
private:
mutable scoped_refptr<RefCountedTempDir> temp_dir_;
mutable ScopedTempFile file_; // Mutable because of consts in base class.
bool GetDataAsVector(std::vector<char>* buffer) const override;
bool SaveTo(base::File* file) const override;
DISALLOW_COPY_AND_ASSIGN(LazyEmf);
};
// Postscript metafile subclass to override SafePlayback.
class PostScriptMetaFile : public LazyEmf {
public:
PostScriptMetaFile(const scoped_refptr<RefCountedTempDir>& temp_dir,
ScopedTempFile file)
: LazyEmf(temp_dir, std::move(file)) {}
~PostScriptMetaFile() override;
private:
// MetafilePlayer:
bool SafePlayback(HDC hdc) const override;
DISALLOW_COPY_AND_ASSIGN(PostScriptMetaFile);
};
// Class for converting PDF to another format for printing (Emf, Postscript).
// Class uses UI thread, IO thread and |blocking_task_runner_|.
// Internal workflow is following:
// 1. Create instance on the UI thread. (files_, settings_,)
// 2. Create pdf file on |blocking_task_runner_|.
// 3. Start utility process and start conversion on the IO thread.
// 4. Utility process returns page count.
// 5. For each page:
// 1. Clients requests page with file handle to a temp file.
// 2. Utility converts the page, save it to the file and reply.
//
// All these steps work sequentially, so no data should be accessed
// simultaneously by several threads.
class PdfConverterUtilityProcessHostClient
: public content::UtilityProcessHostClient {
public:
PdfConverterUtilityProcessHostClient(
base::WeakPtr<PdfConverterImpl> converter,
const PdfRenderSettings& settings);
void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfConverter::StartCallback& start_callback);
void GetPage(int page_number,
const PdfConverter::GetPageCallback& get_page_callback);
void Stop();
// UtilityProcessHostClient implementation.
void OnProcessCrashed(int exit_code) override;
void OnProcessLaunchFailed(int exit_code) override;
// Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters
// sync message replies.
bool Send(IPC::Message* msg);
private:
class GetPageCallbackData {
public:
GetPageCallbackData(int page_number, PdfConverter::GetPageCallback callback)
: page_number_(page_number), callback_(callback) {}
GetPageCallbackData(GetPageCallbackData&& other) {
*this = std::move(other);
}
GetPageCallbackData& operator=(GetPageCallbackData&& rhs) {
page_number_ = rhs.page_number_;
callback_ = rhs.callback_;
file_ = std::move(rhs.file_);
return *this;
}
int page_number() const { return page_number_; }
const PdfConverter::GetPageCallback& callback() const { return callback_; }
ScopedTempFile TakeFile() { return std::move(file_); }
void set_file(ScopedTempFile file) { file_ = std::move(file); }
private:
int page_number_;
PdfConverter::GetPageCallback callback_;
ScopedTempFile file_;
DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData);
};
~PdfConverterUtilityProcessHostClient() override;
bool OnMessageReceived(const IPC::Message& message) override;
// Helper functions: must be overridden by subclasses
// Set the process name
base::string16 GetName() const;
// Create a metafileplayer subclass file from a temporary file.
std::unique_ptr<MetafilePlayer> GetFileFromTemp(ScopedTempFile temp_file);
// Send the messages to Start, GetPage, and Stop.
void SendStartMessage(IPC::PlatformFileForTransit transit);
void SendGetPageMessage(int page_number, IPC::PlatformFileForTransit transit);
void SendStopMessage();
// Message handlers:
void OnPageCount(int page_count);
void OnPageDone(bool success, float scale_factor);
void OnFailed();
void OnTempPdfReady(ScopedTempFile pdf);
void OnTempFileReady(GetPageCallbackData* callback_data,
ScopedTempFile temp_file);
// Additional message handler needed for Pdf to Emf
void OnPreCacheFontCharacters(const LOGFONT& log_font,
const base::string16& characters);
scoped_refptr<RefCountedTempDir> temp_dir_;
// Used to suppress callbacks after PdfConverter is deleted.
base::WeakPtr<PdfConverterImpl> converter_;
PdfRenderSettings settings_;
// Document loaded callback.
PdfConverter::StartCallback start_callback_;
// Process host for IPC.
base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
// Queue of callbacks for GetPage() requests. Utility process should reply
// with PageDone in the same order as requests were received.
// Use containers that keeps element pointers valid after push() and pop().
using GetPageCallbacks = std::queue<GetPageCallbackData>;
GetPageCallbacks get_page_callbacks_;
const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
DISALLOW_COPY_AND_ASSIGN(PdfConverterUtilityProcessHostClient);
};
std::unique_ptr<MetafilePlayer>
PdfConverterUtilityProcessHostClient::GetFileFromTemp(
ScopedTempFile temp_file) {
if (settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 ||
settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3) {
return std::make_unique<PostScriptMetaFile>(temp_dir_,
std::move(temp_file));
}
return std::make_unique<LazyEmf>(temp_dir_, std::move(temp_file));
}
class PdfConverterImpl : public PdfConverter {
public:
PdfConverterImpl();
~PdfConverterImpl() override;
base::WeakPtr<PdfConverterImpl> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const StartCallback& start_callback);
void GetPage(int page_number,
const GetPageCallback& get_page_callback) override;
// Helps to cancel callbacks if this object is destroyed.
void RunCallback(const base::Closure& callback);
void Start(
const scoped_refptr<PdfConverterUtilityProcessHostClient>& utility_client,
const scoped_refptr<base::RefCountedMemory>& data,
const StartCallback& start_callback);
private:
scoped_refptr<PdfConverterUtilityProcessHostClient> utility_client_;
base::WeakPtrFactory<PdfConverterImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PdfConverterImpl);
};
ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) {
if (!temp_dir->get())
*temp_dir = base::MakeRefCounted<RefCountedTempDir>();
ScopedTempFile file;
if (!(*temp_dir)->IsValid())
return file;
base::FilePath path;
if (!base::CreateTemporaryFileInDir((*temp_dir)->GetPath(), &path)) {
PLOG(ERROR) << "Failed to create file in "
<< (*temp_dir)->GetPath().value();
return file;
}
file = std::make_unique<TempFile>(base::File(
path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
base::File::FLAG_READ | base::File::FLAG_DELETE_ON_CLOSE |
base::File::FLAG_TEMPORARY));
if (!file->file().IsValid()) {
PLOG(ERROR) << "Failed to create " << path.value();
file.reset();
}
return file;
}
ScopedTempFile CreateTempPdfFile(
const scoped_refptr<base::RefCountedMemory>& data,
scoped_refptr<RefCountedTempDir>* temp_dir) {
ScopedTempFile pdf_file = CreateTempFile(temp_dir);
if (!pdf_file || static_cast<int>(data->size()) !=
pdf_file->file().WriteAtCurrentPos(
data->front_as<char>(), data->size())) {
pdf_file.reset();
return pdf_file;
}
pdf_file->file().Seek(base::File::FROM_BEGIN, 0);
return pdf_file;
}
bool LazyEmf::SafePlayback(HDC hdc) const {
Emf emf;
bool result = LoadEmf(&emf) && emf.SafePlayback(hdc);
// TODO(thestig): Fix destruction of metafiles. For some reasons
// instances of Emf are not deleted. https://crbug.com/260806
// It's known that the Emf going to be played just once to a printer. So just
// release |file_| here.
Close();
return result;
}
bool LazyEmf::GetDataAsVector(std::vector<char>* buffer) const {
NOTREACHED();
return false;
}
bool LazyEmf::SaveTo(base::File* file) const {
Emf emf;
return LoadEmf(&emf) && emf.SaveTo(file);
}
void LazyEmf::Close() const {
file_.reset();
temp_dir_ = nullptr;
}
bool LazyEmf::LoadEmf(Emf* emf) const {
file_->file().Seek(base::File::FROM_BEGIN, 0);
int64_t size = file_->file().GetLength();
if (size <= 0)
return false;
std::vector<char> data(size);
if (file_->file().ReadAtCurrentPos(data.data(), data.size()) != size)
return false;
return emf->InitFromData(data.data(), data.size());
}
PostScriptMetaFile::~PostScriptMetaFile() {}
bool PostScriptMetaFile::SafePlayback(HDC hdc) const {
// TODO(thestig): Fix destruction of metafiles. For some reasons
// instances of Emf are not deleted. https://crbug.com/260806
// It's known that the Emf going to be played just once to a printer. So just
// release |file_| before returning.
Emf emf;
if (!LoadEmf(&emf)) {
Close();
return false;
}
{
// Ensure enumerator destruction before calling Close() below.
Emf::Enumerator emf_enum(emf, nullptr, nullptr);
for (const Emf::Record& record : emf_enum) {
auto* emf_record = record.record();
if (emf_record->iType != EMR_GDICOMMENT)
continue;
const EMRGDICOMMENT* comment =
reinterpret_cast<const EMRGDICOMMENT*>(emf_record);
const char* data = reinterpret_cast<const char*>(comment->Data);
const uint16_t* ptr = reinterpret_cast<const uint16_t*>(data);
int ret = ExtEscape(hdc, PASSTHROUGH, 2 + *ptr, data, 0, nullptr);
DCHECK_EQ(*ptr, ret);
}
}
Close();
return true;
}
PdfConverterUtilityProcessHostClient::PdfConverterUtilityProcessHostClient(
base::WeakPtr<PdfConverterImpl> converter,
const PdfRenderSettings& settings)
: converter_(converter),
settings_(settings),
blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {}
PdfConverterUtilityProcessHostClient::~PdfConverterUtilityProcessHostClient() {}
void PdfConverterUtilityProcessHostClient::Start(
const scoped_refptr<base::RefCountedMemory>& data,
const PdfConverter::StartCallback& start_callback) {
CHECK(false) << "Printing doesn't work yet.";
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PdfConverterUtilityProcessHostClient::Start, this, data,
start_callback));
return;
}
// Store callback before any OnFailed() call to make it called on failure.
start_callback_ = start_callback;
// NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load
// gdiplus.dll, change how rendering happens, and not be able to correctly
// generate when sent to a metafile DC.
/*
utility_process_host_ = content::UtilityProcessHost::Create(
this, base::ThreadTaskRunnerHandle::Get())
->AsWeakPtr();
*/
utility_process_host_ = nullptr;
utility_process_host_->SetName(GetName());
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(), FROM_HERE,
base::Bind(&CreateTempPdfFile, data, &temp_dir_),
base::Bind(&PdfConverterUtilityProcessHostClient::OnTempPdfReady, this));
}
void PdfConverterUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!utility_process_host_ || !pdf)
return OnFailed();
// Should reply with OnPageCount().
SendStartMessage(
IPC::GetPlatformFileForTransit(pdf->file().GetPlatformFile(), false));
}
void PdfConverterUtilityProcessHostClient::OnPageCount(int page_count) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (start_callback_.is_null())
return OnFailed();
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&PdfConverterImpl::RunCallback, converter_,
base::Bind(start_callback_, page_count)));
start_callback_.Reset();
}
void PdfConverterUtilityProcessHostClient::GetPage(
int page_number,
const PdfConverter::GetPageCallback& get_page_callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PdfConverterUtilityProcessHostClient::GetPage, this,
page_number, get_page_callback));
return;
}
// Store callback before any OnFailed() call to make it called on failure.
get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback));
if (!utility_process_host_)
return OnFailed();
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(), FROM_HERE,
base::Bind(&CreateTempFile, &temp_dir_),
base::Bind(&PdfConverterUtilityProcessHostClient::OnTempFileReady, this,
&get_page_callbacks_.back()));
}
void PdfConverterUtilityProcessHostClient::OnTempFileReady(
GetPageCallbackData* callback_data,
ScopedTempFile temp_file) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!utility_process_host_ || !temp_file)
return OnFailed();
IPC::PlatformFileForTransit transit = IPC::GetPlatformFileForTransit(
temp_file->file().GetPlatformFile(), false);
callback_data->set_file(std::move(temp_file));
// Should reply with OnPageDone().
SendGetPageMessage(callback_data->page_number(), transit);
}
void PdfConverterUtilityProcessHostClient::OnPageDone(bool success,
float scale_factor) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (get_page_callbacks_.empty())
return OnFailed();
GetPageCallbackData& data = get_page_callbacks_.front();
std::unique_ptr<MetafilePlayer> file;
if (success) {
ScopedTempFile temp_file = data.TakeFile();
if (!temp_file) // Unexpected message from utility process.
return OnFailed();
file = GetFileFromTemp(std::move(temp_file));
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&PdfConverterImpl::RunCallback, converter_,
base::Bind(data.callback(), data.page_number(), scale_factor,
base::Passed(&file))));
get_page_callbacks_.pop();
}
void PdfConverterUtilityProcessHostClient::Stop() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PdfConverterUtilityProcessHostClient::Stop, this));
return;
}
SendStopMessage();
}
void PdfConverterUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
OnFailed();
}
void PdfConverterUtilityProcessHostClient::OnProcessLaunchFailed(
int exit_code) {
OnFailed();
}
bool PdfConverterUtilityProcessHostClient::Send(IPC::Message* msg) {
if (utility_process_host_)
#if 1
CHECK(false) << "Printing is broken.";
#else
return utility_process_host_->Send(msg);
#endif
delete msg;
return false;
}
void PdfConverterUtilityProcessHostClient::OnFailed() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!start_callback_.is_null())
OnPageCount(0);
while (!get_page_callbacks_.empty())
OnPageDone(false, 0.0f);
utility_process_host_.reset();
}
void PdfConverterUtilityProcessHostClient::OnPreCacheFontCharacters(
const LOGFONT& font,
const base::string16& str) {
// TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
// GDI fonts (http://crbug.com/383227), even when using DirectWrite.
// Eventually this shouldn't be added and should be moved to
// FontCacheDispatcher too. http://crbug.com/356346.
// First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
// Except that for True Type fonts,
// GetTextMetrics will not load the font in memory.
// The only way windows seem to load properly, it is to create a similar
// device (like the one in which we print), then do an ExtTextOut,
// as we do in the printing thread, which is sandboxed.
HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr);
HFONT font_handle = CreateFontIndirect(&font);
DCHECK(font_handle != nullptr);
HGDIOBJ old_font = SelectObject(hdc, font_handle);
DCHECK(old_font != nullptr);
ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr);
SelectObject(hdc, old_font);
DeleteObject(font_handle);
HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
if (metafile)
DeleteEnhMetaFile(metafile);
}
bool PdfConverterUtilityProcessHostClient::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PdfConverterUtilityProcessHostClient, message)
IPC_MESSAGE_HANDLER(
ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount)
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
OnPageDone)
#if 0
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters,
OnPreCacheFontCharacters)
#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
base::string16 PdfConverterUtilityProcessHostClient::GetName() const {
return L"ChromeUtilityProcessPDFConvertor";
}
void PdfConverterUtilityProcessHostClient::SendGetPageMessage(
int page_number,
IPC::PlatformFileForTransit transit) {
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage(page_number,
transit));
}
void PdfConverterUtilityProcessHostClient::SendStartMessage(
IPC::PlatformFileForTransit transit) {
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(transit, settings_));
}
void PdfConverterUtilityProcessHostClient::SendStopMessage() {
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
}
// Pdf Converter Impl and subclasses
PdfConverterImpl::PdfConverterImpl() : weak_ptr_factory_(this) {}
PdfConverterImpl::~PdfConverterImpl() {
if (utility_client_.get())
utility_client_->Stop();
}
void PdfConverterImpl::Start(
const scoped_refptr<PdfConverterUtilityProcessHostClient>& utility_client,
const scoped_refptr<base::RefCountedMemory>& data,
const StartCallback& start_callback) {
DCHECK(!utility_client_);
utility_client_ = utility_client;
utility_client_->Start(data, start_callback);
}
void PdfConverterImpl::GetPage(int page_number,
const GetPageCallback& get_page_callback) {
utility_client_->GetPage(page_number, get_page_callback);
}
void PdfConverterImpl::RunCallback(const base::Closure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
callback.Run();
}
} // namespace
PdfConverter::~PdfConverter() {}
// static
std::unique_ptr<PdfConverter> PdfConverter::StartPdfConverter(
const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const StartCallback& start_callback) {
std::unique_ptr<PdfConverterImpl> converter =
std::make_unique<PdfConverterImpl>();
converter->Start(new PdfConverterUtilityProcessHostClient(
converter->GetWeakPtr(), conversion_settings),
data, start_callback);
return std::move(converter);
}
} // namespace printing

View file

@ -1,43 +0,0 @@
// Copyright 2014 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_TO_EMF_CONVERTER_H_
#define CHROME_BROWSER_PRINTING_PDF_TO_EMF_CONVERTER_H_
#include <memory>
#include "base/callback.h"
#include "base/memory/ref_counted_memory.h"
namespace printing {
class MetafilePlayer;
struct PdfRenderSettings;
class PdfConverter {
public:
using StartCallback = base::Callback<void(int page_count)>;
using GetPageCallback =
base::Callback<void(int page_number,
float scale_factor,
std::unique_ptr<MetafilePlayer> file)>;
virtual ~PdfConverter();
// Starts conversion of PDF provided as |data|. Calls |start_callback|
// with positive |page_count|. |page_count| is 0 if initialization failed.
static std::unique_ptr<PdfConverter> StartPdfConverter(
const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const StartCallback& start_callback);
// Requests conversion of the page. |page_number| is 0-base page number in
// PDF provided in Start() call.
// Calls |get_page_callback| after conversion. |emf| of callback in not NULL
// if conversion succeeded.
virtual void GetPage(int page_number,
const GetPageCallback& get_page_callback) = 0;
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PDF_TO_EMF_CONVERTER_H_

View file

@ -1,468 +0,0 @@
// Copyright (c) 2012 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/print_job.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job_worker.h"
#include "content/public/browser/notification_service.h"
#include "printing/printed_document.h"
#if defined(OS_WIN)
#include "chrome/browser/printing/pdf_to_emf_converter.h"
#include "printing/metafile.h"
#include "printing/pdf_render_settings.h"
#endif
using base::TimeDelta;
namespace printing {
namespace {
// Helper function to ensure |owner| is valid until at least |callback| returns.
void HoldRefCallback(const scoped_refptr<PrintJobWorkerOwner>& owner,
const base::Closure& callback) {
callback.Run();
}
} // namespace
PrintJob::PrintJob()
: is_job_pending_(false), is_canceling_(false), quit_factory_(this) {
DCHECK(base::MessageLoopForUI::IsCurrent());
}
PrintJob::~PrintJob() {
// The job should be finished (or at least canceled) when it is destroyed.
DCHECK(!is_job_pending_);
DCHECK(!is_canceling_);
DCHECK(!worker_ || !worker_->IsRunning());
DCHECK(RunsTasksInCurrentSequence());
}
void PrintJob::Initialize(PrintJobWorkerOwner* job,
const base::string16& name,
int page_count) {
DCHECK(!worker_);
DCHECK(!is_job_pending_);
DCHECK(!is_canceling_);
DCHECK(!document_.get());
worker_ = job->DetachWorker(this);
settings_ = job->settings();
PrintedDocument* new_doc =
new PrintedDocument(settings_, name, job->cookie());
new_doc->set_page_count(page_count);
UpdatePrintedDocument(new_doc);
// Don't forget to register to our own messages.
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::Source<PrintJob>(this));
}
void PrintJob::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(RunsTasksInCurrentSequence());
DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
}
void PrintJob::GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) {
NOTREACHED();
}
std::unique_ptr<PrintJobWorker> PrintJob::DetachWorker(
PrintJobWorkerOwner* new_owner) {
NOTREACHED();
return nullptr;
}
const PrintSettings& PrintJob::settings() const {
return settings_;
}
int PrintJob::cookie() const {
// Always use an invalid cookie in this case.
if (!document_.get())
return 0;
return document_->cookie();
}
void PrintJob::StartPrinting() {
DCHECK(RunsTasksInCurrentSequence());
if (!worker_->IsRunning() || is_job_pending_) {
NOTREACHED();
return;
}
// Real work is done in PrintJobWorker::StartPrinting().
worker_->PostTask(FROM_HERE,
base::Bind(&HoldRefCallback, WrapRefCounted(this),
base::Bind(&PrintJobWorker::StartPrinting,
base::Unretained(worker_.get()),
base::RetainedRef(document_))));
// Set the flag right now.
is_job_pending_ = true;
// Tell everyone!
scoped_refptr<JobEventDetails> details(
new JobEventDetails(JobEventDetails::NEW_DOC, 0, document_.get()));
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<PrintJob>(this),
content::Details<JobEventDetails>(details.get()));
}
void PrintJob::Stop() {
DCHECK(RunsTasksInCurrentSequence());
if (quit_factory_.HasWeakPtrs()) {
// In case we're running a nested message loop to wait for a job to finish,
// and we finished before the timeout, quit the nested loop right away.
Quit();
quit_factory_.InvalidateWeakPtrs();
}
// Be sure to live long enough.
scoped_refptr<PrintJob> handle(this);
if (worker_->IsRunning()) {
ControlledWorkerShutdown();
} else {
// Flush the cached document.
is_job_pending_ = false;
UpdatePrintedDocument(nullptr);
}
}
void PrintJob::Cancel() {
if (is_canceling_)
return;
is_canceling_ = true;
// Be sure to live long enough.
scoped_refptr<PrintJob> handle(this);
DCHECK(RunsTasksInCurrentSequence());
if (worker_ && worker_->IsRunning()) {
// Call this right now so it renders the context invalid. Do not use
// InvokeLater since it would take too much time.
worker_->Cancel();
}
// Make sure a Cancel() is broadcast.
scoped_refptr<JobEventDetails> details(
new JobEventDetails(JobEventDetails::FAILED, 0, nullptr));
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<PrintJob>(this),
content::Details<JobEventDetails>(details.get()));
Stop();
is_canceling_ = false;
}
bool PrintJob::FlushJob(base::TimeDelta timeout) {
// Make sure the object outlive this message loop.
scoped_refptr<PrintJob> handle(this);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&PrintJob::Quit, quit_factory_.GetWeakPtr()),
timeout);
base::MessageLoop::ScopedNestableTaskAllower allow;
base::RunLoop().Run();
return true;
}
bool PrintJob::is_job_pending() const {
return is_job_pending_;
}
PrintedDocument* PrintJob::document() const {
return document_.get();
}
#if defined(OS_WIN)
class PrintJob::PdfConversionState {
public:
PdfConversionState(gfx::Size page_size, gfx::Rect content_area)
: page_count_(0),
current_page_(0),
pages_in_progress_(0),
page_size_(page_size),
content_area_(content_area) {}
void Start(const scoped_refptr<base::RefCountedMemory>& data,
const PdfRenderSettings& conversion_settings,
const PdfConverter::StartCallback& start_callback) {
converter_ = PdfConverter::StartPdfConverter(data, conversion_settings,
start_callback);
}
void GetMorePages(const PdfConverter::GetPageCallback& get_page_callback) {
const int kMaxNumberOfTempFilesPerDocument = 3;
while (pages_in_progress_ < kMaxNumberOfTempFilesPerDocument &&
current_page_ < page_count_) {
++pages_in_progress_;
converter_->GetPage(current_page_++, get_page_callback);
}
}
void OnPageProcessed(const PdfConverter::GetPageCallback& get_page_callback) {
--pages_in_progress_;
GetMorePages(get_page_callback);
// Release converter if we don't need this any more.
if (!pages_in_progress_ && current_page_ >= page_count_)
converter_.reset();
}
void set_page_count(int page_count) { page_count_ = page_count; }
gfx::Size page_size() const { return page_size_; }
gfx::Rect content_area() const { return content_area_; }
private:
int page_count_;
int current_page_;
int pages_in_progress_;
gfx::Size page_size_;
gfx::Rect content_area_;
std::unique_ptr<PdfConverter> converter_;
};
void PrintJob::AppendPrintedPage(int page_number) {
pdf_page_mapping_.push_back(page_number);
}
void PrintJob::StartPdfToEmfConversion(
const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Size& page_size,
const gfx::Rect& content_area,
bool print_text_with_gdi) {
DCHECK(!pdf_conversion_state_);
pdf_conversion_state_ =
std::make_unique<PdfConversionState>(page_size, content_area);
const int kPrinterDpi = settings().dpi();
PdfRenderSettings settings(
content_area, gfx::Point(0, 0), gfx::Size(kPrinterDpi, kPrinterDpi),
/*autorotate=*/true, settings_.color() == COLOR,
print_text_with_gdi ? PdfRenderSettings::Mode::GDI_TEXT
: PdfRenderSettings::Mode::NORMAL);
pdf_conversion_state_->Start(
bytes, settings, base::Bind(&PrintJob::OnPdfConversionStarted, this));
}
void PrintJob::OnPdfConversionStarted(int page_count) {
if (page_count <= 0) {
pdf_conversion_state_.reset();
Cancel();
return;
}
pdf_conversion_state_->set_page_count(page_count);
pdf_conversion_state_->GetMorePages(
base::Bind(&PrintJob::OnPdfPageConverted, this));
}
void PrintJob::OnPdfPageConverted(int page_number,
float scale_factor,
std::unique_ptr<MetafilePlayer> metafile) {
DCHECK(pdf_conversion_state_);
if (!document_.get() || !metafile || page_number < 0 ||
static_cast<size_t>(page_number) >= pdf_page_mapping_.size()) {
pdf_conversion_state_.reset();
Cancel();
return;
}
// Update the rendered document. It will send notifications to the listener.
document_->SetPage(pdf_page_mapping_[page_number], std::move(metafile),
scale_factor, pdf_conversion_state_->page_size(),
pdf_conversion_state_->content_area());
pdf_conversion_state_->GetMorePages(
base::Bind(&PrintJob::OnPdfPageConverted, this));
}
void PrintJob::StartPdfToPostScriptConversion(
const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Rect& content_area,
const gfx::Point& physical_offsets,
bool ps_level2) {
DCHECK(!pdf_conversion_state_);
pdf_conversion_state_ =
std::make_unique<PdfConversionState>(gfx::Size(), gfx::Rect());
const int kPrinterDpi = settings().dpi();
PdfRenderSettings settings(
content_area, physical_offsets, gfx::Size(kPrinterDpi, kPrinterDpi),
true /* autorotate? */, settings_.color() == COLOR,
ps_level2 ? PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2
: PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3);
pdf_conversion_state_->Start(
bytes, settings, base::Bind(&PrintJob::OnPdfConversionStarted, this));
}
#endif // defined(OS_WIN)
void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
if (document_.get() == new_document)
return;
document_ = new_document;
if (document_.get())
settings_ = document_->settings();
if (worker_) {
DCHECK(!is_job_pending_);
// Sync the document with the worker.
worker_->PostTask(FROM_HERE,
base::Bind(&HoldRefCallback, WrapRefCounted(this),
base::Bind(&PrintJobWorker::OnDocumentChanged,
base::Unretained(worker_.get()),
base::RetainedRef(document_))));
}
}
void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
switch (event_details.type()) {
case JobEventDetails::FAILED: {
settings_.Clear();
// No need to cancel since the worker already canceled itself.
Stop();
break;
}
case JobEventDetails::USER_INIT_DONE:
case JobEventDetails::DEFAULT_INIT_DONE:
case JobEventDetails::USER_INIT_CANCELED: {
DCHECK_EQ(event_details.document(), document_.get());
break;
}
case JobEventDetails::NEW_DOC:
case JobEventDetails::NEW_PAGE:
case JobEventDetails::JOB_DONE:
case JobEventDetails::ALL_PAGES_REQUESTED: {
// Don't care.
break;
}
case JobEventDetails::DOC_DONE: {
// This will call Stop() and broadcast a JOB_DONE message.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this));
break;
}
case JobEventDetails::PAGE_DONE:
#if defined(OS_WIN)
if (pdf_conversion_state_) {
pdf_conversion_state_->OnPageProcessed(
base::Bind(&PrintJob::OnPdfPageConverted, this));
}
#endif // defined(OS_WIN)
break;
default: {
NOTREACHED();
break;
}
}
}
void PrintJob::OnDocumentDone() {
// Be sure to live long enough. The instance could be destroyed by the
// JOB_DONE broadcast.
scoped_refptr<PrintJob> handle(this);
// Stop the worker thread.
Stop();
scoped_refptr<JobEventDetails> details(
new JobEventDetails(JobEventDetails::JOB_DONE, 0, document_.get()));
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT, content::Source<PrintJob>(this),
content::Details<JobEventDetails>(details.get()));
}
void PrintJob::ControlledWorkerShutdown() {
DCHECK(RunsTasksInCurrentSequence());
// The deadlock this code works around is specific to window messaging on
// Windows, so we aren't likely to need it on any other platforms.
#if defined(OS_WIN)
// We could easily get into a deadlock case if worker_->Stop() is used; the
// printer driver created a window as a child of the browser window. By
// canceling the job, the printer driver initiated dialog box is destroyed,
// which sends a blocking message to its parent window. If the browser window
// thread is not processing messages, a deadlock occurs.
//
// This function ensures that the dialog box will be destroyed in a timely
// manner by the mere fact that the thread will terminate. So the potential
// deadlock is eliminated.
worker_->StopSoon();
// Delay shutdown until the worker terminates. We want this code path
// to wait on the thread to quit before continuing.
if (worker_->IsRunning()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&PrintJob::ControlledWorkerShutdown, this),
base::TimeDelta::FromMilliseconds(100));
return;
}
#endif
// Now make sure the thread object is cleaned up. Do this on a worker
// thread because it may block.
base::PostTaskAndReply(
FROM_HERE,
base::Bind(&PrintJobWorker::Stop, base::Unretained(worker_.get())),
base::Bind(&PrintJob::HoldUntilStopIsCalled, this));
is_job_pending_ = false;
registrar_.RemoveAll();
UpdatePrintedDocument(nullptr);
}
void PrintJob::HoldUntilStopIsCalled() {}
void PrintJob::Quit() {
base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
// Takes settings_ ownership and will be deleted in the receiving thread.
#if defined(OS_WIN)
JobEventDetails::JobEventDetails(Type type,
int job_id,
PrintedDocument* document,
PrintedPage* page)
: document_(document), page_(page), type_(type), job_id_(job_id) {}
#endif
JobEventDetails::JobEventDetails(Type type,
int job_id,
PrintedDocument* document)
: document_(document), type_(type), job_id_(job_id) {}
JobEventDetails::~JobEventDetails() {}
PrintedDocument* JobEventDetails::document() const {
return document_.get();
}
#if defined(OS_WIN)
PrintedPage* JobEventDetails::page() const {
return page_.get();
}
#endif
} // namespace printing

View file

@ -1,246 +0,0 @@
// Copyright (c) 2012 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_PRINT_JOB_H_
#define CHROME_BROWSER_PRINTING_PRINT_JOB_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/printing/print_job_worker_owner.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#if defined(OS_WIN)
#include "printing/printed_page_win.h"
#endif
namespace base {
class RefCountedMemory;
}
namespace printing {
class JobEventDetails;
class MetafilePlayer;
class PdfToEmfConverter;
class PrintJobWorker;
class PrintedDocument;
#if defined(OS_WIN)
class PrintedPage;
#endif
class PrinterQuery;
// Manages the print work for a specific document. Talks to the printer through
// PrintingContext through PrintJobWorker. Hides access to PrintingContext in a
// worker thread so the caller never blocks. PrintJob will send notifications on
// any state change. While printing, the PrintJobManager instance keeps a
// reference to the job to be sure it is kept alive. All the code in this class
// runs in the UI thread.
class PrintJob : public PrintJobWorkerOwner,
public content::NotificationObserver {
public:
// Create a empty PrintJob. When initializing with this constructor,
// post-constructor initialization must be done with Initialize().
PrintJob();
// Grabs the ownership of the PrintJobWorker from another job, which is
// usually a PrinterQuery. Set the expected page count of the print job.
void Initialize(PrintJobWorkerOwner* job,
const base::string16& name,
int page_count);
// content::NotificationObserver implementation.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// PrintJobWorkerOwner implementation.
void GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) override;
std::unique_ptr<PrintJobWorker> DetachWorker(
PrintJobWorkerOwner* new_owner) override;
const PrintSettings& settings() const override;
int cookie() const override;
// Starts the actual printing. Signals the worker that it should begin to
// spool as soon as data is available.
void StartPrinting();
// Asks for the worker thread to finish its queued tasks and disconnects the
// delegate object. The PrintJobManager will remove its reference. This may
// have the side-effect of destroying the object if the caller doesn't have a
// handle to the object. Use PrintJob::is_stopped() to check whether the
// worker thread has actually stopped.
void Stop();
// Cancels printing job and stops the worker thread. Takes effect immediately.
void Cancel();
// Synchronously wait for the job to finish. It is mainly useful when the
// process is about to be shut down and we're waiting for the spooler to eat
// our data.
bool FlushJob(base::TimeDelta timeout);
// Returns true if the print job is pending, i.e. between a StartPrinting()
// and the end of the spooling.
bool is_job_pending() const;
// Access the current printed document. Warning: may be NULL.
PrintedDocument* document() const;
#if defined(OS_WIN)
// Let the PrintJob know the 0-based |page_number| of a given printed page.
void AppendPrintedPage(int page_number);
void StartPdfToEmfConversion(
const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Size& page_size,
const gfx::Rect& content_area,
bool print_text_with_gdi);
void StartPdfToPostScriptConversion(
const scoped_refptr<base::RefCountedMemory>& bytes,
const gfx::Rect& content_area,
const gfx::Point& physical_offset,
bool ps_level2);
#endif // defined(OS_WIN)
protected:
~PrintJob() override;
private:
// Updates |document_| to a new instance.
void UpdatePrintedDocument(PrintedDocument* new_document);
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
void OnNotifyPrintJobEvent(const JobEventDetails& event_details);
// Releases the worker thread by calling Stop(), then broadcasts a JOB_DONE
// notification.
void OnDocumentDone();
// Terminates the worker thread in a very controlled way, to work around any
// eventual deadlock.
void ControlledWorkerShutdown();
// Called at shutdown when running a nested message loop.
void Quit();
void HoldUntilStopIsCalled();
#if defined(OS_WIN)
void OnPdfConversionStarted(int page_count);
void OnPdfPageConverted(int page_number,
float scale_factor,
std::unique_ptr<MetafilePlayer> emf);
#endif // defined(OS_WIN)
content::NotificationRegistrar registrar_;
// All the UI is done in a worker thread because many Win32 print functions
// are blocking and enters a message loop without your consent. There is one
// worker thread per print job.
std::unique_ptr<PrintJobWorker> worker_;
// Cache of the print context settings for access in the UI thread.
PrintSettings settings_;
// The printed document.
scoped_refptr<PrintedDocument> document_;
// Is the worker thread printing.
bool is_job_pending_;
// Is Canceling? If so, try to not cause recursion if on FAILED notification,
// the notified calls Cancel() again.
bool is_canceling_;
#if defined(OS_WIN)
class PdfConversionState;
std::unique_ptr<PdfConversionState> pdf_conversion_state_;
std::vector<int> pdf_page_mapping_;
#endif // defined(OS_WIN)
// Used at shutdown so that we can quit a nested message loop.
base::WeakPtrFactory<PrintJob> quit_factory_;
DISALLOW_COPY_AND_ASSIGN(PrintJob);
};
// Details for a NOTIFY_PRINT_JOB_EVENT notification. The members may be NULL.
class JobEventDetails : public base::RefCountedThreadSafe<JobEventDetails> {
public:
// Event type.
enum Type {
// Print... dialog box has been closed with OK button.
USER_INIT_DONE,
// Print... dialog box has been closed with CANCEL button.
USER_INIT_CANCELED,
// An automated initialization has been done, e.g. Init(false, NULL).
DEFAULT_INIT_DONE,
// A new document started printing.
NEW_DOC,
// A new page started printing.
NEW_PAGE,
// A page is done printing.
PAGE_DONE,
// A document is done printing. The worker thread is still alive. Warning:
// not a good moment to release the handle to PrintJob.
DOC_DONE,
// The worker thread is finished. A good moment to release the handle to
// PrintJob.
JOB_DONE,
// All missing pages have been requested.
ALL_PAGES_REQUESTED,
// An error occured. Printing is canceled.
FAILED,
};
#if defined(OS_WIN)
JobEventDetails(Type type,
int job_id,
PrintedDocument* document,
PrintedPage* page);
#endif
JobEventDetails(Type type, int job_id, PrintedDocument* document);
// Getters.
PrintedDocument* document() const;
#if defined(OS_WIN)
PrintedPage* page() const;
#endif
Type type() const { return type_; }
int job_id() const { return job_id_; }
private:
friend class base::RefCountedThreadSafe<JobEventDetails>;
~JobEventDetails();
scoped_refptr<PrintedDocument> document_;
#if defined(OS_WIN)
scoped_refptr<PrintedPage> page_;
#endif
const Type type_;
int job_id_;
DISALLOW_COPY_AND_ASSIGN(JobEventDetails);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_H_

View file

@ -1,151 +0,0 @@
// Copyright (c) 2012 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/print_job_manager.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job.h"
#include "chrome/browser/printing/printer_query.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "printing/printed_document.h"
namespace printing {
PrintQueriesQueue::PrintQueriesQueue() {}
PrintQueriesQueue::~PrintQueriesQueue() {
base::AutoLock lock(lock_);
queued_queries_.clear();
}
void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) {
base::AutoLock lock(lock_);
DCHECK(job);
queued_queries_.push_back(WrapRefCounted(job));
DCHECK(job->is_valid());
}
scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
int document_cookie) {
base::AutoLock lock(lock_);
for (PrinterQueries::iterator itr = queued_queries_.begin();
itr != queued_queries_.end(); ++itr) {
if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) {
scoped_refptr<PrinterQuery> current_query(*itr);
queued_queries_.erase(itr);
DCHECK(current_query->is_valid());
return current_query;
}
}
return NULL;
}
scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery(
int render_process_id,
int render_frame_id) {
return WrapRefCounted(new PrinterQuery(render_process_id, render_frame_id));
}
void PrintQueriesQueue::Shutdown() {
PrinterQueries queries_to_stop;
{
base::AutoLock lock(lock_);
queued_queries_.swap(queries_to_stop);
}
// Stop all pending queries, requests to generate print preview do not have
// corresponding PrintJob, so any pending preview requests are not covered
// by PrintJobManager::StopJobs and should be stopped explicitly.
for (PrinterQueries::iterator itr = queries_to_stop.begin();
itr != queries_to_stop.end(); ++itr) {
(*itr)->PostTask(FROM_HERE, base::Bind(&PrinterQuery::StopWorker, *itr));
}
}
PrintJobManager::PrintJobManager() : is_shutdown_(false) {
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::NotificationService::AllSources());
}
PrintJobManager::~PrintJobManager() {}
scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!queue_.get())
queue_ = new PrintQueriesQueue();
return queue_;
}
void PrintJobManager::Shutdown() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(!is_shutdown_);
is_shutdown_ = true;
registrar_.RemoveAll();
StopJobs(true);
if (queue_.get())
queue_->Shutdown();
queue_ = NULL;
}
void PrintJobManager::StopJobs(bool wait_for_finish) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Copy the array since it can be modified in transit.
PrintJobs to_stop;
to_stop.swap(current_jobs_);
for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
++job) {
// Wait for two minutes for the print job to be spooled.
if (wait_for_finish)
(*job)->FlushJob(base::TimeDelta::FromMinutes(2));
(*job)->Stop();
}
}
void PrintJobManager::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
*content::Details<JobEventDetails>(details).ptr());
}
void PrintJobManager::OnPrintJobEvent(PrintJob* print_job,
const JobEventDetails& event_details) {
switch (event_details.type()) {
case JobEventDetails::NEW_DOC: {
DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
// Causes a AddRef().
current_jobs_.insert(print_job);
break;
}
case JobEventDetails::JOB_DONE: {
DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
current_jobs_.erase(print_job);
break;
}
case JobEventDetails::FAILED: {
current_jobs_.erase(print_job);
break;
}
case JobEventDetails::USER_INIT_DONE:
case JobEventDetails::USER_INIT_CANCELED:
case JobEventDetails::DEFAULT_INIT_DONE:
case JobEventDetails::NEW_PAGE:
case JobEventDetails::PAGE_DONE:
case JobEventDetails::DOC_DONE:
case JobEventDetails::ALL_PAGES_REQUESTED: {
// Don't care.
break;
}
default: {
NOTREACHED();
break;
}
}
}
} // namespace printing

View file

@ -1,100 +0,0 @@
// Copyright (c) 2012 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_PRINT_JOB_MANAGER_H_
#define CHROME_BROWSER_PRINTING_PRINT_JOB_MANAGER_H_
#include <memory>
#include <set>
#include <vector>
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
namespace printing {
class JobEventDetails;
class PrintJob;
class PrinterQuery;
class PrintQueriesQueue : public base::RefCountedThreadSafe<PrintQueriesQueue> {
public:
PrintQueriesQueue();
// Queues a semi-initialized worker thread. Can be called from any thread.
// Current use case is queuing from the I/O thread.
// TODO(maruel): Have them vanish after a timeout (~5 minutes?)
void QueuePrinterQuery(PrinterQuery* job);
// Pops a queued PrintJobWorkerOwner object that was previously queued or
// create new one. Can be called from any thread.
scoped_refptr<PrinterQuery> PopPrinterQuery(int document_cookie);
// Creates new query.
scoped_refptr<PrinterQuery> CreatePrinterQuery(int render_process_id,
int render_frame_id);
void Shutdown();
private:
friend class base::RefCountedThreadSafe<PrintQueriesQueue>;
typedef std::vector<scoped_refptr<PrinterQuery>> PrinterQueries;
virtual ~PrintQueriesQueue();
// Used to serialize access to queued_workers_.
base::Lock lock_;
PrinterQueries queued_queries_;
DISALLOW_COPY_AND_ASSIGN(PrintQueriesQueue);
};
class PrintJobManager : public content::NotificationObserver {
public:
PrintJobManager();
~PrintJobManager() override;
// On browser quit, we should wait to have the print job finished.
void Shutdown();
// content::NotificationObserver
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Returns queries queue. Never returns NULL. Must be called on Browser UI
// Thread. Reference could be stored and used from any thread.
scoped_refptr<PrintQueriesQueue> queue();
private:
typedef std::set<scoped_refptr<PrintJob>> PrintJobs;
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
void OnPrintJobEvent(PrintJob* print_job,
const JobEventDetails& event_details);
// Stops all printing jobs. If wait_for_finish is true, tries to give jobs
// a chance to complete before stopping them.
void StopJobs(bool wait_for_finish);
content::NotificationRegistrar registrar_;
// Current print jobs that are active.
PrintJobs current_jobs_;
scoped_refptr<PrintQueriesQueue> queue_;
bool is_shutdown_;
DISALLOW_COPY_AND_ASSIGN(PrintJobManager);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_MANAGER_H_

View file

@ -1,558 +0,0 @@
// Copyright (c) 2012 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/print_job_worker.h"
#include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "printing/print_job_constants.h"
#include "printing/printed_document.h"
#include "printing/printing_utils.h"
#include "ui/base/l10n/l10n_util.h"
#include <stddef.h>
#include <algorithm>
#include <cmath>
#include <string>
#include <utility>
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "printing/page_size_margins.h"
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
#include "printing/units.h"
#if defined(OS_WIN)
#include "printing/printed_page_win.h"
#endif
using content::BrowserThread;
namespace printing {
namespace {
// Helper function to ensure |owner| is valid until at least |callback| returns.
void HoldRefCallback(const scoped_refptr<PrintJobWorkerOwner>& owner,
base::OnceClosure callback) {
std::move(callback).Run();
}
void SetCustomMarginsToJobSettings(const PageSizeMargins& page_size_margins,
base::DictionaryValue* settings) {
std::unique_ptr<base::DictionaryValue> custom_margins(
new base::DictionaryValue());
custom_margins->SetDouble(kSettingMarginTop, page_size_margins.margin_top);
custom_margins->SetDouble(kSettingMarginBottom,
page_size_margins.margin_bottom);
custom_margins->SetDouble(kSettingMarginLeft, page_size_margins.margin_left);
custom_margins->SetDouble(kSettingMarginRight,
page_size_margins.margin_right);
settings->Set(kSettingMarginsCustom, std::move(custom_margins));
}
void PrintSettingsToJobSettings(const PrintSettings& settings,
base::DictionaryValue* job_settings) {
// header footer
job_settings->SetBoolean(kSettingHeaderFooterEnabled,
settings.display_header_footer());
job_settings->SetString(kSettingHeaderFooterTitle, settings.title());
job_settings->SetString(kSettingHeaderFooterURL, settings.url());
// bg
job_settings->SetBoolean(kSettingShouldPrintBackgrounds,
settings.should_print_backgrounds());
job_settings->SetBoolean(kSettingShouldPrintSelectionOnly,
settings.selection_only());
// margin
auto margin_type = settings.margin_type();
job_settings->SetInteger(kSettingMarginsType, settings.margin_type());
if (margin_type == CUSTOM_MARGINS) {
const auto& margins_in_points =
settings.requested_custom_margins_in_points();
PageSizeMargins page_size_margins;
page_size_margins.margin_top = margins_in_points.top;
page_size_margins.margin_bottom = margins_in_points.bottom;
page_size_margins.margin_left = margins_in_points.left;
page_size_margins.margin_right = margins_in_points.right;
SetCustomMarginsToJobSettings(page_size_margins, job_settings);
}
job_settings->SetInteger(kSettingPreviewPageCount, 1);
// range
if (!settings.ranges().empty()) {
auto page_range_array = std::make_unique<base::ListValue>();
job_settings->Set(kSettingPageRange, std::move(page_range_array));
for (size_t i = 0; i < settings.ranges().size(); ++i) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1);
dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1);
page_range_array->Append(std::move(dict));
}
}
job_settings->SetBoolean(kSettingCollate, settings.collate());
job_settings->SetInteger(kSettingCopies, 1);
job_settings->SetInteger(kSettingColor, settings.color());
job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode());
job_settings->SetBoolean(kSettingLandscape, settings.landscape());
job_settings->SetString(kSettingDeviceName, settings.device_name());
job_settings->SetInteger(kSettingScaleFactor, 100);
job_settings->SetBoolean("rasterizePDF", false);
job_settings->SetInteger("dpi", settings.dpi());
job_settings->SetInteger("dpiHorizontal", 72);
job_settings->SetInteger("dpiVertical", 72);
job_settings->SetBoolean(kSettingPrintToPDF, false);
job_settings->SetBoolean(kSettingCloudPrintDialog, false);
job_settings->SetBoolean(kSettingPrintWithPrivet, false);
job_settings->SetBoolean(kSettingPrintWithExtension, false);
job_settings->SetBoolean(kSettingShowSystemDialog, false);
job_settings->SetInteger(kSettingPreviewPageCount, 1);
}
class PrintingContextDelegate : public PrintingContext::Delegate {
public:
PrintingContextDelegate(int render_process_id, int render_frame_id);
~PrintingContextDelegate() override;
gfx::NativeView GetParentView() override;
std::string GetAppLocale() override;
// Not exposed to PrintingContext::Delegate because of dependency issues.
content::WebContents* GetWebContents();
private:
const int render_process_id_;
const int render_frame_id_;
};
PrintingContextDelegate::PrintingContextDelegate(int render_process_id,
int render_frame_id)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id) {}
PrintingContextDelegate::~PrintingContextDelegate() {}
gfx::NativeView PrintingContextDelegate::GetParentView() {
content::WebContents* wc = GetWebContents();
return wc ? wc->GetNativeView() : nullptr;
}
content::WebContents* PrintingContextDelegate::GetWebContents() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* rfh =
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
return rfh ? content::WebContents::FromRenderFrameHost(rfh) : nullptr;
}
std::string PrintingContextDelegate::GetAppLocale() {
return g_browser_process->GetApplicationLocale();
}
void NotificationCallback(PrintJobWorkerOwner* print_job,
JobEventDetails::Type detail_type,
int job_id,
PrintedDocument* document) {
JobEventDetails* details = new JobEventDetails(detail_type, job_id, document);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT,
// We know that is is a PrintJob object in this circumstance.
content::Source<PrintJob>(static_cast<PrintJob*>(print_job)),
content::Details<JobEventDetails>(details));
}
void PostOnOwnerThread(const scoped_refptr<PrintJobWorkerOwner>& owner,
PrintingContext::PrintSettingsCallback callback,
PrintingContext::Result result) {
owner->PostTask(FROM_HERE,
base::BindOnce(&HoldRefCallback, owner,
base::BindOnce(std::move(callback), result)));
}
#if defined(OS_WIN)
void PageNotificationCallback(PrintJobWorkerOwner* print_job,
JobEventDetails::Type detail_type,
int job_id,
PrintedDocument* document,
PrintedPage* page) {
JobEventDetails* details =
new JobEventDetails(detail_type, job_id, document, page);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_EVENT,
// We know that is is a PrintJob object in this circumstance.
content::Source<PrintJob>(static_cast<PrintJob*>(print_job)),
content::Details<JobEventDetails>(details));
}
#endif
} // namespace
PrintJobWorker::PrintJobWorker(int render_process_id,
int render_frame_id,
PrintJobWorkerOwner* owner)
: owner_(owner), thread_("Printing_Worker"), weak_factory_(this) {
// The object is created in the IO thread.
DCHECK(owner_->RunsTasksInCurrentSequence());
printing_context_delegate_ = std::make_unique<PrintingContextDelegate>(
render_process_id, render_frame_id);
printing_context_ = PrintingContext::Create(printing_context_delegate_.get());
}
PrintJobWorker::~PrintJobWorker() {
// The object is normally deleted in the UI thread, but when the user
// cancels printing or in the case of print preview, the worker is destroyed
// on the I/O thread.
DCHECK(owner_->RunsTasksInCurrentSequence());
Stop();
}
void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) {
DCHECK(page_number_ == PageNumber::npos());
owner_ = new_owner;
}
void PrintJobWorker::GetSettings(bool ask_user_for_settings,
int document_page_count,
bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable,
const base::string16& device_name) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(page_number_, PageNumber::npos());
// Recursive task processing is needed for the dialog in case it needs to be
// destroyed by a task.
// TODO(thestig): This code is wrong. SetNestableTasksAllowed(true) is needed
// on the thread where the PrintDlgEx is called, and definitely both calls
// should happen on the same thread. See http://crbug.com/73466
// MessageLoop::current()->SetNestableTasksAllowed(true);
printing_context_->set_margin_type(margin_type);
printing_context_->set_is_modifiable(is_modifiable);
// When we delegate to a destination, we don't ask the user for settings.
// TODO(mad): Ask the destination for settings.
if (ask_user_for_settings) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&HoldRefCallback, WrapRefCounted(owner_),
base::BindOnce(&PrintJobWorker::GetSettingsWithUI,
base::Unretained(this), document_page_count,
has_selection, is_scripted)));
} else if (!device_name.empty()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&HoldRefCallback, WrapRefCounted(owner_),
base::BindOnce(&PrintJobWorker::InitWithDeviceName,
base::Unretained(this), device_name)));
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&HoldRefCallback, WrapRefCounted(owner_),
base::BindOnce(&PrintJobWorker::UseDefaultSettings,
base::Unretained(this))));
}
}
void PrintJobWorker::SetSettings(
std::unique_ptr<base::DictionaryValue> new_settings) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&HoldRefCallback, WrapRefCounted(owner_),
base::BindOnce(&PrintJobWorker::UpdatePrintSettings,
base::Unretained(this), base::Passed(&new_settings))));
}
void PrintJobWorker::UpdatePrintSettings(
std::unique_ptr<base::DictionaryValue> new_settings) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PrintingContext::Result result =
printing_context_->UpdatePrintSettings(*new_settings);
GetSettingsDone(result);
}
void PrintJobWorker::GetSettingsDone(PrintingContext::Result result) {
// Most PrintingContext functions may start a message loop and process
// message recursively, so disable recursive task processing.
// TODO(thestig): See above comment. SetNestableTasksAllowed(false) needs to
// be called on the same thread as the previous call. See
// http://crbug.com/73466
// MessageLoop::current()->SetNestableTasksAllowed(false);
// We can't use OnFailure() here since owner_ may not support notifications.
// PrintJob will create the new PrintedDocument.
owner_->PostTask(
FROM_HERE,
base::Bind(&PrintJobWorkerOwner::GetSettingsDone, WrapRefCounted(owner_),
printing_context_->settings(), result));
}
void PrintJobWorker::GetSettingsWithUI(int document_page_count,
bool has_selection,
bool is_scripted) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// weak_factory_ creates pointers valid only on owner_ thread.
printing_context_->AskUserForSettings(
document_page_count, has_selection, is_scripted,
base::BindOnce(&PostOnOwnerThread, WrapRefCounted(owner_),
base::BindOnce(&PrintJobWorker::GetSettingsDone,
weak_factory_.GetWeakPtr())));
}
void PrintJobWorker::UseDefaultSettings() {
PrintingContext::Result result = printing_context_->UseDefaultSettings();
GetSettingsDone(result);
}
void PrintJobWorker::InitWithDeviceName(const base::string16& device_name) {
const auto& settings = printing_context_->settings();
std::unique_ptr<base::DictionaryValue> dic(new base::DictionaryValue);
PrintSettingsToJobSettings(settings, dic.get());
dic->SetString(kSettingDeviceName, device_name);
UpdatePrintSettings(std::move(dic));
}
void PrintJobWorker::StartPrinting(PrintedDocument* new_document) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(page_number_, PageNumber::npos());
DCHECK_EQ(document_.get(), new_document);
DCHECK(document_.get());
if (!document_.get() || page_number_ != PageNumber::npos() ||
document_.get() != new_document) {
return;
}
base::string16 document_name =
printing::SimplifyDocumentTitle(document_->name());
PrintingContext::Result result =
printing_context_->NewDocument(document_name);
if (result != PrintingContext::OK) {
OnFailure();
return;
}
// Try to print already cached data. It may already have been generated for
// the print preview.
OnNewPage();
// Don't touch this anymore since the instance could be destroyed. It happens
// if all the pages are printed a one sweep and the client doesn't have a
// handle to us anymore. There's a timing issue involved between the worker
// thread and the UI thread. Take no chance.
}
void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(page_number_, PageNumber::npos());
if (page_number_ != PageNumber::npos())
return;
document_ = new_document;
}
void PrintJobWorker::PostWaitForPage() {
// We need to wait for the page to be available.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PrintJobWorker::OnNewPage, weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(500));
}
#if defined(OS_WIN)
void PrintJobWorker::OnNewPage() {
if (!document_.get()) // Spurious message.
return;
// message_loop() could return NULL when the print job is cancelled.
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (page_number_ == PageNumber::npos()) {
// Find first page to print.
int page_count = document_->page_count();
if (!page_count) {
// We still don't know how many pages the document contains. We can't
// start to print the document yet since the header/footer may refer to
// the document's page count.
return;
}
// We have enough information to initialize page_number_.
page_number_.Init(document_->settings(), page_count);
}
DCHECK_NE(page_number_, PageNumber::npos());
while (true) {
// Is the page available?
scoped_refptr<PrintedPage> page = document_->GetPage(page_number_.ToInt());
if (!page.get()) {
PostWaitForPage();
break;
}
// The page is there, print it.
SpoolPage(page.get());
++page_number_;
if (page_number_ == PageNumber::npos()) {
OnDocumentDone();
// Don't touch this anymore since the instance could be destroyed.
break;
}
}
}
#else
void PrintJobWorker::OnNewPage() {
if (!document_.get()) // Spurious message.
return;
// message_loop() could return NULL when the print job is cancelled.
DCHECK(task_runner_->RunsTasksInCurrentSequence());
const MetafilePlayer* metafile = document_->GetMetafile();
if (!metafile) {
PostWaitForPage();
return;
}
SpoolJob();
// Don't touch this anymore since the instance could be destroyed.
OnDocumentDone();
}
#endif // defined(OS_WIN)
void PrintJobWorker::Cancel() {
// This is the only function that can be called from any thread.
printing_context_->Cancel();
// Cannot touch any member variable since we don't know in which thread
// context we run.
}
bool PrintJobWorker::IsRunning() const {
return thread_.IsRunning();
}
bool PrintJobWorker::PostTask(const base::Location& from_here,
const base::Closure& task) {
if (task_runner_.get())
return task_runner_->PostTask(from_here, task);
return false;
}
void PrintJobWorker::StopSoon() {
thread_.StopSoon();
}
void PrintJobWorker::Stop() {
thread_.Stop();
}
bool PrintJobWorker::Start() {
bool result = thread_.Start();
task_runner_ = thread_.task_runner();
return result;
}
void PrintJobWorker::OnDocumentDone() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(page_number_, PageNumber::npos());
DCHECK(document_.get());
int job_id = printing_context_->job_id();
if (printing_context_->DocumentDone() != PrintingContext::OK) {
OnFailure();
return;
}
owner_->PostTask(FROM_HERE,
base::Bind(&NotificationCallback, base::RetainedRef(owner_),
JobEventDetails::DOC_DONE, job_id,
base::RetainedRef(document_)));
// Makes sure the variables are reinitialized.
document_ = NULL;
}
#if defined(OS_WIN)
void PrintJobWorker::SpoolPage(PrintedPage* page) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_NE(page_number_, PageNumber::npos());
// Preprocess.
if (printing_context_->NewPage() != PrintingContext::OK) {
OnFailure();
return;
}
// Actual printing.
document_->RenderPrintedPage(*page, printing_context_->context());
// Postprocess.
if (printing_context_->PageDone() != PrintingContext::OK) {
OnFailure();
return;
}
// Signal everyone that the page is printed.
owner_->PostTask(FROM_HERE,
base::BindRepeating(
&PageNotificationCallback, base::RetainedRef(owner_),
JobEventDetails::PAGE_DONE, printing_context_->job_id(),
base::RetainedRef(document_), base::RetainedRef(page)));
}
#else
void PrintJobWorker::SpoolJob() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!document_->RenderPrintedDocument(printing_context_.get()))
OnFailure();
}
#endif
void PrintJobWorker::OnFailure() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
// We may loose our last reference by broadcasting the FAILED event.
scoped_refptr<PrintJobWorkerOwner> handle(owner_);
owner_->PostTask(
FROM_HERE, base::BindRepeating(
&NotificationCallback, base::RetainedRef(owner_),
JobEventDetails::FAILED, 0, base::RetainedRef(document_)));
Cancel();
// Makes sure the variables are reinitialized.
document_ = NULL;
page_number_ = PageNumber::npos();
}
} // namespace printing

View file

@ -1,174 +0,0 @@
// Copyright (c) 2012 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_PRINT_JOB_WORKER_H_
#define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H_
#include <memory>
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "chrome/browser/printing/printer_query.h"
#include "content/public/browser/browser_thread.h"
#include "printing/page_number.h"
#include "printing/print_job_constants.h"
#include "printing/printing_context.h"
namespace base {
class DictionaryValue;
}
namespace printing {
class PrintJob;
class PrintJobWorkerOwner;
class PrintedDocument;
class PrintedPage;
// Worker thread code. It manages the PrintingContext, which can be blocking
// and/or run a message loop. This is the object that generates most
// NOTIFY_PRINT_JOB_EVENT notifications, but they are generated through a
// NotificationTask task to be executed from the right thread, the UI thread.
// PrintJob always outlives its worker instance.
class PrintJobWorker {
public:
PrintJobWorker(int render_process_id,
int render_frame_id,
PrintJobWorkerOwner* owner);
virtual ~PrintJobWorker();
void SetNewOwner(PrintJobWorkerOwner* new_owner);
// Initializes the print settings. If |ask_user_for_settings| is true, a
// Print... dialog box will be shown to ask the user their preference.
// |is_scripted| should be true for calls coming straight from window.print().
// |is_modifiable| implies HTML and not other formats like PDF.
void GetSettings(bool ask_user_for_settings,
int document_page_count,
bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable,
const base::string16& device_name);
// Set the new print settings.
void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings);
// Starts the printing loop. Every pages are printed as soon as the data is
// available. Makes sure the new_document is the right one.
void StartPrinting(PrintedDocument* new_document);
// Updates the printed document.
void OnDocumentChanged(PrintedDocument* new_document);
// Dequeues waiting pages. Called when PrintJob receives a
// NOTIFY_PRINTED_DOCUMENT_UPDATED notification. It's time to look again if
// the next page can be printed.
void OnNewPage();
// This is the only function that can be called in a thread.
void Cancel();
// Returns true if the thread has been started, and not yet stopped.
bool IsRunning() const;
// Posts the given task to be run.
bool PostTask(const base::Location& from_here, const base::Closure& task);
// Signals the thread to exit in the near future.
void StopSoon();
// Signals the thread to exit and returns once the thread has exited.
void Stop();
// Starts the thread.
bool Start();
protected:
// Retrieves the context for testing only.
PrintingContext* printing_context() { return printing_context_.get(); }
private:
// The shared NotificationService service can only be accessed from the UI
// thread, so this class encloses the necessary information to send the
// notification from the right thread. Most NOTIFY_PRINT_JOB_EVENT
// notifications are sent this way, except USER_INIT_DONE, USER_INIT_CANCELED
// and DEFAULT_INIT_DONE. These three are sent through PrintJob::InitDone().
class NotificationTask;
// Posts a task to call OnNewPage(). Used to wait for pages/document to be
// available.
void PostWaitForPage();
#if defined(OS_WIN)
// Renders a page in the printer.
void SpoolPage(PrintedPage* page);
#else
// Renders the document to the printer.
void SpoolJob();
#endif
// Closes the job since spooling is done.
void OnDocumentDone();
// Discards the current document, the current page and cancels the printing
// context.
void OnFailure();
// Asks the user for print settings. Must be called on the UI thread.
// Required on Mac and Linux. Windows can display UI from non-main threads,
// but sticks with this for consistency.
void GetSettingsWithUI(int document_page_count,
bool has_selection,
bool is_scripted);
// Called on the UI thread to update the print settings.
void UpdatePrintSettings(std::unique_ptr<base::DictionaryValue> new_settings);
// Reports settings back to owner_.
void GetSettingsDone(PrintingContext::Result result);
// Use the default settings. When using GTK+ or Mac, this can still end up
// displaying a dialog. So this needs to happen from the UI thread on these
// systems.
void UseDefaultSettings();
// set the printer name
void InitWithDeviceName(const base::string16& device_name);
// Printing context delegate.
std::unique_ptr<PrintingContext::Delegate> printing_context_delegate_;
// Information about the printer setting.
std::unique_ptr<PrintingContext> printing_context_;
// The printed document. Only has read-only access.
scoped_refptr<PrintedDocument> document_;
// The print job owning this worker thread. It is guaranteed to outlive this
// object.
PrintJobWorkerOwner* owner_;
// Current page number to print.
PageNumber page_number_;
// Thread to run worker tasks.
base::Thread thread_;
// Tread-safe pointer to task runner of the |thread_|.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
// Used to generate a WeakPtr for callbacks.
base::WeakPtrFactory<PrintJobWorker> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PrintJobWorker);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H_

View file

@ -1,27 +0,0 @@
// Copyright 2014 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/print_job_worker_owner.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
namespace printing {
PrintJobWorkerOwner::PrintJobWorkerOwner()
: task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
PrintJobWorkerOwner::~PrintJobWorkerOwner() {}
bool PrintJobWorkerOwner::RunsTasksInCurrentSequence() const {
return task_runner_->RunsTasksInCurrentSequence();
}
bool PrintJobWorkerOwner::PostTask(const base::Location& from_here,
base::OnceClosure task) {
return task_runner_->PostTask(from_here, std::move(task));
}
} // namespace printing

View file

@ -1,65 +0,0 @@
// Copyright (c) 2011 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_PRINT_JOB_WORKER_OWNER_H__
#define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__
#include <memory>
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "printing/printing_context.h"
namespace base {
class MessageLoop;
class SequencedTaskRunner;
} // namespace base
namespace printing {
class PrintJobWorker;
class PrintSettings;
class PrintJobWorkerOwner
: public base::RefCountedThreadSafe<PrintJobWorkerOwner> {
public:
PrintJobWorkerOwner();
// Finishes the initialization began by PrintJobWorker::GetSettings().
// Creates a new PrintedDocument if necessary. Solely meant to be called by
// PrintJobWorker.
virtual void GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) = 0;
// Detach the PrintJobWorker associated to this object.
virtual std::unique_ptr<PrintJobWorker> DetachWorker(
PrintJobWorkerOwner* new_owner) = 0;
// Access the current settings.
virtual const PrintSettings& settings() const = 0;
// Cookie uniquely identifying the PrintedDocument and/or loaded settings.
virtual int cookie() const = 0;
// Returns true if the current thread is a thread on which a task
// may be run, and false if no task will be run on the current
// thread.
bool RunsTasksInCurrentSequence() const;
// Posts the given task to be run.
bool PostTask(const base::Location& from_here, base::OnceClosure task);
protected:
friend class base::RefCountedThreadSafe<PrintJobWorkerOwner>;
virtual ~PrintJobWorkerOwner();
// Task runner reference. Used to send notifications in the right
// thread.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_OWNER_H__

View file

@ -1,142 +0,0 @@
// Copyright (c) 2012 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/print_preview_message_handler.h"
#include "base/bind.h"
#include "base/memory/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/common/print_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "printing/page_size_margins.h"
#include "printing/pdf_metafile_skia.h"
#include "printing/print_job_constants.h"
#include "atom/common/node_includes.h"
using content::BrowserThread;
using content::WebContents;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintPreviewMessageHandler);
namespace {
void StopWorker(int document_cookie) {
if (document_cookie <= 0)
return;
scoped_refptr<printing::PrintQueriesQueue> queue =
g_browser_process->print_job_manager()->queue();
scoped_refptr<printing::PrinterQuery> printer_query =
queue->PopPrinterQuery(document_cookie);
if (printer_query.get()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&printing::PrinterQuery::StopWorker, printer_query));
}
}
char* CopyPDFDataOnIOThread(
const PrintHostMsg_DidPreviewDocument_Params& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<base::SharedMemory> shared_buf(
new base::SharedMemory(params.metafile_data_handle, true));
if (!shared_buf->Map(params.data_size))
return nullptr;
char* pdf_data = new char[params.data_size];
memcpy(pdf_data, shared_buf->memory(), params.data_size);
return pdf_data;
}
void FreeNodeBufferData(char* data, void* hint) {
delete[] data;
}
} // namespace
namespace printing {
PrintPreviewMessageHandler::PrintPreviewMessageHandler(
WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
DCHECK(web_contents);
}
PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {}
void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
const PrintHostMsg_DidPreviewDocument_Params& params) {
// Always try to stop the worker.
StopWorker(params.document_cookie);
if (params.expected_pages_count <= 0) {
NOTREACHED();
return;
}
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO, FROM_HERE, base::Bind(&CopyPDFDataOnIOThread, params),
base::Bind(&PrintPreviewMessageHandler::RunPrintToPDFCallback,
base::Unretained(this), params.preview_request_id,
params.data_size));
}
void PrintPreviewMessageHandler::OnPrintPreviewFailed(int document_cookie,
int request_id) {
StopWorker(document_cookie);
RunPrintToPDFCallback(request_id, 0, nullptr);
}
bool PrintPreviewMessageHandler::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
OnMetafileReadyForPrinting)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed, OnPrintPreviewFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PrintPreviewMessageHandler::PrintToPDF(
const base::DictionaryValue& options,
const atom::api::WebContents::PrintToPDFCallback& callback) {
int request_id;
options.GetInteger(printing::kPreviewRequestID, &request_id);
print_to_pdf_callback_map_[request_id] = callback;
content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options));
}
void PrintPreviewMessageHandler::RunPrintToPDFCallback(int request_id,
uint32_t data_size,
char* data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (data) {
v8::Local<v8::Value> buffer =
node::Buffer::New(isolate, data, static_cast<size_t>(data_size),
&FreeNodeBufferData, nullptr)
.ToLocalChecked();
print_to_pdf_callback_map_[request_id].Run(v8::Null(isolate), buffer);
} else {
v8::Local<v8::String> error_message =
v8::String::NewFromUtf8(isolate, "Failed to generate PDF");
print_to_pdf_callback_map_[request_id].Run(
v8::Exception::Error(error_message), v8::Null(isolate));
}
print_to_pdf_callback_map_.erase(request_id);
}
} // namespace printing

View file

@ -1,60 +0,0 @@
// Copyright (c) 2012 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_PRINT_PREVIEW_MESSAGE_HANDLER_H_
#define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
#include <map>
#include "atom/browser/api/atom_api_web_contents.h"
#include "base/compiler_specific.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
struct PrintHostMsg_DidPreviewDocument_Params;
namespace content {
class WebContents;
}
namespace printing {
struct PageSizeMargins;
// Manages the print preview handling for a WebContents.
class PrintPreviewMessageHandler
: public content::WebContentsObserver,
public content::WebContentsUserData<PrintPreviewMessageHandler> {
public:
~PrintPreviewMessageHandler() override;
// content::WebContentsObserver implementation.
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* render_frame_host) override;
void PrintToPDF(const base::DictionaryValue& options,
const atom::api::WebContents::PrintToPDFCallback& callback);
private:
typedef std::map<int, atom::api::WebContents::PrintToPDFCallback>
PrintToPDFCallbackMap;
explicit PrintPreviewMessageHandler(content::WebContents* web_contents);
friend class content::WebContentsUserData<PrintPreviewMessageHandler>;
// Message handlers.
void OnMetafileReadyForPrinting(
const PrintHostMsg_DidPreviewDocument_Params& params);
void OnPrintPreviewFailed(int document_cookie, int request_id);
void RunPrintToPDFCallback(int request_id, uint32_t data_size, char* data);
PrintToPDFCallbackMap print_to_pdf_callback_map_;
DISALLOW_COPY_AND_ASSIGN(PrintPreviewMessageHandler);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_

View file

@ -1,508 +0,0 @@
// Copyright 2013 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/print_view_manager_base.h"
#include <memory>
#include "base/bind.h"
#include "base/memory/ref_counted_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/timer/timer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/print_messages.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#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/web_contents.h"
#include "printing/pdf_metafile_skia.h"
#include "printing/printed_document.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(ENABLE_FULL_PRINTING)
#include "chrome/browser/printing/print_error_dialog.h"
#endif
using base::TimeDelta;
using content::BrowserThread;
namespace printing {
namespace {} // namespace
PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
number_pages_(0),
printing_succeeded_(false),
inside_inner_message_loop_(false),
cookie_(0),
queue_(g_browser_process->print_job_manager()->queue()) {
DCHECK(queue_.get());
expecting_first_page_ = true;
printing_enabled_ = true;
}
PrintViewManagerBase::~PrintViewManagerBase() {
ReleasePrinterQuery();
DisconnectFromCurrentPrintJob();
}
#if !defined(DISABLE_BASIC_PRINTING)
bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
bool silent,
bool print_background,
const base::string16& device_name) {
int32_t id = rfh->GetRoutingID();
return PrintNowInternal(rfh, std::make_unique<PrintMsg_PrintPages>(
id, silent, print_background, device_name));
}
#endif // !DISABLE_BASIC_PRINTING
void PrintViewManagerBase::NavigationStopped() {
// Cancel the current job, wait for the worker to finish.
TerminatePrintJob(true);
}
void PrintViewManagerBase::RenderProcessGone(base::TerminationStatus status) {
ReleasePrinterQuery();
if (!print_job_.get())
return;
scoped_refptr<PrintedDocument> document(print_job_->document());
if (document.get()) {
// If IsComplete() returns false, the document isn't completely rendered.
// Since our renderer is gone, there's nothing to do, cancel it. Otherwise,
// the print job may finish without problem.
TerminatePrintJob(!document->IsComplete());
}
}
base::string16 PrintViewManagerBase::RenderSourceName() {
base::string16 name(web_contents()->GetTitle());
return name;
}
void PrintViewManagerBase::OnDidGetPrintedPagesCount(int cookie,
int number_pages) {
DCHECK_GT(cookie, 0);
DCHECK_GT(number_pages, 0);
number_pages_ = number_pages;
OpportunisticallyCreatePrintJob(cookie);
}
void PrintViewManagerBase::OnDidGetDocumentCookie(int cookie) {
cookie_ = cookie;
}
void PrintViewManagerBase::OnDidPrintPage(
const PrintHostMsg_DidPrintPage_Params& params) {
// TODO(rbpotter): Remove this check once there are no more spurious
// DidPrintPage messages.
#if !defined(OS_WIN)
if (!expecting_first_page_)
return;
#endif
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;
}
const bool metafile_must_be_valid = expecting_first_page_;
expecting_first_page_ = false;
base::SharedMemory shared_buf(params.metafile_data_handle, true);
if (metafile_must_be_valid) {
if (!shared_buf.Map(params.data_size)) {
NOTREACHED() << "couldn't map";
web_contents()->Stop();
return;
}
}
auto metafile = std::make_unique<PdfMetafileSkia>();
if (metafile_must_be_valid) {
if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) {
NOTREACHED() << "Invalid metafile header";
web_contents()->Stop();
return;
}
}
#if !defined(OS_WIN)
// Update the rendered document. It will send notifications to the listener.
document->SetDocument(std::move(metafile), params.page_size,
params.content_area);
ShouldQuitFromInnerMessageLoop();
#else
print_job_->AppendPrintedPage(params.page_number);
if (metafile_must_be_valid) {
bool print_text_with_gdi = document->settings().print_text_with_gdi() &&
!document->settings().printer_is_xps();
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"));
print_job_->StartPdfToEmfConversion(
bytes, params.page_size, params.content_area, print_text_with_gdi);
}
#endif // !OS_WIN
}
void PrintViewManagerBase::OnPrintingFailed(int cookie) {
if (cookie != cookie_) {
NOTREACHED();
return;
}
ReleasePrinterQuery();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
content::Source<content::WebContents>(web_contents()),
content::NotificationService::NoDetails());
}
void PrintViewManagerBase::OnShowInvalidPrinterSettingsError() {
LOG(ERROR) << "Invalid printer settings";
}
bool PrintViewManagerBase::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount,
OnDidGetPrintedPagesCount)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie,
OnDidGetDocumentCookie)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
OnShowInvalidPrinterSettingsError);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PrintViewManagerBase::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
break;
}
default: {
NOTREACHED();
break;
}
}
}
void PrintViewManagerBase::OnNotifyPrintJobEvent(
const JobEventDetails& event_details) {
switch (event_details.type()) {
case JobEventDetails::FAILED: {
TerminatePrintJob(true);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
content::Source<content::WebContents>(web_contents()),
content::NotificationService::NoDetails());
break;
}
case JobEventDetails::USER_INIT_DONE:
case JobEventDetails::DEFAULT_INIT_DONE:
case JobEventDetails::USER_INIT_CANCELED: {
NOTREACHED();
break;
}
case JobEventDetails::ALL_PAGES_REQUESTED: {
ShouldQuitFromInnerMessageLoop();
break;
}
case JobEventDetails::NEW_DOC:
case JobEventDetails::NEW_PAGE:
case JobEventDetails::PAGE_DONE:
case JobEventDetails::DOC_DONE: {
// Don't care about the actual printing process.
break;
}
case JobEventDetails::JOB_DONE: {
// Printing is done, we don't need it anymore.
// print_job_->is_job_pending() may still be true, depending on the order
// of object registration.
printing_succeeded_ = true;
ReleasePrintJob();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PRINT_JOB_RELEASED,
content::Source<content::WebContents>(web_contents()),
content::NotificationService::NoDetails());
break;
}
default: {
NOTREACHED();
break;
}
}
}
bool PrintViewManagerBase::RenderAllMissingPagesNow() {
if (!print_job_.get() || !print_job_->is_job_pending())
return false;
// We can't print if there is no renderer.
if (!web_contents() || !web_contents()->GetRenderViewHost() ||
!web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
return false;
}
// Is the document already complete?
if (print_job_->document() && print_job_->document()->IsComplete()) {
printing_succeeded_ = true;
return true;
}
// WebContents is either dying or a second consecutive request to print
// happened before the first had time to finish. We need to render all the
// pages in an hurry if a print_job_ is still pending. No need to wait for it
// to actually spool the pages, only to have the renderer generate them. Run
// a message loop until we get our signal that the print job is satisfied.
// PrintJob will send a ALL_PAGES_REQUESTED after having received all the
// pages it needs. MessageLoop::current()->Quit() will be called as soon as
// print_job_->document()->IsComplete() is true on either ALL_PAGES_REQUESTED
// or in DidPrintPage(). The check is done in
// ShouldQuitFromInnerMessageLoop().
// BLOCKS until all the pages are received. (Need to enable recursive task)
if (!RunInnerMessageLoop()) {
// This function is always called from DisconnectFromCurrentPrintJob() so we
// know that the job will be stopped/canceled in any case.
return false;
}
return true;
}
void PrintViewManagerBase::ShouldQuitFromInnerMessageLoop() {
// Look at the reason.
DCHECK(print_job_->document());
if (print_job_->document() && print_job_->document()->IsComplete() &&
inside_inner_message_loop_) {
// We are in a message loop created by RenderAllMissingPagesNow. Quit from
// it.
base::RunLoop::QuitCurrentWhenIdleDeprecated();
inside_inner_message_loop_ = false;
}
}
bool PrintViewManagerBase::CreateNewPrintJob(PrintJobWorkerOwner* job) {
DCHECK(!inside_inner_message_loop_);
// Disconnect the current print_job_.
DisconnectFromCurrentPrintJob();
// We can't print if there is no renderer.
if (!web_contents()->GetRenderViewHost() ||
!web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
return false;
}
// Ask the renderer to generate the print preview, create the print preview
// view and switch to it, initialize the printer and show the print dialog.
DCHECK(!print_job_.get());
DCHECK(job);
if (!job)
return false;
print_job_ = new PrintJob();
print_job_->Initialize(job, RenderSourceName(), number_pages_);
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::Source<PrintJob>(print_job_.get()));
printing_succeeded_ = false;
return true;
}
void PrintViewManagerBase::DisconnectFromCurrentPrintJob() {
// Make sure all the necessary rendered page are done. Don't bother with the
// return value.
bool result = RenderAllMissingPagesNow();
// Verify that assertion.
if (print_job_.get() && print_job_->document() &&
!print_job_->document()->IsComplete()) {
DCHECK(!result);
// That failed.
TerminatePrintJob(true);
} else {
// DO NOT wait for the job to finish.
ReleasePrintJob();
}
expecting_first_page_ = true;
}
void PrintViewManagerBase::PrintingDone(bool success) {
auto* host = web_contents()->GetRenderViewHost();
if (print_job_.get()) {
if (host)
host->Send(new PrintMsg_PrintingDone(host->GetRoutingID(), success));
}
if (!callback.is_null()) {
callback.Run(success && print_job_);
}
}
void PrintViewManagerBase::TerminatePrintJob(bool cancel) {
if (!print_job_.get())
return;
if (cancel) {
// We don't need the metafile data anymore because the printing is canceled.
print_job_->Cancel();
inside_inner_message_loop_ = false;
} else {
DCHECK(!inside_inner_message_loop_);
DCHECK(!print_job_->document() || print_job_->document()->IsComplete());
// WebContents is either dying or navigating elsewhere. We need to render
// all the pages in an hurry if a print job is still pending. This does the
// trick since it runs a blocking message loop:
print_job_->Stop();
}
ReleasePrintJob();
}
void PrintViewManagerBase::ReleasePrintJob() {
if (!print_job_.get())
return;
PrintingDone(printing_succeeded_);
registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
content::Source<PrintJob>(print_job_.get()));
// Don't close the worker thread.
print_job_ = NULL;
}
bool PrintViewManagerBase::RunInnerMessageLoop() {
// This value may actually be too low:
//
// - If we're looping because of printer settings initialization, the premise
// here is that some poor users have their print server away on a VPN over a
// slow connection. In this situation, the simple fact of opening the printer
// can be dead slow. On the other side, we don't want to die infinitely for a
// real network error. Give the printer 60 seconds to comply.
//
// - If we're looping because of renderer page generation, the renderer could
// be CPU bound, the page overly complex/large or the system just
// memory-bound.
static const int kPrinterSettingsTimeout = 60000;
base::OneShotTimer quit_timer;
base::RunLoop run_loop;
quit_timer.Start(FROM_HERE,
TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
run_loop.QuitWhenIdleClosure());
inside_inner_message_loop_ = true;
// Need to enable recursive task.
{
base::MessageLoop::ScopedNestableTaskAllower allow;
base::RunLoop().Run();
}
bool success = true;
if (inside_inner_message_loop_) {
// Ok we timed out. That's sad.
inside_inner_message_loop_ = false;
success = false;
}
return success;
}
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
if (print_job_.get())
return true;
if (!cookie) {
// Out of sync. It may happens since we are completely asynchronous. Old
// spurious message can happen if one of the processes is overloaded.
return false;
}
// The job was initiated by a script. Time to get the corresponding worker
// thread.
scoped_refptr<PrinterQuery> queued_query = queue_->PopPrinterQuery(cookie);
if (!queued_query.get()) {
NOTREACHED();
return false;
}
if (!CreateNewPrintJob(queued_query.get())) {
// Don't kill anything.
return false;
}
// Settings are already loaded. Go ahead. This will set
// print_job_->is_job_pending() to true.
print_job_->StartPrinting();
return true;
}
bool PrintViewManagerBase::PrintNowInternal(
content::RenderFrameHost* rfh,
std::unique_ptr<IPC::Message> message) {
// Don't print / print preview interstitials or crashed tabs.
if (web_contents()->ShowingInterstitialPage() || web_contents()->IsCrashed())
return false;
return rfh->Send(message.release());
}
void PrintViewManagerBase::ReleasePrinterQuery() {
if (!cookie_)
return;
int cookie = cookie_;
cookie_ = 0;
printing::PrintJobManager* print_job_manager =
g_browser_process->print_job_manager();
// May be NULL in tests.
if (!print_job_manager)
return;
scoped_refptr<printing::PrinterQuery> printer_query;
printer_query = queue_->PopPrinterQuery(cookie);
if (!printer_query.get())
return;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PrinterQuery::StopWorker, printer_query.get()));
}
} // namespace printing

View file

@ -1,171 +0,0 @@
// Copyright 2013 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_PRINT_VIEW_MANAGER_BASE_H_
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_
#include <memory>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "components/prefs/pref_member.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
struct PrintHostMsg_DidPrintPage_Params;
namespace content {
class RenderViewHost;
}
namespace printing {
class JobEventDetails;
class MetafilePlayer;
class PrintJob;
class PrintJobWorkerOwner;
class PrintQueriesQueue;
// Base class for managing the print commands for a WebContents.
class PrintViewManagerBase : public content::NotificationObserver,
public content::WebContentsObserver {
public:
~PrintViewManagerBase() override;
#if !defined(DISABLE_BASIC_PRINTING)
// Prints the current document immediately. Since the rendering is
// asynchronous, the actual printing will not be completed on the return of
// this function. Returns false if printing is impossible at the moment.
virtual bool PrintNow(content::RenderFrameHost* rfh,
bool silent,
bool print_background,
const base::string16& device_name);
#endif // !DISABLE_BASIC_PRINTING
// PrintedPagesSource implementation.
base::string16 RenderSourceName();
void SetCallback(const base::Callback<void(bool)>& cb) { callback = cb; };
protected:
explicit PrintViewManagerBase(content::WebContents* web_contents);
// Helper method for Print*Now().
bool PrintNowInternal(content::RenderFrameHost* rfh,
std::unique_ptr<IPC::Message> message);
// Terminates or cancels the print job if one was pending.
void RenderProcessGone(base::TerminationStatus status) override;
// content::WebContentsObserver implementation.
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* render_frame_host) override;
// IPC Message handlers.
virtual void OnPrintingFailed(int cookie);
private:
// content::NotificationObserver implementation.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Cancels the print job.
void NavigationStopped() override;
// IPC Message handlers.
void OnDidGetPrintedPagesCount(int cookie, int number_pages);
void OnDidGetDocumentCookie(int cookie);
void OnDidPrintPage(const PrintHostMsg_DidPrintPage_Params& params);
void OnShowInvalidPrinterSettingsError();
// Processes a NOTIFY_PRINT_JOB_EVENT notification.
void OnNotifyPrintJobEvent(const JobEventDetails& event_details);
// Requests the RenderView to render all the missing pages for the print job.
// No-op if no print job is pending. Returns true if at least one page has
// been requested to the renderer.
bool RenderAllMissingPagesNow();
// Quits the current message loop if these conditions hold true: a document is
// loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This
// function is called in DidPrintPage() or on ALL_PAGES_REQUESTED
// notification. The inner message loop is created was created by
// RenderAllMissingPagesNow().
void ShouldQuitFromInnerMessageLoop();
// Creates a new empty print job. It has no settings loaded. If there is
// currently a print job, safely disconnect from it. Returns false if it is
// impossible to safely disconnect from the current print job or it is
// impossible to create a new print job.
bool CreateNewPrintJob(PrintJobWorkerOwner* job);
// Makes sure the current print_job_ has all its data before continuing, and
// disconnect from it.
void DisconnectFromCurrentPrintJob();
// Notify that the printing is done.
void PrintingDone(bool success);
// Terminates the print job. No-op if no print job has been created. If
// |cancel| is true, cancel it instead of waiting for the job to finish. Will
// call ReleasePrintJob().
void TerminatePrintJob(bool cancel);
// Releases print_job_. Correctly deregisters from notifications. No-op if
// no print job has been created.
void ReleasePrintJob();
// Runs an inner message loop. It will set inside_inner_message_loop_ to true
// while the blocking inner message loop is running. This is useful in cases
// where the RenderView is about to be destroyed while a printing job isn't
// finished.
bool RunInnerMessageLoop();
// In the case of Scripted Printing, where the renderer is controlling the
// control flow, print_job_ is initialized whenever possible. No-op is
// print_job_ is initialized.
bool OpportunisticallyCreatePrintJob(int cookie);
// Release the PrinterQuery associated with our |cookie_|.
void ReleasePrinterQuery();
content::NotificationRegistrar registrar_;
// Manages the low-level talk to the printer.
scoped_refptr<PrintJob> print_job_;
// Number of pages to print in the print job.
int number_pages_;
// Indication of success of the print job.
bool printing_succeeded_;
// Running an inner message loop inside RenderAllMissingPagesNow(). This means
// we are _blocking_ until all the necessary pages have been rendered or the
// print settings are being loaded.
bool inside_inner_message_loop_;
// Set to true when OnDidPrintPage() should be expecting the first page.
bool expecting_first_page_;
// The document cookie of the current PrinterQuery.
int cookie_;
// Whether printing is enabled.
bool printing_enabled_;
scoped_refptr<printing::PrintQueriesQueue> queue_;
base::Callback<void(bool)> callback;
DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBase);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_

View file

@ -1,46 +0,0 @@
// Copyright 2013 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/print_view_manager_basic.h"
#if defined(OS_ANDROID)
#include "base/file_descriptor_posix.h"
#include "chrome/common/print_messages.h"
#include "printing/printing_context_android.h"
#endif
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManagerBasic);
namespace printing {
PrintViewManagerBasic::PrintViewManagerBasic(content::WebContents* web_contents)
: PrintViewManagerBase(web_contents) {}
PrintViewManagerBasic::~PrintViewManagerBasic() {}
#if defined(OS_ANDROID)
void PrintViewManagerBasic::RenderProcessGone(base::TerminationStatus status) {
PrintingContextAndroid::PdfWritingDone(file_descriptor_.fd, false);
file_descriptor_ = base::FileDescriptor(-1, false);
PrintViewManagerBase::RenderProcessGone(status);
}
void PrintViewManagerBasic::OnPrintingFailed(int cookie) {
PrintingContextAndroid::PdfWritingDone(file_descriptor_.fd, false);
file_descriptor_ = base::FileDescriptor(-1, false);
PrintViewManagerBase::OnPrintingFailed(cookie);
}
bool PrintViewManagerBasic::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBasic, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled ? true : PrintViewManagerBase::OnMessageReceived(message);
}
#endif
} // namespace printing

View file

@ -1,57 +0,0 @@
// Copyright 2013 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_PRINT_VIEW_MANAGER_BASIC_H_
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASIC_H_
#include "chrome/browser/printing/print_view_manager_base.h"
#include "content/public/browser/web_contents_user_data.h"
#if defined(OS_ANDROID)
#include "base/file_descriptor_posix.h"
#endif
namespace printing {
// Manages the print commands for a WebContents - basic version.
class PrintViewManagerBasic
: public PrintViewManagerBase,
public content::WebContentsUserData<PrintViewManagerBasic> {
public:
~PrintViewManagerBasic() override;
#if defined(OS_ANDROID)
// Sets the file descriptor into which the PDF will be written.
void set_file_descriptor(const base::FileDescriptor& file_descriptor) {
file_descriptor_ = file_descriptor;
}
// Gets the file descriptor into which the PDF will be written.
base::FileDescriptor file_descriptor() const { return file_descriptor_; }
// content::WebContentsObserver implementation.
// Terminates or cancels the print job if one was pending.
virtual void RenderProcessGone(base::TerminationStatus status) override;
// content::WebContentsObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message) override;
#endif
private:
explicit PrintViewManagerBasic(content::WebContents* web_contents);
friend class content::WebContentsUserData<PrintViewManagerBasic>;
#if defined(OS_ANDROID)
virtual void OnPrintingFailed(int cookie) override;
// The file descriptor into which the PDF of the page will be written.
base::FileDescriptor file_descriptor_;
#endif
DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBasic);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASIC_H_

View file

@ -1,23 +0,0 @@
// Copyright (c) 2011 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_PRINT_VIEW_MANAGER_OBSERVER_H_
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_OBSERVER_H_
namespace printing {
// An interface the PrintViewManager uses to notify an observer when the print
// dialog is shown. Register the observer via PrintViewManager::set_observer.
class PrintViewManagerObserver {
public:
// Notifies the observer that the print dialog was shown.
virtual void OnPrintDialogShown() = 0;
protected:
virtual ~PrintViewManagerObserver() {}
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_OBSERVER_H_

View file

@ -1,152 +0,0 @@
// Copyright (c) 2012 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/printer_query.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "chrome/browser/printing/print_job_worker.h"
namespace printing {
PrinterQuery::PrinterQuery(int render_process_id, int render_frame_id)
: worker_(new PrintJobWorker(render_process_id, render_frame_id, this)),
is_print_dialog_box_shown_(false),
cookie_(PrintSettings::NewCookie()),
last_status_(PrintingContext::FAILED) {
DCHECK(base::MessageLoopForIO::IsCurrent());
}
PrinterQuery::~PrinterQuery() {
// The job should be finished (or at least canceled) when it is destroyed.
DCHECK(!is_print_dialog_box_shown_);
// If this fires, it is that this pending printer context has leaked.
DCHECK(!worker_);
}
void PrinterQuery::GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) {
is_print_dialog_box_shown_ = false;
last_status_ = result;
if (result != PrintingContext::FAILED) {
settings_ = new_settings;
cookie_ = PrintSettings::NewCookie();
} else {
// Failure.
cookie_ = 0;
}
if (!callback_.is_null()) {
// This may cause reentrancy like to call StopWorker().
callback_.Run();
callback_.Reset();
}
}
std::unique_ptr<PrintJobWorker> PrinterQuery::DetachWorker(
PrintJobWorkerOwner* new_owner) {
DCHECK(callback_.is_null());
DCHECK(worker_);
worker_->SetNewOwner(new_owner);
return std::move(worker_);
}
const PrintSettings& PrinterQuery::settings() const {
return settings_;
}
int PrinterQuery::cookie() const {
return cookie_;
}
void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
int expected_page_count,
bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable,
const base::Closure& callback) {
DCHECK(RunsTasksInCurrentSequence());
DCHECK(!is_print_dialog_box_shown_ || !is_scripted);
StartWorker(callback);
// Real work is done in PrintJobWorker::GetSettings().
is_print_dialog_box_shown_ =
ask_user_for_settings == GetSettingsAskParam::ASK_USER;
worker_->PostTask(
FROM_HERE,
base::Bind(&PrintJobWorker::GetSettings, base::Unretained(worker_.get()),
is_print_dialog_box_shown_, expected_page_count, has_selection,
margin_type, is_scripted, is_modifiable, base::string16()));
}
void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
int expected_page_count,
bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable,
const base::string16& device_name,
const base::Closure& callback) {
DCHECK(RunsTasksInCurrentSequence());
DCHECK(!is_print_dialog_box_shown_);
StartWorker(callback);
is_print_dialog_box_shown_ = false;
worker_->PostTask(
FROM_HERE,
base::Bind(&PrintJobWorker::GetSettings, base::Unretained(worker_.get()),
is_print_dialog_box_shown_, expected_page_count, has_selection,
margin_type, is_scripted, is_modifiable, device_name));
}
void PrinterQuery::SetSettings(
std::unique_ptr<base::DictionaryValue> new_settings,
const base::Closure& callback) {
StartWorker(callback);
worker_->PostTask(FROM_HERE, base::Bind(&PrintJobWorker::SetSettings,
base::Unretained(worker_.get()),
base::Passed(&new_settings)));
}
void PrinterQuery::StartWorker(const base::Closure& callback) {
DCHECK(callback_.is_null());
DCHECK(worker_);
// Lazily create the worker thread. There is one worker thread per print job.
if (!worker_->IsRunning())
worker_->Start();
callback_ = callback;
}
void PrinterQuery::StopWorker() {
if (worker_) {
// http://crbug.com/66082: We're blocking on the PrinterQuery's worker
// thread. It's not clear to me if this may result in blocking the current
// thread for an unacceptable time. We should probably fix it.
base::ThreadRestrictions::ScopedAllowIO allow_io;
worker_->Stop();
worker_.reset();
}
}
bool PrinterQuery::is_callback_pending() const {
return !callback_.is_null();
}
bool PrinterQuery::is_valid() const {
return !!worker_;
}
} // namespace printing

View file

@ -1,111 +0,0 @@
// Copyright (c) 2012 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_PRINTER_QUERY_H_
#define CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_
#include <memory>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/browser/printing/print_job_worker_owner.h"
#include "printing/print_job_constants.h"
namespace base {
class DictionaryValue;
}
namespace printing {
class PrintDestinationInterface;
class PrintJobWorker;
// Query the printer for settings.
class PrinterQuery : public PrintJobWorkerOwner {
public:
// GetSettings() UI parameter.
enum class GetSettingsAskParam {
DEFAULTS,
ASK_USER,
};
PrinterQuery(int render_process_id, int render_frame_id);
// PrintJobWorkerOwner implementation.
void GetSettingsDone(const PrintSettings& new_settings,
PrintingContext::Result result) override;
std::unique_ptr<PrintJobWorker> DetachWorker(
PrintJobWorkerOwner* new_owner) override;
const PrintSettings& settings() const override;
int cookie() const override;
// Initializes the printing context. It is fine to call this function multiple
// times to reinitialize the settings. |web_contents_observer| can be queried
// to find the owner of the print setting dialog box. It is unused when
// |ask_for_user_settings| is DEFAULTS.
void GetSettings(GetSettingsAskParam ask_user_for_settings,
int expected_page_count,
bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable,
const base::Closure& callback);
void GetSettings(GetSettingsAskParam ask_user_for_settings,
int expected_page_count,
bool has_selection,
MarginType margin_type,
bool is_scripted,
bool is_modifiable,
const base::string16& device_name,
const base::Closure& callback);
// Updates the current settings with |new_settings| dictionary values.
void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings,
const base::Closure& callback);
// Stops the worker thread since the client is done with this object.
void StopWorker();
// Returns true if a GetSettings() call is pending completion.
bool is_callback_pending() const;
PrintingContext::Result last_status() const { return last_status_; }
// Returns if a worker thread is still associated to this instance.
bool is_valid() const;
private:
~PrinterQuery() override;
// Lazy create the worker thread. There is one worker thread per print job.
void StartWorker(const base::Closure& callback);
// All the UI is done in a worker thread because many Win32 print functions
// are blocking and enters a message loop without your consent. There is one
// worker thread per print job.
std::unique_ptr<PrintJobWorker> worker_;
// Cache of the print context settings for access in the UI thread.
PrintSettings settings_;
// Is the Print... dialog box currently shown.
bool is_print_dialog_box_shown_;
// Cookie that make this instance unique.
int cookie_;
// Results from the last GetSettingsDone() callback.
PrintingContext::Result last_status_;
// Callback waiting to be run.
base::Closure callback_;
DISALLOW_COPY_AND_ASSIGN(PrinterQuery);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_

View file

@ -1,328 +0,0 @@
// Copyright (c) 2012 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/printing_message_filter.h"
#include <string>
#include "base/bind.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_io_data.h"
#include "chrome/common/print_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/child_process_host.h"
#include "printing/buildflags/buildflags.h"
#if defined(OS_ANDROID)
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "printing/printing_context_android.h"
#endif
using content::BrowserThread;
namespace printing {
namespace {
void RenderParamsFromPrintSettings(const PrintSettings& settings,
PrintMsg_Print_Params* params) {
params->page_size = settings.page_setup_device_units().physical_size();
params->content_size.SetSize(
settings.page_setup_device_units().content_area().width(),
settings.page_setup_device_units().content_area().height());
params->printable_area.SetRect(
settings.page_setup_device_units().printable_area().x(),
settings.page_setup_device_units().printable_area().y(),
settings.page_setup_device_units().printable_area().width(),
settings.page_setup_device_units().printable_area().height());
params->margin_top = settings.page_setup_device_units().content_area().y();
params->margin_left = settings.page_setup_device_units().content_area().x();
params->dpi = settings.dpi();
params->scale_factor = settings.scale_factor();
// Always use an invalid cookie.
params->document_cookie = 0;
params->selection_only = settings.selection_only();
params->supports_alpha_blend = settings.supports_alpha_blend();
params->should_print_backgrounds = settings.should_print_backgrounds();
params->display_header_footer = settings.display_header_footer();
params->title = settings.title();
params->url = settings.url();
}
#if defined(OS_ANDROID)
content::WebContents* GetWebContentsForRenderFrame(int render_process_id,
int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::RenderFrameHost* frame =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
return frame ? content::WebContents::FromRenderFrameHost(frame) : nullptr;
}
PrintViewManagerBasic* GetPrintManager(int render_process_id,
int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::WebContents* web_contents =
GetWebContentsForRenderFrame(render_process_id, render_frame_id);
return web_contents ? PrintViewManagerBasic::FromWebContents(web_contents)
: nullptr;
}
#endif
} // namespace
PrintingMessageFilter::PrintingMessageFilter(int render_process_id)
: BrowserMessageFilter(PrintMsgStart),
render_process_id_(render_process_id),
queue_(g_browser_process->print_job_manager()->queue()) {
DCHECK(queue_.get());
}
PrintingMessageFilter::~PrintingMessageFilter() {}
void PrintingMessageFilter::OnDestruct() const {
BrowserThread::DeleteOnUIThread::Destruct(this);
}
void PrintingMessageFilter::OverrideThreadForMessage(
const IPC::Message& message,
BrowserThread::ID* thread) {
#if defined(OS_ANDROID)
if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID ||
message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) {
*thread = BrowserThread::UI;
}
#endif
}
bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting,
OnAllocateTempFileForPrinting)
IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten,
OnTempFileForPrintingWritten)
#endif
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_InitSettingWithDeviceName,
OnInitSettingWithDeviceName)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
OnUpdatePrintSettings)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
#if defined(OS_ANDROID)
void PrintingMessageFilter::OnAllocateTempFileForPrinting(
int render_frame_id,
base::FileDescriptor* temp_file_fd,
int* sequence_number) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PrintViewManagerBasic* print_view_manager =
GetPrintManager(render_process_id_, render_frame_id);
if (!print_view_manager)
return;
// The file descriptor is originally created in & passed from the Android
// side, and it will handle the closing.
temp_file_fd->fd = print_view_manager->file_descriptor().fd;
temp_file_fd->auto_close = false;
}
void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_frame_id,
int sequence_number) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PrintViewManagerBasic* print_view_manager =
GetPrintManager(render_process_id_, render_frame_id);
if (print_view_manager)
print_view_manager->PdfWritingDone(true);
}
#endif // defined(OS_ANDROID)
void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
scoped_refptr<PrinterQuery> printer_query;
if (false) {
// Reply with NULL query.
OnGetDefaultPrintSettingsReply(printer_query, reply_msg);
return;
}
printer_query = queue_->PopPrinterQuery(0);
if (!printer_query.get()) {
printer_query =
queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
}
// Loads default settings. This is asynchronous, only the IPC message sender
// will hang until the settings are retrieved.
printer_query->GetSettings(
PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, DEFAULT_MARGINS,
false, false,
base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, this,
printer_query, reply_msg));
}
void PrintingMessageFilter::OnInitSettingWithDeviceName(
const base::string16& device_name,
IPC::Message* reply_msg) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
scoped_refptr<PrinterQuery> printer_query;
printer_query = queue_->PopPrinterQuery(0);
if (!printer_query.get()) {
printer_query =
queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
}
// Loads default settings. This is asynchronous, only the IPC message sender
// will hang until the settings are retrieved.
printer_query->GetSettings(
PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, DEFAULT_MARGINS,
true, true, device_name,
base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, this,
printer_query, reply_msg));
}
void PrintingMessageFilter::OnGetDefaultPrintSettingsReply(
scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg) {
PrintMsg_Print_Params params;
if (!printer_query.get() ||
printer_query->last_status() != PrintingContext::OK) {
params.Reset();
} else {
RenderParamsFromPrintSettings(printer_query->settings(), &params);
params.document_cookie = printer_query->cookie();
}
PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params);
Send(reply_msg);
// If printing was enabled.
if (printer_query.get()) {
// If user hasn't cancelled.
if (printer_query->cookie() && printer_query->settings().dpi()) {
queue_->QueuePrinterQuery(printer_query.get());
} else {
printer_query->StopWorker();
}
}
}
void PrintingMessageFilter::OnScriptedPrint(
const PrintHostMsg_ScriptedPrint_Params& params,
IPC::Message* reply_msg) {
scoped_refptr<PrinterQuery> printer_query =
queue_->PopPrinterQuery(params.cookie);
if (!printer_query.get()) {
printer_query =
queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
}
printer_query->GetSettings(
PrinterQuery::GetSettingsAskParam::ASK_USER, params.expected_pages_count,
params.has_selection, params.margin_type, true, true,
base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this,
printer_query, reply_msg));
}
void PrintingMessageFilter::OnScriptedPrintReply(
scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg) {
PrintMsg_PrintPages_Params params;
#if defined(OS_ANDROID)
// We need to save the routing ID here because Send method below deletes the
// |reply_msg| before we can get the routing ID for the Android code.
int routing_id = reply_msg->routing_id();
#endif
if (printer_query->last_status() != PrintingContext::OK ||
!printer_query->settings().dpi()) {
params.Reset();
} else {
RenderParamsFromPrintSettings(printer_query->settings(), &params.params);
params.params.document_cookie = printer_query->cookie();
params.pages = PageRange::GetPages(printer_query->settings().ranges());
}
PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params);
Send(reply_msg);
if (params.params.dpi && params.params.document_cookie) {
#if defined(OS_ANDROID)
int file_descriptor;
const base::string16& device_name = printer_query->settings().device_name();
if (base::StringToInt(device_name, &file_descriptor)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&PrintingMessageFilter::UpdateFileDescriptor, this,
routing_id, file_descriptor));
}
#endif
queue_->QueuePrinterQuery(printer_query.get());
} else {
printer_query->StopWorker();
}
}
#if defined(OS_ANDROID)
void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::WebContents* wc = GetWebContentsForRenderView(render_view_id);
if (!wc)
return;
PrintViewManagerBasic* print_view_manager =
PrintViewManagerBasic::FromWebContents(wc);
print_view_manager->set_file_descriptor(base::FileDescriptor(fd, false));
}
#endif
void PrintingMessageFilter::OnUpdatePrintSettings(
int document_cookie,
const base::DictionaryValue& job_settings,
IPC::Message* reply_msg) {
std::unique_ptr<base::DictionaryValue> new_settings(job_settings.DeepCopy());
scoped_refptr<PrinterQuery> printer_query;
printer_query = queue_->PopPrinterQuery(document_cookie);
if (!printer_query.get()) {
printer_query = queue_->CreatePrinterQuery(
content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE);
}
printer_query->SetSettings(
std::move(new_settings),
base::Bind(&PrintingMessageFilter::OnUpdatePrintSettingsReply, this,
printer_query, reply_msg));
}
void PrintingMessageFilter::OnUpdatePrintSettingsReply(
scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg) {
PrintMsg_PrintPages_Params params;
if (!printer_query.get() ||
printer_query->last_status() != PrintingContext::OK) {
params.Reset();
} else {
RenderParamsFromPrintSettings(printer_query->settings(), &params.params);
params.params.document_cookie = printer_query->cookie();
params.pages = PageRange::GetPages(printer_query->settings().ranges());
}
bool canceled = printer_query.get() &&
(printer_query->last_status() == PrintingContext::CANCEL);
PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params,
canceled);
Send(reply_msg);
// If user hasn't cancelled.
if (printer_query.get()) {
if (printer_query->cookie() && printer_query->settings().dpi()) {
queue_->QueuePrinterQuery(printer_query.get());
} else {
printer_query->StopWorker();
}
}
}
} // namespace printing

View file

@ -1,97 +0,0 @@
// Copyright (c) 2012 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_PRINTING_MESSAGE_FILTER_H_
#define CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
#include <string>
#include "base/compiler_specific.h"
#include "content/public/browser/browser_message_filter.h"
struct PrintHostMsg_ScriptedPrint_Params;
namespace base {
class DictionaryValue;
class FilePath;
} // namespace base
namespace content {
class WebContents;
}
namespace printing {
class PrintQueriesQueue;
class PrinterQuery;
// This class filters out incoming printing related IPC messages for the
// renderer process on the IPC thread.
class PrintingMessageFilter : public content::BrowserMessageFilter {
public:
PrintingMessageFilter(int render_process_id);
// content::BrowserMessageFilter methods.
void OverrideThreadForMessage(const IPC::Message& message,
content::BrowserThread::ID* thread) override;
bool OnMessageReceived(const IPC::Message& message) override;
private:
friend class base::DeleteHelper<PrintingMessageFilter>;
friend class content::BrowserThread;
~PrintingMessageFilter() override;
void OnDestruct() const override;
#if defined(OS_ANDROID)
// Used to ask the browser allocate a temporary file for the renderer
// to fill in resulting PDF in renderer.
void OnAllocateTempFileForPrinting(int render_frame_id,
base::FileDescriptor* temp_file_fd,
int* sequence_number);
void OnTempFileForPrintingWritten(int render_frame_id, int sequence_number);
// Updates the file descriptor for the PrintViewManagerBasic of a given
// render_frame_id.
void UpdateFileDescriptor(int render_frame_id, int fd);
#endif
// Get the default print setting.
void OnGetDefaultPrintSettings(IPC::Message* reply_msg);
// Set deviceName
void OnInitSettingWithDeviceName(const base::string16& device_name,
IPC::Message* reply_msg);
void OnGetDefaultPrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg);
// The renderer host have to show to the user the print dialog and returns
// the selected print settings. The task is handled by the print worker
// thread and the UI thread. The reply occurs on the IO thread.
void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params,
IPC::Message* reply_msg);
void OnScriptedPrintReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg);
// Modify the current print settings based on |job_settings|. The task is
// handled by the print worker thread and the UI thread. The reply occurs on
// the IO thread.
void OnUpdatePrintSettings(int document_cookie,
const base::DictionaryValue& job_settings,
IPC::Message* reply_msg);
void OnUpdatePrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg);
const int render_process_id_;
scoped_refptr<PrintQueriesQueue> queue_;
DISALLOW_COPY_AND_ASSIGN(PrintingMessageFilter);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_

View file

@ -1,19 +0,0 @@
// Copyright 2013 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/printing_ui_web_contents_observer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
PrintingUIWebContentsObserver::PrintingUIWebContentsObserver(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}
gfx::NativeView PrintingUIWebContentsObserver::GetParentView() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return web_contents() ? web_contents()->GetNativeView() : NULL;
}

View file

@ -1,24 +0,0 @@
// Copyright 2013 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_PRINTING_UI_WEB_CONTENTS_OBSERVER_H_
#define CHROME_BROWSER_PRINTING_PRINTING_UI_WEB_CONTENTS_OBSERVER_H_
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/native_widget_types.h"
// Wrapper used to keep track of the lifetime of a WebContents.
// Lives on the UI thread.
class PrintingUIWebContentsObserver : public content::WebContentsObserver {
public:
explicit PrintingUIWebContentsObserver(content::WebContents* web_contents);
// Return the parent NativeView of the observed WebContents.
gfx::NativeView GetParentView();
private:
DISALLOW_COPY_AND_ASSIGN(PrintingUIWebContentsObserver);
};
#endif // CHROME_BROWSER_PRINTING_PRINTING_UI_WEB_CONTENTS_OBSERVER_H_

View file

@ -1,113 +0,0 @@
// Copyright 2014 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.
// Multiply-included message file, so no include guard.
#include <string>
#include <vector>
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
#include "ipc/ipc_platform_file.h"
#include "printing/backend/print_backend.h"
#include "printing/buildflags/buildflags.h"
#include "printing/page_range.h"
#include "printing/pdf_render_settings.h"
#include "printing/pwg_raster_settings.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
#define IPC_MESSAGE_START ChromeUtilityPrintingMsgStart
IPC_ENUM_TRAITS_MAX_VALUE(printing::PdfRenderSettings::Mode,
printing::PdfRenderSettings::Mode::LAST)
IPC_STRUCT_TRAITS_BEGIN(printing::PdfRenderSettings)
IPC_STRUCT_TRAITS_MEMBER(area)
IPC_STRUCT_TRAITS_MEMBER(offsets)
IPC_STRUCT_TRAITS_MEMBER(dpi)
IPC_STRUCT_TRAITS_MEMBER(autorotate)
IPC_STRUCT_TRAITS_MEMBER(mode)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(printing::PrinterCapsAndDefaults)
IPC_STRUCT_TRAITS_MEMBER(printer_capabilities)
IPC_STRUCT_TRAITS_MEMBER(caps_mime_type)
IPC_STRUCT_TRAITS_MEMBER(printer_defaults)
IPC_STRUCT_TRAITS_MEMBER(defaults_mime_type)
IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS_MAX_VALUE(printing::ColorModel, printing::PROCESSCOLORMODEL_RGB)
IPC_STRUCT_TRAITS_BEGIN(printing::PrinterSemanticCapsAndDefaults::Paper)
IPC_STRUCT_TRAITS_MEMBER(display_name)
IPC_STRUCT_TRAITS_MEMBER(vendor_id)
IPC_STRUCT_TRAITS_MEMBER(size_um)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(printing::PrinterSemanticCapsAndDefaults)
IPC_STRUCT_TRAITS_MEMBER(collate_capable)
IPC_STRUCT_TRAITS_MEMBER(collate_default)
IPC_STRUCT_TRAITS_MEMBER(copies_capable)
IPC_STRUCT_TRAITS_MEMBER(duplex_capable)
IPC_STRUCT_TRAITS_MEMBER(duplex_default)
IPC_STRUCT_TRAITS_MEMBER(color_changeable)
IPC_STRUCT_TRAITS_MEMBER(color_default)
IPC_STRUCT_TRAITS_MEMBER(color_model)
IPC_STRUCT_TRAITS_MEMBER(bw_model)
IPC_STRUCT_TRAITS_MEMBER(papers)
IPC_STRUCT_TRAITS_MEMBER(default_paper)
IPC_STRUCT_TRAITS_MEMBER(dpis)
IPC_STRUCT_TRAITS_MEMBER(default_dpi)
IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS_MAX_VALUE(printing::PwgRasterTransformType,
printing::TRANSFORM_TYPE_LAST)
IPC_STRUCT_TRAITS_BEGIN(printing::PwgRasterSettings)
IPC_STRUCT_TRAITS_MEMBER(odd_page_transform)
IPC_STRUCT_TRAITS_MEMBER(rotate_all_pages)
IPC_STRUCT_TRAITS_MEMBER(reverse_page_order)
IPC_STRUCT_TRAITS_END()
#if defined(OS_WIN)
// Reply when the utility process loaded PDF. |page_count| is 0, if loading
// failed.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount,
int /* page_count */)
// Reply when the utility process rendered the PDF page.
IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
bool /* success */,
float /* scale_factor */)
// Request that the given font characters be loaded by the browser so it's
// cached by the OS. Please see
// PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters for details.
#if 0
IPC_SYNC_MESSAGE_CONTROL2_0(ChromeUtilityHostMsg_PreCacheFontCharacters,
LOGFONT /* font_data */,
base::string16 /* characters */)
#endif
// Tell the utility process to start rendering the given PDF into a metafile.
// Utility process would be alive until
// ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop message.
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RenderPDFPagesToMetafiles,
IPC::PlatformFileForTransit /* input_file */,
printing::PdfRenderSettings /* settings */)
// Requests conversion of the next page.
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage,
int /* page_number */,
IPC::PlatformFileForTransit /* output_file */)
// Requests utility process to stop conversion and exit.
IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop)
#endif // OS_WIN

View file

@ -1,66 +0,0 @@
// Copyright (c) 2012 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/common/print_messages.h"
#include "base/strings/string16.h"
#include "ui/gfx/geometry/size.h"
PrintMsg_Print_Params::PrintMsg_Print_Params()
: page_size(),
content_size(),
printable_area(),
margin_top(0),
margin_left(0),
dpi(0),
scale_factor(1.0f),
document_cookie(0),
selection_only(false),
supports_alpha_blend(false),
preview_ui_id(-1),
preview_request_id(0),
is_first_request(false),
print_scaling_option(blink::kWebPrintScalingOptionSourceSize),
print_to_pdf(false),
display_header_footer(false),
title(),
url(),
should_print_backgrounds(false) {}
PrintMsg_Print_Params::PrintMsg_Print_Params(const PrintMsg_Print_Params&) =
default;
PrintMsg_Print_Params::~PrintMsg_Print_Params() = default;
void PrintMsg_Print_Params::Reset() {
page_size = gfx::Size();
content_size = gfx::Size();
printable_area = gfx::Rect();
margin_top = 0;
margin_left = 0;
dpi = 0;
scale_factor = 1.0f;
document_cookie = 0;
selection_only = false;
supports_alpha_blend = false;
preview_ui_id = -1;
preview_request_id = 0;
is_first_request = false;
print_scaling_option = blink::kWebPrintScalingOptionSourceSize;
print_to_pdf = false;
display_header_footer = false;
title = base::string16();
url = base::string16();
should_print_backgrounds = false;
}
PrintMsg_PrintPages_Params::PrintMsg_PrintPages_Params() : pages() {}
PrintMsg_PrintPages_Params::PrintMsg_PrintPages_Params(
const PrintMsg_PrintPages_Params&) = default;
PrintMsg_PrintPages_Params::~PrintMsg_PrintPages_Params() = default;
void PrintMsg_PrintPages_Params::Reset() {
params.Reset();
pages = std::vector<int>();
}

View file

@ -1,314 +0,0 @@
// Copyright (c) 2012 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.
// IPC messages for printing.
// Multiply-included message file, hence no include guard.
#include <string>
#include <vector>
#include "base/memory/shared_memory.h"
#include "base/values.h"
#include "ipc/ipc_message_macros.h"
#include "printing/page_size_margins.h"
#include "printing/print_job_constants.h"
#include "third_party/blink/public/web/web_print_scaling_option.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#if defined(OS_WIN)
#include "ipc/ipc_platform_file.h"
#include "printing/backend/print_backend.h"
#include "printing/page_range.h"
#include "printing/pdf_render_settings.h"
#endif
#ifndef CHROME_COMMON_PRINT_MESSAGES_H_
#define CHROME_COMMON_PRINT_MESSAGES_H_
struct PrintMsg_Print_Params {
PrintMsg_Print_Params();
PrintMsg_Print_Params(const PrintMsg_Print_Params&);
~PrintMsg_Print_Params();
// Resets the members of the struct to 0.
void Reset();
gfx::Size page_size;
gfx::Size content_size;
gfx::Rect printable_area;
int margin_top;
int margin_left;
double dpi;
double scale_factor;
bool rasterize_pdf;
int document_cookie;
bool selection_only;
bool supports_alpha_blend;
int32_t preview_ui_id;
int preview_request_id;
bool is_first_request;
blink::WebPrintScalingOption print_scaling_option;
bool print_to_pdf;
bool display_header_footer;
base::string16 title;
base::string16 url;
bool should_print_backgrounds;
};
struct PrintMsg_PrintPages_Params {
PrintMsg_PrintPages_Params();
PrintMsg_PrintPages_Params(const PrintMsg_PrintPages_Params&);
~PrintMsg_PrintPages_Params();
// Resets the members of the struct to 0.
void Reset();
PrintMsg_Print_Params params;
std::vector<int> pages;
};
#endif // CHROME_COMMON_PRINT_MESSAGES_H_
#define IPC_MESSAGE_START PrintMsgStart
IPC_ENUM_TRAITS_MAX_VALUE(printing::MarginType, printing::MARGIN_TYPE_LAST)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(printing::DuplexMode,
printing::UNKNOWN_DUPLEX_MODE,
printing::SHORT_EDGE)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebPrintScalingOption,
blink::kWebPrintScalingOptionLast)
// Parameters for a render request.
IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
// Physical size of the page, including non-printable margins,
// in pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(page_size)
// In pixels according to dpi_x and dpi_y.
IPC_STRUCT_TRAITS_MEMBER(content_size)
// Physical printable area of the page in pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(printable_area)
// The y-offset of the printable area, in pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(margin_top)
// The x-offset of the printable area, in pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(margin_left)
// Specifies dots per inch.
IPC_STRUCT_TRAITS_MEMBER(dpi)
// Specifies the scale factor in percent
IPC_STRUCT_TRAITS_MEMBER(scale_factor)
// Cookie for the document to ensure correctness.
IPC_STRUCT_TRAITS_MEMBER(document_cookie)
// Should only print currently selected text.
IPC_STRUCT_TRAITS_MEMBER(selection_only)
// Does the printer support alpha blending?
IPC_STRUCT_TRAITS_MEMBER(supports_alpha_blend)
// *** Parameters below are used only for print preview. ***
// The print preview ui associated with this request.
IPC_STRUCT_TRAITS_MEMBER(preview_ui_id)
// The id of the preview request.
IPC_STRUCT_TRAITS_MEMBER(preview_request_id)
// True if this is the first preview request.
IPC_STRUCT_TRAITS_MEMBER(is_first_request)
// Specifies the page scaling option for preview printing.
IPC_STRUCT_TRAITS_MEMBER(print_scaling_option)
// True if print to pdf is requested.
IPC_STRUCT_TRAITS_MEMBER(print_to_pdf)
// Specifies if the header and footer should be rendered.
IPC_STRUCT_TRAITS_MEMBER(display_header_footer)
// Title string to be printed as header if requested by the user.
IPC_STRUCT_TRAITS_MEMBER(title)
// URL string to be printed as footer if requested by the user.
IPC_STRUCT_TRAITS_MEMBER(url)
// True if print backgrounds is requested by the user.
IPC_STRUCT_TRAITS_MEMBER(should_print_backgrounds)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(PrintMsg_PrintPage_Params)
// Parameters to render the page as a printed page. It must always be the same
// value for all the document.
IPC_STRUCT_MEMBER(PrintMsg_Print_Params, params)
// The page number is the indicator of the square that should be rendered
// according to the layout specified in PrintMsg_Print_Params.
IPC_STRUCT_MEMBER(int, page_number)
IPC_STRUCT_END()
IPC_STRUCT_TRAITS_BEGIN(printing::PageSizeMargins)
IPC_STRUCT_TRAITS_MEMBER(content_width)
IPC_STRUCT_TRAITS_MEMBER(content_height)
IPC_STRUCT_TRAITS_MEMBER(margin_left)
IPC_STRUCT_TRAITS_MEMBER(margin_right)
IPC_STRUCT_TRAITS_MEMBER(margin_top)
IPC_STRUCT_TRAITS_MEMBER(margin_bottom)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(PrintMsg_PrintPages_Params)
// Parameters to render the page as a printed page. It must always be the same
// value for all the document.
IPC_STRUCT_TRAITS_MEMBER(params)
// If empty, this means a request to render all the printed pages.
IPC_STRUCT_TRAITS_MEMBER(pages)
IPC_STRUCT_TRAITS_END()
// Parameters to describe a rendered page.
IPC_STRUCT_BEGIN(PrintHostMsg_DidPrintPage_Params)
// A shared memory handle to the EMF data. This data can be quite large so a
// memory map needs to be used.
IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
// Size of the metafile data.
IPC_STRUCT_MEMBER(uint32_t, data_size)
// Cookie for the document to ensure correctness.
IPC_STRUCT_MEMBER(int, document_cookie)
// Page number.
IPC_STRUCT_MEMBER(int, page_number)
// Shrink factor used to render this page.
IPC_STRUCT_MEMBER(double, actual_shrink)
// The size of the page the page author specified.
IPC_STRUCT_MEMBER(gfx::Size, page_size)
// The printable area the page author specified.
IPC_STRUCT_MEMBER(gfx::Rect, content_area)
IPC_STRUCT_END()
// Parameters for the IPC message ViewHostMsg_ScriptedPrint
IPC_STRUCT_BEGIN(PrintHostMsg_ScriptedPrint_Params)
IPC_STRUCT_MEMBER(int, cookie)
IPC_STRUCT_MEMBER(int, expected_pages_count)
IPC_STRUCT_MEMBER(bool, has_selection)
IPC_STRUCT_MEMBER(printing::MarginType, margin_type)
IPC_STRUCT_END()
// Parameters to describe a rendered document.
IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params)
// A shared memory handle to metafile data.
IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
// Size of metafile data.
IPC_STRUCT_MEMBER(uint32_t, data_size)
// Cookie for the document to ensure correctness.
IPC_STRUCT_MEMBER(int, document_cookie)
// Store the expected pages count.
IPC_STRUCT_MEMBER(int, expected_pages_count)
// Whether the preview can be modified.
IPC_STRUCT_MEMBER(bool, modifiable)
// The id of the preview request.
IPC_STRUCT_MEMBER(int, preview_request_id)
IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
// Tells the render view to switch the CSS to print media type, renders every
// requested pages and switch back the CSS to display media type.
IPC_MESSAGE_ROUTED3(PrintMsg_PrintPages,
bool /* silent print */,
bool /* print page's background */,
base::string16 /* device name*/)
// Tells the render view that printing is done so it can clean up.
IPC_MESSAGE_ROUTED1(PrintMsg_PrintingDone, bool /* success */)
// Tells the render view to switch the CSS to print media type, renders every
// requested pages for print preview using the given |settings|. This gets
// called multiple times as the user updates settings.
IPC_MESSAGE_ROUTED1(PrintMsg_PrintPreview, base::DictionaryValue /* settings */)
// Messages sent from the renderer to the browser.
#if defined(OS_WIN)
// Duplicates a shared memory handle from the renderer to the browser. Then
// the renderer can flush the handle.
IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_DuplicateSection,
base::SharedMemoryHandle /* renderer handle */,
base::SharedMemoryHandle /* browser handle */)
#endif
// Tells the browser that the renderer is done calculating the number of
// rendered pages according to the specified settings.
IPC_MESSAGE_ROUTED2(PrintHostMsg_DidGetPrintedPagesCount,
int /* rendered document cookie */,
int /* number of rendered pages */)
// Sends the document cookie of the current printer query to the browser.
IPC_MESSAGE_ROUTED1(PrintHostMsg_DidGetDocumentCookie,
int /* rendered document cookie */)
// Tells the browser that the print dialog has been shown.
IPC_MESSAGE_ROUTED0(PrintHostMsg_DidShowPrintDialog)
// Sends back to the browser the rendered "printed page" that was requested by
// a ViewMsg_PrintPage message or from scripted printing. The memory handle in
// this message is already valid in the browser process.
IPC_MESSAGE_ROUTED1(PrintHostMsg_DidPrintPage,
PrintHostMsg_DidPrintPage_Params /* page content */)
// The renderer wants to know the default print settings.
IPC_SYNC_MESSAGE_ROUTED0_1(PrintHostMsg_GetDefaultPrintSettings,
PrintMsg_Print_Params /* default_settings */)
// you can set the printer
IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_InitSettingWithDeviceName,
base::string16, /* device name */
PrintMsg_Print_Params /* default_settings */)
// The renderer wants to update the current print settings with new
// |job_settings|.
IPC_SYNC_MESSAGE_ROUTED2_2(PrintHostMsg_UpdatePrintSettings,
int /* document_cookie */,
base::DictionaryValue /* job_settings */,
PrintMsg_PrintPages_Params /* current_settings */,
bool /* canceled */)
// It's the renderer that controls the printing process when it is generated
// by javascript. This step is about showing UI to the user to select the
// final print settings. The output parameter is the same as
// ViewMsg_PrintPages which is executed implicitly.
IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_ScriptedPrint,
PrintHostMsg_ScriptedPrint_Params,
PrintMsg_PrintPages_Params
/* settings chosen by the user*/)
// This is sent when there are invalid printer settings.
IPC_MESSAGE_ROUTED0(PrintHostMsg_ShowInvalidPrinterSettingsError)
// Tell the browser printing failed.
IPC_MESSAGE_ROUTED1(PrintHostMsg_PrintingFailed, int /* document cookie */)
// Sends back to the browser the complete rendered document (non-draft mode,
// used for printing) that was requested by a PrintMsg_PrintPreview message.
// The memory handle in this message is already valid in the browser process.
IPC_MESSAGE_ROUTED1(PrintHostMsg_MetafileReadyForPrinting,
PrintHostMsg_DidPreviewDocument_Params /* params */)
IPC_MESSAGE_ROUTED2(PrintHostMsg_PrintPreviewFailed,
int /* document cookie */,
int /* request_id */);

File diff suppressed because it is too large Load diff

View file

@ -1,396 +0,0 @@
// Copyright (c) 2012 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_RENDERER_PRINTING_PRINT_WEB_VIEW_HELPER_H_
#define CHROME_RENDERER_PRINTING_PRINT_WEB_VIEW_HELPER_H_
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_observer_tracker.h"
#include "printing/pdf_metafile_skia.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "ui/gfx/geometry/size.h"
struct PrintMsg_Print_Params;
struct PrintMsg_PrintPage_Params;
struct PrintMsg_PrintPages_Params;
struct PrintHostMsg_SetOptionsFromDocument_Params;
namespace base {
class DictionaryValue;
}
namespace blink {
class WebView;
}
namespace cc {
class PaintCanvas;
}
namespace printing {
struct PageSizeMargins;
class PrepareFrameAndViewForPrint;
// Stores reference to frame using WebVew and unique name.
// Workaround to modal dialog issue on Linux. crbug.com/236147.
// If WebFrame someday supports WeakPtr, we should use it here.
class FrameReference {
public:
explicit FrameReference(blink::WebLocalFrame* frame);
FrameReference();
~FrameReference();
void Reset(blink::WebLocalFrame* frame);
blink::WebLocalFrame* GetFrame();
blink::WebView* view();
private:
blink::WebView* view_;
blink::WebLocalFrame* frame_;
};
// PrintWebViewHelper handles most of the printing grunt work for RenderView.
// We plan on making print asynchronous and that will require copying the DOM
// of the document and creating a new WebView with the contents.
class PrintWebViewHelper
: public content::RenderFrameObserver,
public content::RenderFrameObserverTracker<PrintWebViewHelper> {
public:
explicit PrintWebViewHelper(content::RenderFrame* render_frame);
~PrintWebViewHelper() override;
void PrintNode(const blink::WebNode& node);
private:
enum PrintingResult {
OK,
FAIL_PRINT_INIT,
FAIL_PRINT,
FAIL_PREVIEW,
INVALID_SETTINGS,
};
enum PrintPreviewErrorBuckets {
PREVIEW_ERROR_NONE, // Always first.
PREVIEW_ERROR_BAD_SETTING,
PREVIEW_ERROR_METAFILE_COPY_FAILED,
PREVIEW_ERROR_METAFILE_INIT_FAILED_DEPRECATED,
PREVIEW_ERROR_ZERO_PAGES,
PREVIEW_ERROR_MAC_DRAFT_METAFILE_INIT_FAILED_DEPRECATED,
PREVIEW_ERROR_PAGE_RENDERED_WITHOUT_METAFILE,
PREVIEW_ERROR_INVALID_PRINTER_SETTINGS,
PREVIEW_ERROR_LAST_ENUM // Always last.
};
// RenderFrameObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
void OnDestruct() override;
void ScriptedPrint(bool user_initiated) override;
// Message handlers ---------------------------------------------------------
#if !defined(DISABLE_BASIC_PRINTING)
void OnPrintPages(bool silent,
bool print_background,
const base::string16& device_name);
void OnPrintingDone(bool success);
#endif // !DISABLE_BASIC_PRINTING
void OnPrintPreview(const base::DictionaryValue& settings);
// Get |page_size| and |content_area| information from
// |page_layout_in_points|.
void GetPageSizeAndContentAreaFromPageLayout(
const PageSizeMargins& page_layout_in_points,
gfx::Size* page_size,
gfx::Rect* content_area);
// Update |ignore_css_margins_| based on settings.
void UpdateFrameMarginsCssInfo(const base::DictionaryValue& settings);
// Prepare frame for creating preview document.
void PrepareFrameForPreviewDocument();
// Continue creating preview document.
void OnFramePreparedForPreviewDocument();
// Finalize the print ready preview document.
bool FinalizePrintReadyDocument();
// Renders a print preview page. |page_number| is 0-based.
// Returns true if print preview should continue, false on failure.
bool RenderPreviewPage(int page_number,
const PrintMsg_Print_Params& print_params);
// Initialize the print preview document.
bool CreatePreviewDocument();
// Main printing code -------------------------------------------------------
void Print(blink::WebLocalFrame* frame,
const blink::WebNode& node,
bool silent = false,
bool print_background = false,
const base::string16& device_name = base::string16());
// Notification when printing is done - signal tear-down/free resources.
void DidFinishPrinting(PrintingResult result);
// Print Settings -----------------------------------------------------------
// Initialize print page settings with default settings.
// Used only for native printing workflow.
bool InitPrintSettings(bool fit_to_paper_size,
const base::string16& device_name = base::string16());
// Calculate number of pages in source document.
bool CalculateNumberOfPages(
blink::WebLocalFrame* frame,
const blink::WebNode& node,
int* number_of_pages,
const base::string16& device_name = base::string16());
// Update the current print settings with new |passed_job_settings|.
// |passed_job_settings| dictionary contains print job details such as printer
// name, number of copies, page range, etc.
bool UpdatePrintSettings(blink::WebLocalFrame* frame,
const blink::WebNode& node,
const base::DictionaryValue& passed_job_settings);
// Get final print settings from the user.
// Return false if the user cancels or on error.
bool GetPrintSettingsFromUser(blink::WebLocalFrame* frame,
const blink::WebNode& node,
int expected_pages_count);
// Page Printing / Rendering ------------------------------------------------
void OnFramePreparedForPrintPages();
void PrintPages();
bool PrintPagesNative(blink::WebLocalFrame* frame, int page_count);
void FinishFramePrinting();
// Prints the page listed in |params|.
#if defined(OS_LINUX) || defined(OS_ANDROID)
void PrintPageInternal(const PrintMsg_PrintPage_Params& params,
blink::WebLocalFrame* frame,
PdfMetafileSkia* metafile);
#elif defined(OS_WIN)
void PrintPageInternal(const PrintMsg_PrintPage_Params& params,
blink::WebLocalFrame* frame,
PdfMetafileSkia* metafile,
gfx::Size* page_size_in_dpi,
gfx::Rect* content_area_in_dpi);
#else
void PrintPageInternal(const PrintMsg_PrintPage_Params& params,
blink::WebLocalFrame* frame);
#endif
// Render the frame for printing.
bool RenderPagesForPrint(blink::WebLocalFrame* frame,
const blink::WebNode& node);
// Platform specific helper function for rendering page(s) to |metafile|.
#if defined(OS_MACOSX)
void RenderPage(const PrintMsg_Print_Params& params,
int page_number,
blink::WebLocalFrame* frame,
PdfMetafileSkia* metafile,
gfx::Size* page_size,
gfx::Rect* content_rect);
#endif // defined(OS_MACOSX)
// Renders page contents from |frame| to |content_area| of |canvas|.
// |page_number| is zero-based.
// When method is called, canvas should be setup to draw to |canvas_area|
// with |scale_factor|.
static float RenderPageContent(blink::WebLocalFrame* frame,
int page_number,
const gfx::Rect& canvas_area,
const gfx::Rect& content_area,
double scale_factor,
cc::PaintCanvas* canvas);
// Helper methods -----------------------------------------------------------
bool CopyMetafileDataToSharedMem(const PdfMetafileSkia& metafile,
base::SharedMemoryHandle* shared_mem_handle);
// Helper method to get page layout in points and fit to page if needed.
static void ComputePageLayoutInPointsForCss(
blink::WebLocalFrame* frame,
int page_index,
const PrintMsg_Print_Params& default_params,
bool ignore_css_margins,
double* scale_factor,
PageSizeMargins* page_layout_in_points);
// Script Initiated Printing ------------------------------------------------
// Notifies the browser a print preview page has been rendered.
// |page_number| is 0-based.
// For a valid |page_number| with modifiable content,
// |metafile| is the rendered page. Otherwise |metafile| is NULL.
// Returns true if print preview should continue, false on failure.
bool PreviewPageRendered(int page_number, PdfMetafileSkia* metafile);
void SetPrintPagesParams(const PrintMsg_PrintPages_Params& settings);
// WebView used only to print the selection.
std::unique_ptr<PrepareFrameAndViewForPrint> prep_frame_view_;
bool reset_prep_frame_view_;
std::unique_ptr<PrintMsg_PrintPages_Params> print_pages_params_;
bool is_print_ready_metafile_sent_;
bool ignore_css_margins_;
// Used for scripted initiated printing blocking.
bool is_scripted_printing_blocked_;
// Let the browser process know of a printing failure. Only set to false when
// the failure came from the browser in the first place.
bool notify_browser_of_print_failure_;
// True, when printing from print preview.
bool print_for_preview_;
// Keeps track of the state of print preview between messages.
// TODO(vitalybuka): Create PrintPreviewContext when needed and delete after
// use. Now it's interaction with various messages is confusing.
class PrintPreviewContext {
public:
PrintPreviewContext();
~PrintPreviewContext();
// Initializes the print preview context. Need to be called to set
// the |web_frame| / |web_node| to generate the print preview for.
void InitWithFrame(blink::WebLocalFrame* web_frame);
void InitWithNode(const blink::WebNode& web_node);
// Does bookkeeping at the beginning of print preview.
void OnPrintPreview();
// Create the print preview document. |pages| is empty to print all pages.
// Takes ownership of |prepared_frame|.
bool CreatePreviewDocument(PrepareFrameAndViewForPrint* prepared_frame,
const std::vector<int>& pages);
// Called after a page gets rendered. |page_time| is how long the
// rendering took.
void RenderedPreviewPage(const base::TimeDelta& page_time);
// Updates the print preview context when the required pages are rendered.
void AllPagesRendered();
// Finalizes the print ready preview document.
void FinalizePrintReadyDocument();
// Cleanup after print preview finishes.
void Finished();
// Cleanup after print preview fails.
void Failed(bool report_error);
// Helper functions
int GetNextPageNumber();
bool IsRendering() const;
bool IsModifiable();
bool HasSelection();
bool IsLastPageOfPrintReadyMetafile() const;
bool IsFinalPageRendered() const;
// Setters
void set_generate_draft_pages(bool generate_draft_pages);
void set_error(enum PrintPreviewErrorBuckets error);
// Getters
// Original frame for which preview was requested.
blink::WebLocalFrame* source_frame();
// Original node for which preview was requested.
const blink::WebNode& source_node() const;
// Frame to be use to render preview. May be the same as source_frame(), or
// generated from it, e.g. copy of selected block.
blink::WebLocalFrame* prepared_frame();
// Node to be use to render preview. May be the same as source_node(), or
// generated from it, e.g. copy of selected block.
const blink::WebNode& prepared_node() const;
int total_page_count() const;
bool generate_draft_pages() const;
PdfMetafileSkia* metafile();
int last_error() const;
private:
enum State {
UNINITIALIZED, // Not ready to render.
INITIALIZED, // Ready to render.
RENDERING, // Rendering.
DONE // Finished rendering.
};
// Reset some of the internal rendering context.
void ClearContext();
// Specifies what to render for print preview.
FrameReference source_frame_;
blink::WebNode source_node_;
std::unique_ptr<PrepareFrameAndViewForPrint> prep_frame_view_;
std::unique_ptr<PdfMetafileSkia> metafile_;
// Total page count in the renderer.
int total_page_count_;
// The current page to render.
int current_page_index_;
// List of page indices that need to be rendered.
std::vector<int> pages_to_render_;
// True, when draft pages needs to be generated.
bool generate_draft_pages_;
// Specifies the total number of pages in the print ready metafile.
int print_ready_metafile_page_count_;
base::TimeDelta document_render_time_;
base::TimeTicks begin_time_;
enum PrintPreviewErrorBuckets error_;
State state_;
};
bool print_node_in_progress_;
bool is_loading_;
bool is_scripted_preview_delayed_;
int ipc_nesting_level_;
PrintPreviewContext print_preview_context_;
// Used to fix a race condition where the source is a PDF and print preview
// hangs because RequestPrintPreview is called before DidStopLoading() is
// called. This is a store for the RequestPrintPreview() call and its
// parameters so that it can be invoked after DidStopLoading.
base::Closure on_stop_loading_closure_;
base::WeakPtrFactory<PrintWebViewHelper> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelper);
};
} // namespace printing
#endif // CHROME_RENDERER_PRINTING_PRINT_WEB_VIEW_HELPER_H_

View file

@ -1,142 +0,0 @@
// Copyright (c) 2012 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/renderer/printing/print_web_view_helper.h"
#include <memory>
#include "base/logging.h"
#include "chrome/common/print_messages.h"
#include "content/public/renderer/render_thread.h"
#include "printing/metafile_skia_wrapper.h"
#include "printing/page_size_margins.h"
#include "printing/pdf_metafile_skia.h"
#include "third_party/blink/public/web/web_local_frame.h"
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
#include "base/process/process_handle.h"
#else
#include "base/file_descriptor_posix.h"
#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
namespace printing {
using blink::WebLocalFrame;
bool PrintWebViewHelper::RenderPreviewPage(
int page_number,
const PrintMsg_Print_Params& print_params) {
PrintMsg_PrintPage_Params page_params;
page_params.params = print_params;
page_params.page_number = page_number;
std::unique_ptr<PdfMetafileSkia> draft_metafile;
PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile();
if (print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_) {
draft_metafile.reset(new PdfMetafileSkia());
initial_render_metafile = draft_metafile.get();
}
base::TimeTicks begin_time = base::TimeTicks::Now();
PrintPageInternal(page_params, print_preview_context_.prepared_frame(),
initial_render_metafile);
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
begin_time);
if (draft_metafile.get()) {
draft_metafile->FinishDocument();
} else if (print_preview_context_.IsModifiable() &&
print_preview_context_.generate_draft_pages()) {
DCHECK(!draft_metafile.get());
draft_metafile =
print_preview_context_.metafile()->GetMetafileForCurrentPage(
SkiaDocumentType::PDF);
}
return PreviewPageRendered(page_number, draft_metafile.get());
}
bool PrintWebViewHelper::PrintPagesNative(blink::WebLocalFrame* frame,
int page_count) {
PdfMetafileSkia metafile;
if (!metafile.Init())
return false;
const PrintMsg_PrintPages_Params& params = *print_pages_params_;
std::vector<int> printed_pages;
if (params.pages.empty()) {
for (int i = 0; i < page_count; ++i) {
printed_pages.push_back(i);
}
} else {
// TODO(vitalybuka): redesign to make more code cross platform.
for (size_t i = 0; i < params.pages.size(); ++i) {
if (params.pages[i] >= 0 && params.pages[i] < page_count) {
printed_pages.push_back(params.pages[i]);
}
}
}
if (printed_pages.empty())
return false;
PrintMsg_PrintPage_Params page_params;
page_params.params = params.params;
for (size_t i = 0; i < printed_pages.size(); ++i) {
page_params.page_number = printed_pages[i];
PrintPageInternal(page_params, frame, &metafile);
}
// blink::printEnd() for PDF should be called before metafile is closed.
FinishFramePrinting();
metafile.FinishDocument();
PrintHostMsg_DidPrintPage_Params printed_page_params;
if (!CopyMetafileDataToSharedMem(metafile,
&printed_page_params.metafile_data_handle)) {
return false;
}
printed_page_params.data_size = metafile.GetDataSize();
printed_page_params.document_cookie = params.params.document_cookie;
for (size_t i = 0; i < printed_pages.size(); ++i) {
printed_page_params.page_number = printed_pages[i];
Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params));
// Send the rest of the pages with an invalid metafile handle.
printed_page_params.metafile_data_handle.Release();
}
return true;
}
void PrintWebViewHelper::PrintPageInternal(
const PrintMsg_PrintPage_Params& params,
WebLocalFrame* frame,
PdfMetafileSkia* metafile) {
PageSizeMargins page_layout_in_points;
double scale_factor = 1.0f;
ComputePageLayoutInPointsForCss(frame, params.page_number, params.params,
ignore_css_margins_, &scale_factor,
&page_layout_in_points);
gfx::Size page_size;
gfx::Rect content_area;
GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size,
&content_area);
gfx::Rect canvas_area = content_area;
cc::PaintCanvas* canvas =
metafile->GetVectorCanvasForNewPage(page_size, canvas_area, scale_factor);
if (!canvas)
return;
MetafileSkiaWrapper::SetMetafileOnCanvas(canvas, metafile);
RenderPageContent(frame, params.page_number, canvas_area, content_area,
scale_factor, canvas);
// Done printing. Close the device context to retrieve the compiled metafile.
if (!metafile->FinishPage())
NOTREACHED() << "metafile failed";
}
} // namespace printing

View file

@ -1,127 +0,0 @@
// Copyright (c) 2012 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/renderer/printing/print_web_view_helper.h"
#import <AppKit/AppKit.h>
#include "base/logging.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/metrics/histogram.h"
#include "cc/paint/paint_canvas.h"
#include "chrome/common/print_messages.h"
#include "printing/metafile_skia_wrapper.h"
#include "printing/page_size_margins.h"
#include "third_party/blink/public/web/web_local_frame.h"
namespace printing {
using blink::WebLocalFrame;
void PrintWebViewHelper::PrintPageInternal(
const PrintMsg_PrintPage_Params& params,
WebLocalFrame* frame) {
PdfMetafileSkia metafile;
CHECK(metafile.Init());
int page_number = params.page_number;
gfx::Size page_size_in_dpi;
gfx::Rect content_area_in_dpi;
RenderPage(print_pages_params_->params, page_number, frame, &metafile,
&page_size_in_dpi, &content_area_in_dpi);
metafile.FinishDocument();
PrintHostMsg_DidPrintPage_Params page_params;
page_params.data_size = metafile.GetDataSize();
page_params.page_number = page_number;
page_params.document_cookie = params.params.document_cookie;
page_params.page_size = page_size_in_dpi;
page_params.content_area = content_area_in_dpi;
// Ask the browser to create the shared memory for us.
if (!CopyMetafileDataToSharedMem(metafile,
&(page_params.metafile_data_handle))) {
// TODO(thestig): Fail and return false instead.
page_params.data_size = 0;
}
Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params));
}
bool PrintWebViewHelper::RenderPreviewPage(
int page_number,
const PrintMsg_Print_Params& print_params) {
PrintMsg_Print_Params printParams = print_params;
std::unique_ptr<PdfMetafileSkia> draft_metafile;
PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile();
bool render_to_draft =
print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_;
if (render_to_draft) {
draft_metafile.reset(new PdfMetafileSkia());
CHECK(draft_metafile->Init());
initial_render_metafile = draft_metafile.get();
}
base::TimeTicks begin_time = base::TimeTicks::Now();
gfx::Size page_size;
RenderPage(printParams, page_number, print_preview_context_.prepared_frame(),
initial_render_metafile, &page_size, nullptr);
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
begin_time);
if (draft_metafile.get()) {
draft_metafile->FinishDocument();
} else {
if (print_preview_context_.IsModifiable() &&
print_preview_context_.generate_draft_pages()) {
DCHECK(!draft_metafile.get());
draft_metafile =
print_preview_context_.metafile()->GetMetafileForCurrentPage(
SkiaDocumentType::PDF);
}
}
return PreviewPageRendered(page_number, draft_metafile.get());
}
void PrintWebViewHelper::RenderPage(const PrintMsg_Print_Params& params,
int page_number,
WebLocalFrame* frame,
PdfMetafileSkia* metafile,
gfx::Size* page_size,
gfx::Rect* content_rect) {
double scale_factor = 1.0f;
double webkit_shrink_factor = frame->GetPrintPageShrink(page_number);
PageSizeMargins page_layout_in_points;
gfx::Rect content_area;
ComputePageLayoutInPointsForCss(frame, page_number, params,
ignore_css_margins_, &scale_factor,
&page_layout_in_points);
GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, page_size,
&content_area);
if (content_rect)
*content_rect = content_area;
scale_factor *= webkit_shrink_factor;
gfx::Rect canvas_area = content_area;
{
cc::PaintCanvas* canvas = metafile->GetVectorCanvasForNewPage(
*page_size, canvas_area, scale_factor);
if (!canvas)
return;
MetafileSkiaWrapper::SetMetafileOnCanvas(canvas, metafile);
RenderPageContent(frame, page_number, canvas_area, content_area,
scale_factor, static_cast<cc::PaintCanvas*>(canvas));
}
// Done printing. Close the device context to retrieve the compiled metafile.
metafile->FinishPage();
}
} // namespace printing

View file

@ -1,207 +0,0 @@
// Copyright 2014 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/renderer/printing/print_web_view_helper.h"
#include <memory>
#include "base/logging.h"
#include "base/process/process_handle.h"
#include "chrome/common/print_messages.h"
#include "content/public/renderer/render_thread.h"
#include "printing/metafile_skia_wrapper.h"
#include "printing/page_size_margins.h"
#include "printing/pdf_metafile_skia.h"
#include "printing/units.h"
#include "third_party/blink/public/web/web_local_frame.h"
namespace printing {
using blink::WebLocalFrame;
bool PrintWebViewHelper::RenderPreviewPage(
int page_number,
const PrintMsg_Print_Params& print_params) {
PrintMsg_PrintPage_Params page_params;
page_params.params = print_params;
page_params.page_number = page_number;
std::unique_ptr<PdfMetafileSkia> draft_metafile;
PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile();
if (print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_) {
draft_metafile.reset(new PdfMetafileSkia());
initial_render_metafile = draft_metafile.get();
}
base::TimeTicks begin_time = base::TimeTicks::Now();
PrintPageInternal(page_params, print_preview_context_.prepared_frame(),
initial_render_metafile, NULL, NULL);
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
begin_time);
if (draft_metafile.get()) {
draft_metafile->FinishDocument();
} else if (print_preview_context_.IsModifiable() &&
print_preview_context_.generate_draft_pages()) {
DCHECK(!draft_metafile.get());
draft_metafile =
print_preview_context_.metafile()->GetMetafileForCurrentPage(
SkiaDocumentType::PDF);
}
return PreviewPageRendered(page_number, draft_metafile.get());
}
bool PrintWebViewHelper::PrintPagesNative(blink::WebLocalFrame* frame,
int page_count) {
PdfMetafileSkia metafile;
if (!metafile.Init())
return false;
const PrintMsg_PrintPages_Params& params = *print_pages_params_;
std::vector<int> printed_pages;
if (params.pages.empty()) {
for (int i = 0; i < page_count; ++i) {
printed_pages.push_back(i);
}
} else {
// TODO(vitalybuka): redesign to make more code cross platform.
for (size_t i = 0; i < params.pages.size(); ++i) {
if (params.pages[i] >= 0 && params.pages[i] < page_count) {
printed_pages.push_back(params.pages[i]);
}
}
}
if (printed_pages.empty())
return false;
std::vector<gfx::Size> page_size_in_dpi(printed_pages.size());
std::vector<gfx::Rect> content_area_in_dpi(printed_pages.size());
PrintMsg_PrintPage_Params page_params;
page_params.params = params.params;
for (size_t i = 0; i < printed_pages.size(); ++i) {
page_params.page_number = printed_pages[i];
PrintPageInternal(page_params, frame, &metafile, &page_size_in_dpi[i],
&content_area_in_dpi[i]);
}
// blink::printEnd() for PDF should be called before metafile is closed.
FinishFramePrinting();
metafile.FinishDocument();
PrintHostMsg_DidPrintPage_Params printed_page_params;
if (!CopyMetafileDataToSharedMem(metafile,
&printed_page_params.metafile_data_handle)) {
return false;
}
printed_page_params.content_area = params.params.printable_area;
printed_page_params.data_size = metafile.GetDataSize();
printed_page_params.document_cookie = params.params.document_cookie;
printed_page_params.page_size = params.params.page_size;
for (size_t i = 0; i < printed_pages.size(); ++i) {
printed_page_params.page_number = printed_pages[i];
printed_page_params.page_size = page_size_in_dpi[i];
printed_page_params.content_area = content_area_in_dpi[i];
Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params));
// Send the rest of the pages with an invalid metafile handle.
printed_page_params.metafile_data_handle.Close();
printed_page_params.metafile_data_handle = base::SharedMemoryHandle();
}
return true;
}
void PrintWebViewHelper::PrintPageInternal(
const PrintMsg_PrintPage_Params& params,
WebLocalFrame* frame,
PdfMetafileSkia* metafile,
gfx::Size* page_size_in_dpi,
gfx::Rect* content_area_in_dpi) {
PageSizeMargins page_layout_in_points;
double css_scale_factor = 1.0f;
ComputePageLayoutInPointsForCss(frame, params.page_number, params.params,
ignore_css_margins_, &css_scale_factor,
&page_layout_in_points);
gfx::Size page_size;
gfx::Rect content_area;
GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size,
&content_area);
int dpi = static_cast<int>(params.params.dpi);
// Calculate the actual page size and content area in dpi.
if (page_size_in_dpi) {
*page_size_in_dpi =
gfx::Size(static_cast<int>(ConvertUnitDouble(page_size.width(),
kPointsPerInch, dpi)),
static_cast<int>(ConvertUnitDouble(page_size.height(),
kPointsPerInch, dpi)));
}
if (content_area_in_dpi) {
// Output PDF matches paper size and should be printer edge to edge.
*content_area_in_dpi =
gfx::Rect(0, 0, page_size_in_dpi->width(), page_size_in_dpi->height());
}
gfx::Rect canvas_area = content_area;
#if 0
params.params.display_header_footer ? gfx::Rect(page_size) : content_area;
#endif
float webkit_page_shrink_factor =
frame->GetPrintPageShrink(params.page_number);
float scale_factor = css_scale_factor * webkit_page_shrink_factor;
cc::PaintCanvas* canvas =
metafile->GetVectorCanvasForNewPage(page_size, canvas_area, scale_factor);
if (!canvas)
return;
MetafileSkiaWrapper::SetMetafileOnCanvas(canvas, metafile);
#if 0
if (params.params.display_header_footer) {
// |page_number| is 0-based, so 1 is added.
PrintHeaderAndFooter(canvas.get(),
params.page_number + 1,
print_preview_context_.total_page_count(),
*frame,
scale_factor,
page_layout_in_points,
params.params);
}
#endif
float webkit_scale_factor =
RenderPageContent(frame, params.page_number, canvas_area, content_area,
scale_factor, canvas);
DCHECK_GT(webkit_scale_factor, 0.0f);
// Done printing. Close the device context to retrieve the compiled metafile.
if (!metafile->FinishPage())
NOTREACHED() << "metafile failed";
}
bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
const PdfMetafileSkia& metafile,
base::SharedMemoryHandle* shared_mem_handle) {
uint32_t buf_size = metafile.GetDataSize();
if (buf_size == 0)
return false;
std::unique_ptr<base::SharedMemory> shared_buf(
content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(buf_size));
if (!shared_buf)
return false;
if (!shared_buf->Map(buf_size))
return false;
if (!metafile.GetData(shared_buf->memory(), buf_size))
return false;
*shared_mem_handle =
base::SharedMemory::DuplicateHandle(shared_buf->handle());
return true;
}
} // namespace printing

View file

@ -1,176 +0,0 @@
// Copyright 2014 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/utility/printing_handler_win.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "chrome/common/chrome_utility_printing_messages.h"
#include "chrome/common/print_messages.h"
#include "content/public/utility/utility_thread.h"
#include "pdf/pdf.h"
#include "printing/emf_win.h"
#include "printing/page_range.h"
#include "printing/pdf_render_settings.h"
#include "ui/gfx/gdi_util.h"
namespace printing {
namespace {
bool Send(IPC::Message* message) {
return content::UtilityThread::Get()->Send(message);
}
void ReleaseProcessIfNeeded() {
content::UtilityThread::Get()->ReleaseProcess();
}
void PreCacheFontCharacters(const LOGFONT* logfont,
const wchar_t* text,
size_t text_length) {
#if 0
Send(new ChromeUtilityHostMsg_PreCacheFontCharacters(
*logfont, base::string16(text, text_length)));
#endif
}
} // namespace
PrintingHandlerWin::PrintingHandlerWin() {
chrome_pdf::SetPDFEnsureTypefaceCharactersAccessible(PreCacheFontCharacters);
}
PrintingHandlerWin::~PrintingHandlerWin() {}
bool PrintingHandlerWin::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintingHandlerWin, message)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles,
OnRenderPDFPagesToMetafile)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage,
OnRenderPDFPagesToMetafileGetPage)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop,
OnRenderPDFPagesToMetafileStop)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PrintingHandlerWin::OnRenderPDFPagesToMetafile(
IPC::PlatformFileForTransit pdf_transit,
const PdfRenderSettings& settings) {
pdf_rendering_settings_ = settings;
chrome_pdf::SetPDFUseGDIPrinting(pdf_rendering_settings_.mode ==
PdfRenderSettings::Mode::GDI_TEXT);
int postscript_level;
switch (pdf_rendering_settings_.mode) {
case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2:
postscript_level = chrome_pdf::PrintingMode::kPostScript2;
break;
case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3:
postscript_level = chrome_pdf::PrintingMode::kPostScript3;
break;
default:
postscript_level =
chrome_pdf::PrintingMode::kEmf; // Not using postscript.
}
chrome_pdf::SetPDFUsePrintMode(postscript_level);
base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit);
int page_count = LoadPDF(std::move(pdf_file));
Send(
new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count));
}
void PrintingHandlerWin::OnRenderPDFPagesToMetafileGetPage(
int page_number,
IPC::PlatformFileForTransit output_file) {
base::File emf_file = IPC::PlatformFileForTransitToFile(output_file);
float scale_factor = 1.0f;
bool postscript = pdf_rendering_settings_.mode ==
PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 ||
pdf_rendering_settings_.mode ==
PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3;
bool success = RenderPdfPageToMetafile(page_number, std::move(emf_file),
&scale_factor, postscript);
Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone(
success, scale_factor));
}
void PrintingHandlerWin::OnRenderPDFPagesToMetafileStop() {
ReleaseProcessIfNeeded();
}
int PrintingHandlerWin::LoadPDF(base::File pdf_file) {
int64_t length64 = pdf_file.GetLength();
if (length64 <= 0 || length64 > std::numeric_limits<int>::max())
return 0;
int length = static_cast<int>(length64);
pdf_data_.resize(length);
if (length != pdf_file.Read(0, pdf_data_.data(), pdf_data_.size()))
return 0;
int total_page_count = 0;
if (!chrome_pdf::GetPDFDocInfo(&pdf_data_.front(), pdf_data_.size(),
&total_page_count, nullptr)) {
return 0;
}
return total_page_count;
}
bool PrintingHandlerWin::RenderPdfPageToMetafile(int page_number,
base::File output_file,
float* scale_factor,
bool postscript) {
Emf metafile;
metafile.Init();
// We need to scale down DC to fit an entire page into DC available area.
// Current metafile is based on screen DC and have current screen size.
// Writing outside of those boundaries will result in the cut-off output.
// On metafiles (this is the case here), scaling down will still record
// original coordinates and we'll be able to print in full resolution.
// Before playback we'll need to counter the scaling up that will happen
// in the service (print_system_win.cc).
//
// The postscript driver does not use the metafile size since it outputs
// postscript rather than a metafile. Instead it uses the printable area
// sent to RenderPDFPageToDC to determine the area to render. Therefore,
// don't scale the DC to match the metafile, and send the printer physical
// offsets to the driver.
if (!postscript) {
*scale_factor = gfx::CalculatePageScale(
metafile.context(), pdf_rendering_settings_.area.right(),
pdf_rendering_settings_.area.bottom());
gfx::ScaleDC(metafile.context(), *scale_factor);
}
// The underlying metafile is of type Emf and ignores the arguments passed
// to StartPage.
metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
int offset_x = postscript ? pdf_rendering_settings_.offsets.x() : 0;
int offset_y = postscript ? pdf_rendering_settings_.offsets.y() : 0;
if (!chrome_pdf::RenderPDFPageToDC(
&pdf_data_.front(), pdf_data_.size(), page_number, metafile.context(),
pdf_rendering_settings_.dpi.width(),
pdf_rendering_settings_.dpi.height(),
pdf_rendering_settings_.area.x() - offset_x,
pdf_rendering_settings_.area.y() - offset_y,
pdf_rendering_settings_.area.width(),
pdf_rendering_settings_.area.height(), true, false, true, true,
pdf_rendering_settings_.use_color,
pdf_rendering_settings_.autorotate)) {
return false;
}
metafile.FinishPage();
metafile.FinishDocument();
return metafile.SaveTo(&output_file);
}
} // namespace printing

View file

@ -1,52 +0,0 @@
// Copyright 2014 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_UTILITY_PRINTING_HANDLER_WIN_H_
#define CHROME_UTILITY_PRINTING_HANDLER_WIN_H_
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/utility/utility_message_handler.h"
#include "ipc/ipc_platform_file.h"
#include "printing/pdf_render_settings.h"
namespace printing {
struct PdfRenderSettings;
struct PwgRasterSettings;
struct PageRange;
// Dispatches IPCs for printing.
class PrintingHandlerWin : public UtilityMessageHandler {
public:
PrintingHandlerWin();
~PrintingHandlerWin() override;
// IPC::Listener:
bool OnMessageReceived(const IPC::Message& message) override;
private:
// IPC message handlers.
void OnRenderPDFPagesToMetafile(IPC::PlatformFileForTransit pdf_transit,
const PdfRenderSettings& settings);
void OnRenderPDFPagesToMetafileGetPage(
int page_number,
IPC::PlatformFileForTransit output_file);
void OnRenderPDFPagesToMetafileStop();
int LoadPDF(base::File pdf_file);
bool RenderPdfPageToMetafile(int page_number,
base::File output_file,
float* scale_factor,
bool postscript);
std::vector<char> pdf_data_;
PdfRenderSettings pdf_rendering_settings_;
DISALLOW_COPY_AND_ASSIGN(PrintingHandlerWin);
};
} // namespace printing
#endif // CHROME_UTILITY_PRINTING_HANDLER_WIN_H_

View file

@ -1,21 +0,0 @@
// Copyright 2013 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_UTILITY_UTILITY_MESSAGE_HANDLER_H_
#define CHROME_UTILITY_UTILITY_MESSAGE_HANDLER_H_
namespace IPC {
class Message;
}
class UtilityMessageHandler {
public:
virtual ~UtilityMessageHandler() {}
// Called when a message is received. Returns true iff the message was
// handled.
virtual bool OnMessageReceived(const IPC::Message& message) = 0;
};
#endif // CHROME_UTILITY_UTILITY_MESSAGE_HANDLER_H_

View file

@ -5,6 +5,17 @@
V8 Proxy Resolver
</message>
<!-- Printing Service -->
<message name="IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME" desc="The name of the utility process used for printing conversions.">
Printing Service
</message>
<message name="IDS_PRINT_INVALID_PRINTER_SETTINGS" desc="Message to display when selected printer is not reachable or its settings are invalid.">
The selected printer is not available or not installed correctly. <ph name="BR">&lt;br&gt;</ph> Check your printer or try selecting another printer.
</message>
<message name="IDS_DEFAULT_PRINT_DOCUMENT_TITLE" desc="Default title for a print document">
Untitled Document
</message>
<!-- Desktop Capturer API -->
<message name="IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME" desc="Name for screens in the desktop media picker UI when there is only one monitor.">
Entire screen

View file

@ -582,40 +582,13 @@ filenames = {
"chromium_src/chrome/browser/chrome_process_finder_win.cc",
"chromium_src/chrome/browser/chrome_process_finder_win.h",
"chromium_src/chrome/browser/chrome_notification_types.h",
"chromium_src/chrome/browser/printing/print_job.cc",
"chromium_src/chrome/browser/printing/print_job.h",
"chromium_src/chrome/browser/printing/print_job_manager.cc",
"chromium_src/chrome/browser/printing/print_job_manager.h",
"chromium_src/chrome/browser/printing/print_job_worker.cc",
"chromium_src/chrome/browser/printing/print_job_worker.h",
"chromium_src/chrome/browser/printing/print_job_worker_owner.cc",
"chromium_src/chrome/browser/printing/print_job_worker_owner.h",
"chromium_src/chrome/browser/printing/print_view_manager_base.cc",
"chromium_src/chrome/browser/printing/print_view_manager_base.h",
"chromium_src/chrome/browser/printing/print_view_manager_basic.cc",
"chromium_src/chrome/browser/printing/print_view_manager_basic.h",
"chromium_src/chrome/browser/printing/print_view_manager_observer.h",
"chromium_src/chrome/browser/printing/printer_query.cc",
"chromium_src/chrome/browser/printing/printer_query.h",
"chromium_src/chrome/browser/printing/printing_message_filter.cc",
"chromium_src/chrome/browser/printing/printing_message_filter.h",
"chromium_src/chrome/browser/printing/print_preview_message_handler.cc",
"chromium_src/chrome/browser/printing/print_preview_message_handler.h",
"chromium_src/chrome/browser/process_singleton_posix.cc",
"chromium_src/chrome/browser/process_singleton_win.cc",
"chromium_src/chrome/browser/process_singleton.h",
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc",
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h",
"chromium_src/chrome/common/print_messages.cc",
"chromium_src/chrome/common/print_messages.h",
"chromium_src/chrome/renderer/printing/print_web_view_helper.cc",
"chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc",
"chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm",
"chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc",
"chromium_src/chrome/renderer/printing/print_web_view_helper.h",
"chromium_src/chrome/renderer/spellchecker/spellcheck_worditerator.cc",
"chromium_src/chrome/renderer/spellchecker/spellcheck_worditerator.h",
"chromium_src/chrome/utility/utility_message_handler.h",
]
lib_sources_nss = [
@ -623,13 +596,6 @@ filenames = {
"chromium_src/chrome/browser/certificate_manager_model.h",
]
lib_sources_win = [
"chromium_src/chrome/browser/printing/pdf_to_emf_converter.cc",
"chromium_src/chrome/browser/printing/pdf_to_emf_converter.h",
"chromium_src/chrome/utility/printing_handler_win.cc",
"chromium_src/chrome/utility/printing_handler_win.h",
]
app_sources = [
"atom/app/atom_main.cc",
"atom/app/atom_main.h",

View file

@ -249,6 +249,8 @@ WebContents.prototype.printToPDF = function (options, callback) {
printingSetting.mediaSize = PDFPageSizes['A4']
}
// Chromium expects this in a 0-100 range number, not as float
printingSetting.scaleFactor *= 100
this._printToPDF(printingSetting, callback)
}

View file

@ -5,7 +5,8 @@
"service_manager:connector": {
"requires": {
"device": [ "device:geolocation_control" ],
"proxy_resolver": [ "factory" ]
"proxy_resolver": [ "factory" ],
"chrome_printing": [ "converter" ]
}
}
}

View file

@ -521,3 +521,11 @@ patches:
remained in chromium from a long time ago (last update of that part of the
code was around 2012-2013, and this is purely UI, I don't think they have
automated tests for it).
-
author: Heilig Benedek <benecene@gmail.com>
file: printing.patch
description: |
Add changeset that was previously applied to sources in chromium_src. The
majority of changes originally come from these PRs:
* https://github.com/electron/electron/pull/1835
* https://github.com/electron/electron/pull/8596

View file

@ -0,0 +1,989 @@
diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc
index 1065e808e621..13715870097b 100644
--- a/chrome/browser/printing/print_job_worker.cc
+++ b/chrome/browser/printing/print_job_worker.cc
@@ -20,12 +20,13 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/printing/print_job.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "printing/print_job_constants.h"
+#include "printing/print_settings_conversion.h"
#include "printing/printed_document.h"
#include "printing/printing_utils.h"
#include "ui/base/l10n/l10n_util.h"
@@ -174,7 +175,8 @@ void PrintJobWorker::GetSettings(bool ask_user_for_settings,
bool has_selection,
MarginType margin_type,
bool is_scripted,
- bool is_modifiable) {
+ bool is_modifiable,
+ const base::string16& device_name) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(page_number_, PageNumber::npos());
@@ -200,6 +202,12 @@ void PrintJobWorker::GetSettings(bool ask_user_for_settings,
base::BindOnce(&PrintJobWorker::GetSettingsWithUI,
base::Unretained(this), document_page_count,
has_selection, is_scripted)));
+ } else if (!device_name.empty()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&WorkerHoldRefCallback, base::WrapRefCounted(query_),
+ base::BindOnce(&PrintJobWorker::InitWithDeviceName,
+ base::Unretained(this), device_name)));
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -316,6 +324,14 @@ void PrintJobWorker::UseDefaultSettings() {
GetSettingsDone(result);
}
+void PrintJobWorker::InitWithDeviceName(const base::string16& device_name) {
+ const auto& settings = printing_context_->settings();
+ std::unique_ptr<base::DictionaryValue> dic(new base::DictionaryValue);
+ printing::PrintSettingsToJobSettings(settings, dic.get());
+ dic->SetString(kSettingDeviceName, device_name);
+ UpdatePrintSettings(std::move(dic));
+}
+
void PrintJobWorker::StartPrinting(PrintedDocument* new_document) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
diff --git a/chrome/browser/printing/print_job_worker.h b/chrome/browser/printing/print_job_worker.h
index 182f7563e0c7..eed2230627d6 100644
--- a/chrome/browser/printing/print_job_worker.h
+++ b/chrome/browser/printing/print_job_worker.h
@@ -54,7 +54,8 @@ class PrintJobWorker {
bool has_selection,
MarginType margin_type,
bool is_scripted,
- bool is_modifiable);
+ bool is_modifiable,
+ const base::string16& device_name);
// Set the new print settings from a dictionary value.
void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings);
@@ -155,6 +156,9 @@ class PrintJobWorker {
// systems.
void UseDefaultSettings();
+ // set the printer name
+ void InitWithDeviceName(const base::string16& device_name);
+
// Printing context delegate.
const std::unique_ptr<PrintingContext::Delegate> printing_context_delegate_;
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc
index e1613a9b52ad..db62078f2c08 100644
--- a/chrome/browser/printing/print_preview_message_handler.cc
+++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -57,7 +57,7 @@ void StopWorker(int document_cookie) {
base::BindOnce(&PrinterQuery::StopWorker, printer_query));
}
}
-
+#if 0
scoped_refptr<base::RefCountedMemory> GetDataFromHandle(
base::SharedMemoryHandle handle,
uint32_t data_size) {
@@ -70,6 +70,7 @@ scoped_refptr<base::RefCountedMemory> GetDataFromHandle(
return base::MakeRefCounted<base::RefCountedSharedMemory>(
std::move(shared_buf), data_size);
}
+#endif
} // namespace
@@ -81,7 +82,7 @@ PrintPreviewMessageHandler::PrintPreviewMessageHandler(
PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {
}
-
+#if 0
WebContents* PrintPreviewMessageHandler::GetPrintPreviewDialog() {
PrintPreviewDialogController* dialog_controller =
PrintPreviewDialogController::GetInstance();
@@ -159,6 +160,7 @@ void PrintPreviewMessageHandler::OnDidPreviewPage(
GetDataFromHandle(content.metafile_data_handle, content.data_size));
}
}
+#endif
void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
content::RenderFrameHost* render_frame_host,
@@ -171,7 +173,8 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
NOTREACHED();
return;
}
-
+}
+#if 0
PrintPreviewUI* print_preview_ui = GetPrintPreviewUI(ids.ui_id);
if (!print_preview_ui)
return;
@@ -193,12 +196,13 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
GetDataFromHandle(content.metafile_data_handle, content.data_size));
}
}
-
+#endif
void PrintPreviewMessageHandler::OnPrintPreviewFailed(
int document_cookie,
const PrintHostMsg_PreviewIds& ids) {
StopWorker(document_cookie);
-
+}
+#if 0
PrintPreviewUI* print_preview_ui = GetPrintPreviewUI(ids.ui_id);
if (!print_preview_ui)
return;
@@ -318,15 +322,19 @@ void PrintPreviewMessageHandler::OnCompositePdfDocumentDone(
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region));
}
+#endif
+
bool PrintPreviewMessageHandler::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintPreviewMessageHandler, message,
render_frame_host)
+#if 0
IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
OnRequestPrintPreview)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage)
+#endif
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
OnMetafileReadyForPrinting)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -336,10 +344,13 @@ bool PrintPreviewMessageHandler::OnMessageReceived(
handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
+#if 0
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
OnDidGetPreviewPageCount)
+#endif
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed,
OnPrintPreviewFailed)
+#if 0
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDefaultPageLayout,
OnDidGetDefaultPageLayout)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewCancelled,
@@ -348,6 +359,7 @@ bool PrintPreviewMessageHandler::OnMessageReceived(
OnInvalidPrinterSettings)
IPC_MESSAGE_HANDLER(PrintHostMsg_SetOptionsFromDocument,
OnSetOptionsFromDocument)
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
diff --git a/chrome/browser/printing/print_preview_message_handler.h b/chrome/browser/printing/print_preview_message_handler.h
index 6356792f29e8..5592de3c097f 100644
--- a/chrome/browser/printing/print_preview_message_handler.h
+++ b/chrome/browser/printing/print_preview_message_handler.h
@@ -37,8 +37,7 @@ struct PageSizeMargins;
// Manages the print preview handling for a WebContents.
class PrintPreviewMessageHandler
- : public content::WebContentsObserver,
- public content::WebContentsUserData<PrintPreviewMessageHandler> {
+ : public content::WebContentsObserver {
public:
~PrintPreviewMessageHandler() override;
@@ -46,10 +45,11 @@ class PrintPreviewMessageHandler
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* render_frame_host) override;
- private:
+ protected:
explicit PrintPreviewMessageHandler(content::WebContents* web_contents);
friend class content::WebContentsUserData<PrintPreviewMessageHandler>;
+#if 0
// Gets the print preview dialog associated with the WebContents being
// observed.
content::WebContents* GetPrintPreviewDialog();
@@ -72,12 +72,14 @@ class PrintPreviewMessageHandler
void OnDidPreviewPage(content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewPage_Params& params,
const PrintHostMsg_PreviewIds& ids);
- void OnMetafileReadyForPrinting(
+#endif
+ virtual void OnMetafileReadyForPrinting(
content::RenderFrameHost* render_frame_host,
const PrintHostMsg_DidPreviewDocument_Params& params,
const PrintHostMsg_PreviewIds& ids);
- void OnPrintPreviewFailed(int document_cookie,
- const PrintHostMsg_PreviewIds& ids);
+ virtual void OnPrintPreviewFailed(int document_cookie,
+ const PrintHostMsg_PreviewIds& ids);
+#if 0
void OnPrintPreviewCancelled(int document_cookie,
const PrintHostMsg_PreviewIds& ids);
void OnInvalidPrinterSettings(int document_cookie,
@@ -104,6 +106,7 @@ class PrintPreviewMessageHandler
const PrintHostMsg_PreviewIds& ids,
mojom::PdfCompositor::Status status,
base::ReadOnlySharedMemoryRegion region);
+#endif
base::WeakPtrFactory<PrintPreviewMessageHandler> weak_ptr_factory_;
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 9b0c15b3c501..388994072186 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -30,7 +30,7 @@
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/browser/ui/webui/print_preview/printer_handler.h"
#include "chrome/common/pref_names.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "components/prefs/pref_service.h"
#include "components/printing/browser/print_composite_client.h"
#include "components/printing/browser/print_manager_utils.h"
@@ -67,6 +67,8 @@ using PrintSettingsCallback =
base::OnceCallback<void(scoped_refptr<PrinterQuery>)>;
void ShowWarningMessageBox(const base::string16& message) {
+ LOG(ERROR) << "Invalid printer settings " << message;
+#if 0
// Runs always on the UI thread.
static bool is_dialog_shown = false;
if (is_dialog_shown)
@@ -75,6 +77,7 @@ void ShowWarningMessageBox(const base::string16& message) {
base::AutoReset<bool> auto_reset(&is_dialog_shown, true);
chrome::ShowWarningMessageBox(nullptr, base::string16(), message);
+#endif
}
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -112,12 +115,14 @@ PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents)
queue_(g_browser_process->print_job_manager()->queue()),
weak_ptr_factory_(this) {
DCHECK(queue_);
+#if 0
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
printing_enabled_.Init(
prefs::kPrintingEnabled, profile->GetPrefs(),
base::Bind(&PrintViewManagerBase::UpdatePrintingEnabled,
weak_ptr_factory_.GetWeakPtr()));
+#endif
}
PrintViewManagerBase::~PrintViewManagerBase() {
@@ -125,12 +130,16 @@ PrintViewManagerBase::~PrintViewManagerBase() {
DisconnectFromCurrentPrintJob();
}
-bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh) {
+bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
+ bool silent,
+ bool print_background,
+ const base::string16& device_name) {
DisconnectFromCurrentPrintJob();
SetPrintingRFH(rfh);
int32_t id = rfh->GetRoutingID();
- return PrintNowInternal(rfh, std::make_unique<PrintMsg_PrintPages>(id));
+ return PrintNowInternal(rfh, std::make_unique<PrintMsg_PrintPages>(
+ id, silent, print_background, device_name));
}
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -249,7 +258,7 @@ void PrintViewManagerBase::UpdatePrintingEnabled() {
// The Unretained() is safe because ForEachFrame() is synchronous.
web_contents()->ForEachFrame(base::BindRepeating(
&PrintViewManagerBase::SendPrintingEnabled, base::Unretained(this),
- printing_enabled_.GetValue()));
+ true));
}
void PrintViewManagerBase::NavigationStopped() {
@@ -341,8 +350,10 @@ void PrintViewManagerBase::OnDidPrintDocument(
void PrintViewManagerBase::OnPrintingFailed(int cookie) {
PrintManager::OnPrintingFailed(cookie);
+#if 0
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
ShowPrintErrorDialog();
+#endif
#endif
ReleasePrinterQuery();
@@ -592,6 +603,10 @@ void PrintViewManagerBase::ReleasePrintJob() {
content::RenderFrameHost* rfh = printing_rfh_;
printing_rfh_ = nullptr;
+ if (!callback.is_null()) {
+ callback.Run(printing_succeeded_ && print_job_);
+ }
+
if (!print_job_)
return;
diff --git a/chrome/browser/printing/print_view_manager_base.h b/chrome/browser/printing/print_view_manager_base.h
index fe0e0b5b065c..6670fc8abd2d 100644
--- a/chrome/browser/printing/print_view_manager_base.h
+++ b/chrome/browser/printing/print_view_manager_base.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/scoped_refptr.h"
@@ -47,7 +48,10 @@ class PrintViewManagerBase : public content::NotificationObserver,
// Prints the current document immediately. Since the rendering is
// asynchronous, the actual printing will not be completed on the return of
// this function. Returns false if printing is impossible at the moment.
- virtual bool PrintNow(content::RenderFrameHost* rfh);
+ virtual bool PrintNow(content::RenderFrameHost* rfh,
+ bool silent,
+ bool print_background,
+ const base::string16& device_name);
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Prints the document in |print_data| with settings specified in
@@ -72,6 +76,8 @@ class PrintViewManagerBase : public content::NotificationObserver,
base::string16 RenderSourceName();
+ void SetCallback(const base::Callback<void(bool)>& cb) { callback = cb; };
+
protected:
explicit PrintViewManagerBase(content::WebContents* web_contents);
@@ -208,6 +214,8 @@ class PrintViewManagerBase : public content::NotificationObserver,
scoped_refptr<PrintQueriesQueue> queue_;
+ base::Callback<void(bool)> callback;
+
base::WeakPtrFactory<PrintViewManagerBase> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBase);
diff --git a/chrome/browser/printing/print_view_manager_common.cc b/chrome/browser/printing/print_view_manager_common.cc
index 3d36b0b972b6..3400f4a3470b 100644
--- a/chrome/browser/printing/print_view_manager_common.cc
+++ b/chrome/browser/printing/print_view_manager_common.cc
@@ -11,12 +11,12 @@
#include "printing/buildflags/buildflags.h"
#include "url/gurl.h"
-#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if 0
#include "components/guest_view/browser/guest_view_manager.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+#if 0
#include "chrome/browser/printing/print_view_manager.h"
#else
#include "chrome/browser/printing/print_view_manager_basic.h"
@@ -25,7 +25,7 @@
namespace printing {
namespace {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if 0
// Stores |guest_contents| in |result| and returns true if |guest_contents| is a
// full page MimeHandlerViewGuest plugin. Otherwise, returns false.
bool StoreFullPagePlugin(content::WebContents** result,
@@ -43,7 +43,7 @@ bool StoreFullPagePlugin(content::WebContents** result,
// If we have a single full-page embedded mime handler view guest, print the
// guest's WebContents instead.
content::WebContents* GetWebContentsToUse(content::WebContents* contents) {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if 0
guest_view::GuestViewManager* guest_view_manager =
guest_view::GuestViewManager::FromBrowserContext(
contents->GetBrowserContext());
@@ -69,7 +69,8 @@ content::RenderFrameHost* GetRenderFrameHostToUse(
void StartPrint(content::WebContents* contents,
bool print_preview_disabled,
bool has_selection) {
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+
+#if 0
using PrintViewManagerImpl = PrintViewManager;
#else
using PrintViewManagerImpl = PrintViewManagerBasic;
@@ -85,18 +86,20 @@ void StartPrint(content::WebContents* contents,
GetRenderFrameHostToUse(contents, contents_to_use);
if (!rfh_to_use)
return;
-
+#if 0
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
if (!print_preview_disabled) {
print_view_manager->PrintPreviewNow(rfh_to_use, has_selection);
return;
}
#endif // ENABLE_PRINT_PREVIEW
+#endif
- print_view_manager->PrintNow(rfh_to_use);
+ print_view_manager->PrintNow(rfh_to_use, false, true, base::string16());
}
void StartBasicPrint(content::WebContents* contents) {
+#if 0
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
content::WebContents* contents_to_use = GetWebContentsToUse(contents);
PrintViewManager* print_view_manager =
@@ -111,6 +114,7 @@ void StartBasicPrint(content::WebContents* contents) {
print_view_manager->BasicPrint(rfh_to_use);
#endif // ENABLE_PRINT_PREVIEW
+#endif
}
content::RenderFrameHost* GetFrameToPrint(content::WebContents* contents) {
diff --git a/chrome/browser/printing/printer_query.cc b/chrome/browser/printing/printer_query.cc
index cc2368731367..159ec3a04502 100644
--- a/chrome/browser/printing/printer_query.cc
+++ b/chrome/browser/printing/printer_query.cc
@@ -94,7 +94,31 @@ void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
base::BindOnce(&PrintJobWorker::GetSettings,
base::Unretained(worker_.get()),
is_print_dialog_box_shown_, expected_page_count,
- has_selection, margin_type, is_scripted, is_modifiable));
+ has_selection, margin_type, is_scripted, is_modifiable,
+ base::string16()));
+}
+
+void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
+ int expected_page_count,
+ bool has_selection,
+ MarginType margin_type,
+ bool is_scripted,
+ bool is_modifiable,
+ const base::string16& device_name,
+ base::OnceClosure callback) {
+ DCHECK(RunsTasksInCurrentSequence());
+ DCHECK(!is_print_dialog_box_shown_);
+
+ StartWorker(std::move(callback));
+
+ is_print_dialog_box_shown_ = false;
+ worker_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&PrintJobWorker::GetSettings,
+ base::Unretained(worker_.get()),
+ is_print_dialog_box_shown_, expected_page_count,
+ has_selection, margin_type, is_scripted, is_modifiable,
+ device_name));
}
void PrinterQuery::SetSettings(
diff --git a/chrome/browser/printing/printer_query.h b/chrome/browser/printing/printer_query.h
index 64db84f9f853..0e12adfe7957 100644
--- a/chrome/browser/printing/printer_query.h
+++ b/chrome/browser/printing/printer_query.h
@@ -59,6 +59,15 @@ class PrinterQuery : public base::RefCountedThreadSafe<PrinterQuery> {
bool is_modifiable,
base::OnceClosure callback);
+ void GetSettings(GetSettingsAskParam ask_user_for_settings,
+ int expected_page_count,
+ bool has_selection,
+ MarginType margin_type,
+ bool is_scripted,
+ bool is_modifiable,
+ const base::string16& device_name,
+ base::OnceClosure callback);
+
// Updates the current settings with |new_settings| dictionary values.
virtual void SetSettings(std::unique_ptr<base::DictionaryValue> new_settings,
base::OnceClosure callback);
diff --git a/chrome/browser/printing/printing_message_filter.cc b/chrome/browser/printing/printing_message_filter.cc
index 54866fdcdb64..40d6bd62706c 100644
--- a/chrome/browser/printing/printing_message_filter.cc
+++ b/chrome/browser/printing/printing_message_filter.cc
@@ -94,12 +94,12 @@ PrintViewManager* GetPrintViewManager(int render_process_id,
} // namespace
-PrintingMessageFilter::PrintingMessageFilter(int render_process_id,
- Profile* profile)
+PrintingMessageFilter::PrintingMessageFilter(int render_process_id)
: BrowserMessageFilter(PrintMsgStart),
render_process_id_(render_process_id),
queue_(g_browser_process->print_job_manager()->queue()) {
DCHECK(queue_.get());
+#if 0
printing_shutdown_notifier_ =
PrintingMessageFilterShutdownNotifierFactory::GetInstance()
->Get(profile)
@@ -108,6 +108,7 @@ PrintingMessageFilter::PrintingMessageFilter(int render_process_id,
is_printing_enabled_.Init(prefs::kPrintingEnabled, profile->GetPrefs());
is_printing_enabled_.MoveToThread(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+#endif
}
PrintingMessageFilter::~PrintingMessageFilter() {
@@ -116,7 +117,9 @@ PrintingMessageFilter::~PrintingMessageFilter() {
void PrintingMessageFilter::ShutdownOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+#if 0
is_printing_enabled_.Destroy();
+#endif
printing_shutdown_notifier_.reset();
}
@@ -145,6 +148,8 @@ bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
#endif
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_InitSettingWithDeviceName,
+ OnInitSettingWithDeviceName)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
OnUpdatePrintSettings)
@@ -188,7 +193,7 @@ void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_frame_id,
void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
scoped_refptr<PrinterQuery> printer_query;
- if (!is_printing_enabled_.GetValue()) {
+ if (false) {
// Reply with NULL query.
OnGetDefaultPrintSettingsReply(printer_query, reply_msg);
return;
@@ -208,6 +213,26 @@ void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
printer_query, reply_msg));
}
+void PrintingMessageFilter::OnInitSettingWithDeviceName(
+ const base::string16& device_name,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ scoped_refptr<PrinterQuery> printer_query;
+ printer_query = queue_->PopPrinterQuery(0);
+ if (!printer_query.get()) {
+ printer_query =
+ queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
+ }
+
+ // Loads default settings. This is asynchronous, only the IPC message sender
+ // will hang until the settings are retrieved.
+ printer_query->GetSettings(
+ PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, DEFAULT_MARGINS,
+ true, true, device_name,
+ base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, this,
+ printer_query, reply_msg));
+}
+
void PrintingMessageFilter::OnGetDefaultPrintSettingsReply(
scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg) {
@@ -301,7 +326,7 @@ void PrintingMessageFilter::OnUpdatePrintSettings(
std::unique_ptr<base::DictionaryValue> new_settings(job_settings.DeepCopy());
scoped_refptr<PrinterQuery> printer_query;
- if (!is_printing_enabled_.GetValue()) {
+ if (false) {
// Reply with NULL query.
OnUpdatePrintSettingsReply(printer_query, reply_msg);
return;
@@ -361,10 +386,13 @@ void PrintingMessageFilter::OnUpdatePrintSettingsReply(
}
}
+
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void PrintingMessageFilter::OnCheckForCancel(const PrintHostMsg_PreviewIds& ids,
bool* cancel) {
+#if 0
PrintPreviewUI::GetCurrentPrintPreviewStatus(ids, cancel);
+#endif
}
#endif
diff --git a/chrome/browser/printing/printing_message_filter.h b/chrome/browser/printing/printing_message_filter.h
index a881a853bfb0..46ebeede1955 100644
--- a/chrome/browser/printing/printing_message_filter.h
+++ b/chrome/browser/printing/printing_message_filter.h
@@ -38,7 +38,7 @@ class PrinterQuery;
// renderer process on the IPC thread.
class PrintingMessageFilter : public content::BrowserMessageFilter {
public:
- PrintingMessageFilter(int render_process_id, Profile* profile);
+ PrintingMessageFilter(int render_process_id);
// content::BrowserMessageFilter methods.
void OverrideThreadForMessage(const IPC::Message& message,
@@ -73,6 +73,11 @@ class PrintingMessageFilter : public content::BrowserMessageFilter {
// Get the default print setting.
void OnGetDefaultPrintSettings(IPC::Message* reply_msg);
+
+ // Set deviceName
+ void OnInitSettingWithDeviceName(const base::string16& device_name,
+ IPC::Message* reply_msg);
+
void OnGetDefaultPrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg);
diff --git a/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc b/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc
index 38fd116aa096..62fcfaa00084 100644
--- a/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc
+++ b/chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc
@@ -19,7 +19,7 @@
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
-#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if 0
#include "chrome/common/extensions/extension_constants.h"
#include "extensions/common/constants.h"
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
@@ -45,7 +45,7 @@ bool ChromePrintRenderFrameHelperDelegate::CancelPrerender(
// Return the PDF object element if |frame| is the out of process PDF extension.
blink::WebElement ChromePrintRenderFrameHelperDelegate::GetPdfElement(
blink::WebLocalFrame* frame) {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if 0
GURL url = frame->GetDocument().Url();
bool inside_print_preview = url.GetOrigin() == chrome::kChromeUIPrintURL;
bool inside_pdf_extension =
@@ -71,7 +71,7 @@ bool ChromePrintRenderFrameHelperDelegate::IsPrintPreviewEnabled() {
bool ChromePrintRenderFrameHelperDelegate::OverridePrint(
blink::WebLocalFrame* frame) {
-#if BUILDFLAG(ENABLE_EXTENSIONS)
+#if 0
if (!frame->GetDocument().IsPluginDocument())
return false;
diff --git a/components/printing/common/print_messages.h b/components/printing/common/print_messages.h
index d29bb6aedecd..bb0bd7bfa494 100644
--- a/components/printing/common/print_messages.h
+++ b/components/printing/common/print_messages.h
@@ -367,7 +367,10 @@ IPC_MESSAGE_ROUTED0(PrintMsg_PrintNodeUnderContextMenu)
#if BUILDFLAG(ENABLE_PRINTING)
// Tells the RenderFrame to switch the CSS to print media type, renders every
// requested pages and switch back the CSS to display media type.
-IPC_MESSAGE_ROUTED0(PrintMsg_PrintPages)
+IPC_MESSAGE_ROUTED3(PrintMsg_PrintPages,
+ bool /* silent print */,
+ bool /* print page's background */,
+ base::string16 /* device name*/)
// Like PrintMsg_PrintPages, but using the print preview document's frame/node.
IPC_MESSAGE_ROUTED0(PrintMsg_PrintForSystemDialog)
@@ -425,6 +428,11 @@ IPC_MESSAGE_ROUTED2(PrintHostMsg_DidPrintFrameContent,
IPC_SYNC_MESSAGE_ROUTED0_1(PrintHostMsg_GetDefaultPrintSettings,
PrintMsg_Print_Params /* default_settings */)
+// you can set the printer
+IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_InitSettingWithDeviceName,
+ base::string16, /* device name */
+ PrintMsg_Print_Params /* default_settings */)
+
// The renderer wants to update the current print settings with new
// |job_settings|.
IPC_SYNC_MESSAGE_ROUTED2_2(PrintHostMsg_UpdatePrintSettings,
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index c7ea5cf76aa6..1c3177e679ff 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1093,7 +1093,9 @@ void PrintRenderFrameHelper::OnDestruct() {
delete this;
}
-void PrintRenderFrameHelper::OnPrintPages() {
+void PrintRenderFrameHelper::OnPrintPages(bool silent,
+ bool print_background,
+ const base::string16& device_name) {
if (ipc_nesting_level_ > 1)
return;
@@ -1106,7 +1108,7 @@ void PrintRenderFrameHelper::OnPrintPages() {
// If we are printing a PDF extension frame, find the plugin node and print
// that instead.
auto plugin = delegate_->GetPdfElement(frame);
- Print(frame, plugin, false /* is_scripted? */);
+ Print(frame, plugin, false, silent, print_background, device_name);
if (weak_this)
frame->DispatchAfterPrintEvent();
// WARNING: |this| may be gone at this point. Do not do any more work here and
@@ -1158,6 +1160,8 @@ void PrintRenderFrameHelper::OnPrintPreview(
if (ipc_nesting_level_ > 1)
return;
+ blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+ print_preview_context_.InitWithFrame(frame);
print_preview_context_.OnPrintPreview();
UMA_HISTOGRAM_ENUMERATION("PrintPreview.PreviewEvent",
@@ -1552,7 +1556,10 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
const blink::WebNode& node,
- bool is_scripted) {
+ bool is_scripted,
+ bool silent,
+ bool print_background,
+ const base::string16& device_name) {
// If still not finished with earlier print request simply ignore.
if (prep_frame_view_)
return;
@@ -1560,7 +1567,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
FrameReference frame_ref(frame);
int expected_page_count = 0;
- if (!CalculateNumberOfPages(frame, node, &expected_page_count)) {
+ if (!CalculateNumberOfPages(frame, node, &expected_page_count, device_name)) {
DidFinishPrinting(FAIL_PRINT_INIT);
return; // Failed to init print page settings.
}
@@ -1580,8 +1587,9 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
PrintMsg_PrintPages_Params print_settings;
auto self = weak_ptr_factory_.GetWeakPtr();
- GetPrintSettingsFromUser(frame_ref.GetFrame(), node, expected_page_count,
- is_scripted, &print_settings);
+ if (!silent)
+ GetPrintSettingsFromUser(frame_ref.GetFrame(), node, expected_page_count,
+ is_scripted, &print_settings);
// Check if |this| is still valid.
if (!self)
return;
@@ -1591,6 +1599,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
? blink::kWebPrintScalingOptionSourceSize
: scaling_option;
SetPrintPagesParams(print_settings);
+ print_settings.params.should_print_backgrounds = print_background;
if (print_settings.params.dpi.IsEmpty() ||
!print_settings.params.document_cookie) {
DidFinishPrinting(OK); // Release resources and fail silently on failure.
@@ -1600,7 +1609,6 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
// Render Pages for printing.
if (!RenderPagesForPrint(frame_ref.GetFrame(), node)) {
- LOG(ERROR) << "RenderPagesForPrint failed";
DidFinishPrinting(FAIL_PRINT);
}
scripting_throttler_.Reset();
@@ -1778,10 +1786,17 @@ std::vector<int> PrintRenderFrameHelper::GetPrintedPages(
return printed_pages;
}
-bool PrintRenderFrameHelper::InitPrintSettings(bool fit_to_paper_size) {
+bool PrintRenderFrameHelper::InitPrintSettings(
+ bool fit_to_paper_size,
+ const base::string16& device_name) {
PrintMsg_PrintPages_Params settings;
+ if (device_name.empty()) {
Send(new PrintHostMsg_GetDefaultPrintSettings(routing_id(),
&settings.params));
+ } else {
+ Send(new PrintHostMsg_InitSettingWithDeviceName(routing_id(), device_name,
+ &settings.params));
+ }
// Check if the printer returned any settings, if the settings is empty, we
// can safely assume there are no printer drivers configured. So we safely
// terminate.
@@ -1803,10 +1818,11 @@ bool PrintRenderFrameHelper::InitPrintSettings(bool fit_to_paper_size) {
bool PrintRenderFrameHelper::CalculateNumberOfPages(blink::WebLocalFrame* frame,
const blink::WebNode& node,
- int* number_of_pages) {
+ int* number_of_pages,
+ const base::string16& device_name) {
DCHECK(frame);
bool fit_to_paper_size = !(PrintingNodeOrPdfFrame(frame, node));
- if (!InitPrintSettings(fit_to_paper_size)) {
+ if (!InitPrintSettings(fit_to_paper_size, device_name)) {
notify_browser_of_print_failure_ = false;
Send(new PrintHostMsg_ShowInvalidPrinterSettingsError(routing_id()));
return false;
@@ -1885,11 +1901,13 @@ bool PrintRenderFrameHelper::UpdatePrintSettings(
return false;
}
+#if 0
if (!job_settings->GetInteger(kPreviewUIID, &settings.params.preview_ui_id)) {
NOTREACHED();
print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING);
return false;
}
+#endif
// Validate expected print preview settings.
if (!job_settings->GetInteger(kPreviewRequestID,
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h
index 6e2d7e1467b7..0e6e8ea770f5 100644
--- a/components/printing/renderer/print_render_frame_helper.h
+++ b/components/printing/renderer/print_render_frame_helper.h
@@ -186,7 +186,9 @@ class PrintRenderFrameHelper
bool OnMessageReceived(const IPC::Message& message) override;
// Message handlers ---------------------------------------------------------
- void OnPrintPages();
+ void OnPrintPages(bool silent,
+ bool print_background,
+ const base::string16& device_name);
void OnPrintForSystemDialog();
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void OnInitiatePrintPreview(bool has_selection);
@@ -238,7 +240,10 @@ class PrintRenderFrameHelper
// WARNING: |this| may be gone after this method returns.
void Print(blink::WebLocalFrame* frame,
const blink::WebNode& node,
- bool is_scripted);
+ bool is_scripted,
+ bool silent = false,
+ bool print_background = false,
+ const base::string16& device_name = base::string16());
// Notification when printing is done - signal tear-down/free resources.
void DidFinishPrinting(PrintingResult result);
@@ -247,12 +252,15 @@ class PrintRenderFrameHelper
// Initialize print page settings with default settings.
// Used only for native printing workflow.
- bool InitPrintSettings(bool fit_to_paper_size);
+ bool InitPrintSettings(bool fit_to_paper_size,
+ const base::string16& device_name = base::string16());
// Calculate number of pages in source document.
- bool CalculateNumberOfPages(blink::WebLocalFrame* frame,
- const blink::WebNode& node,
- int* number_of_pages);
+ bool CalculateNumberOfPages(
+ blink::WebLocalFrame* frame,
+ const blink::WebNode& node,
+ int* number_of_pages,
+ const base::string16& device_name = base::string16());
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Set options for print preset from source PDF document.
diff --git a/printing/print_settings_conversion.cc b/printing/print_settings_conversion.cc
index a4c9f49d65e0..b26eb4186880 100644
--- a/printing/print_settings_conversion.cc
+++ b/printing/print_settings_conversion.cc
@@ -42,6 +42,19 @@ void GetCustomMarginsFromJobSettings(const base::DictionaryValue& settings,
}
}
+void SetCustomMarginsToJobSettings(const PageSizeMargins& page_size_margins,
+ base::DictionaryValue* settings) {
+ std::unique_ptr<base::DictionaryValue> custom_margins(
+ new base::DictionaryValue());
+ custom_margins->SetDouble(kSettingMarginTop, page_size_margins.margin_top);
+ custom_margins->SetDouble(kSettingMarginBottom,
+ page_size_margins.margin_bottom);
+ custom_margins->SetDouble(kSettingMarginLeft, page_size_margins.margin_left);
+ custom_margins->SetDouble(kSettingMarginRight,
+ page_size_margins.margin_right);
+ settings->Set(kSettingMarginsCustom, std::move(custom_margins));
+}
+
void SetMarginsToJobSettings(const std::string& json_path,
const PageMargins& margins,
base::DictionaryValue* job_settings) {
@@ -224,6 +237,72 @@ bool PrintSettingsFromJobSettings(const base::DictionaryValue& job_settings,
return true;
}
+void PrintSettingsToJobSettings(const PrintSettings& settings,
+ base::DictionaryValue* job_settings) {
+ // header footer
+ job_settings->SetBoolean(kSettingHeaderFooterEnabled,
+ settings.display_header_footer());
+ job_settings->SetString(kSettingHeaderFooterTitle, settings.title());
+ job_settings->SetString(kSettingHeaderFooterURL, settings.url());
+
+ // bg
+ job_settings->SetBoolean(kSettingShouldPrintBackgrounds,
+ settings.should_print_backgrounds());
+ job_settings->SetBoolean(kSettingShouldPrintSelectionOnly,
+ settings.selection_only());
+
+ // margin
+ auto margin_type = settings.margin_type();
+ job_settings->SetInteger(kSettingMarginsType, settings.margin_type());
+ if (margin_type == CUSTOM_MARGINS) {
+ const auto& margins_in_points =
+ settings.requested_custom_margins_in_points();
+
+ PageSizeMargins page_size_margins;
+
+ page_size_margins.margin_top = margins_in_points.top;
+ page_size_margins.margin_bottom = margins_in_points.bottom;
+ page_size_margins.margin_left = margins_in_points.left;
+ page_size_margins.margin_right = margins_in_points.right;
+ SetCustomMarginsToJobSettings(page_size_margins, job_settings);
+ }
+ job_settings->SetInteger(kSettingPreviewPageCount, 1);
+
+ // range
+
+ if (!settings.ranges().empty()) {
+ auto page_range_array = std::make_unique<base::ListValue>();
+ job_settings->Set(kSettingPageRange, std::move(page_range_array));
+ for (size_t i = 0; i < settings.ranges().size(); ++i) {
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1);
+ dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1);
+ page_range_array->Append(std::move(dict));
+ }
+ }
+
+ job_settings->SetBoolean(kSettingCollate, settings.collate());
+ job_settings->SetInteger(kSettingCopies, 1);
+ job_settings->SetInteger(kSettingColor, settings.color());
+ job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode());
+ job_settings->SetBoolean(kSettingLandscape, settings.landscape());
+ job_settings->SetString(kSettingDeviceName, settings.device_name());
+ job_settings->SetInteger(kSettingScaleFactor, 100);
+ job_settings->SetBoolean("rasterizePDF", false);
+
+ job_settings->SetInteger("dpi", settings.dpi());
+ job_settings->SetInteger("dpiHorizontal", 72);
+ job_settings->SetInteger("dpiVertical", 72);
+
+ job_settings->SetBoolean(kSettingPrintToPDF, false);
+ job_settings->SetBoolean(kSettingCloudPrintDialog, false);
+ job_settings->SetBoolean(kSettingPrintWithPrivet, false);
+ job_settings->SetBoolean(kSettingPrintWithExtension, false);
+
+ job_settings->SetBoolean(kSettingShowSystemDialog, false);
+ job_settings->SetInteger(kSettingPreviewPageCount, 1);
+}
+
void PrintSettingsToJobSettingsDebug(const PrintSettings& settings,
base::DictionaryValue* job_settings) {
job_settings->SetBoolean(kSettingHeaderFooterEnabled,
diff --git a/printing/print_settings_conversion.h b/printing/print_settings_conversion.h
index 283c0ff81954..231873a45644 100644
--- a/printing/print_settings_conversion.h
+++ b/printing/print_settings_conversion.h
@@ -21,6 +21,10 @@ PRINTING_EXPORT bool PrintSettingsFromJobSettings(
const base::DictionaryValue& job_settings,
PrintSettings* print_settings);
+PRINTING_EXPORT void PrintSettingsToJobSettings(
+ const PrintSettings& settings,
+ base::DictionaryValue* job_settings);
+
// Use for debug only, because output is not completely consistent with format
// of |PrintSettingsFromJobSettings| input.
void PrintSettingsToJobSettingsDebug(const PrintSettings& settings,