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:
parent
c806c465fa
commit
a82bcc7e3c
53 changed files with 1398 additions and 7358 deletions
73
BUILD.gn
73
BUILD.gn
|
@ -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") {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
134
atom/browser/atom_print_preview_message_handler.cc
Normal file
134
atom/browser/atom_print_preview_message_handler.cc
Normal 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
|
52
atom/browser/atom_print_preview_message_handler.h
Normal file
52
atom/browser/atom_print_preview_message_handler.h
Normal 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_
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -10,4 +10,6 @@ enable_cdm_host_verification = false
|
|||
proprietary_codecs = true
|
||||
ffmpeg_branding = "Chrome"
|
||||
|
||||
enable_basic_printing = true
|
||||
|
||||
is_cfi = false
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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__
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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(), ¶ms);
|
||||
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(), ¶ms.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(), ¶ms.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
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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
|
|
@ -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>();
|
||||
}
|
|
@ -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
|
@ -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_
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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"><br></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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
"service_manager:connector": {
|
||||
"requires": {
|
||||
"device": [ "device:geolocation_control" ],
|
||||
"proxy_resolver": [ "factory" ]
|
||||
"proxy_resolver": [ "factory" ],
|
||||
"chrome_printing": [ "converter" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
989
patches/common/chromium/printing.patch
Normal file
989
patches/common/chromium/printing.patch
Normal 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,
|
Loading…
Reference in a new issue