[go: nahoru, domu]

blob: 2b6202d5358114ab21b1b04862b5ef7479d41366 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "printing/test_printing_context.h"
#include <memory>
#include <utility>
#include "base/check.h"
#include "base/containers/flat_map.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "printing/backend/print_backend.h"
#include "printing/buildflags/buildflags.h"
#include "printing/mojom/print.mojom.h"
#include "printing/print_settings.h"
#include "printing/printing_context.h"
#include "printing/units.h"
#include "ui/gfx/geometry/size.h"
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
#include "printing/printing_features.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "printing/printed_page_win.h"
#endif
namespace printing {
TestPrintingContextDelegate::TestPrintingContextDelegate() = default;
TestPrintingContextDelegate::~TestPrintingContextDelegate() = default;
gfx::NativeView TestPrintingContextDelegate::GetParentView() {
return gfx::NativeView();
}
std::string TestPrintingContextDelegate::GetAppLocale() {
return std::string();
}
TestPrintingContext::TestPrintingContext(Delegate* delegate,
ProcessBehavior process_behavior)
: PrintingContext(delegate, process_behavior) {}
TestPrintingContext::~TestPrintingContext() = default;
void TestPrintingContext::SetDeviceSettings(
const std::string& device_name,
std::unique_ptr<PrintSettings> settings) {
device_settings_.emplace(device_name, std::move(settings));
}
void TestPrintingContext::SetNewDocumentJobId(int job_id) {
new_document_job_id_ = job_id;
}
void TestPrintingContext::SetUserSettings(const PrintSettings& settings) {
user_settings_ = settings;
}
void TestPrintingContext::AskUserForSettings(int max_pages,
bool has_selection,
bool is_scripted,
PrintSettingsCallback callback) {
std::move(callback).Run(
AskUserForSettingsImpl(max_pages, has_selection, is_scripted));
}
mojom::ResultCode TestPrintingContext::AskUserForSettingsImpl(
int max_pages,
bool has_selection,
bool is_scripted) {
// Do not actually ask the user with a dialog, just pretend like user
// made some kind of interaction.
if (ask_user_for_settings_cancel_) {
// Pretend the user hit the Cancel button.
return mojom::ResultCode::kCanceled;
}
// Allow for test-specific user modifications.
if (user_settings_.has_value()) {
*settings_ = *user_settings_;
} else {
// Pretend the user selected the default printer and used the default
// settings for it.
scoped_refptr<PrintBackend> print_backend =
PrintBackend::CreateInstance(/*locale=*/std::string());
std::string printer_name;
if (print_backend->GetDefaultPrinterName(printer_name) !=
mojom::ResultCode::kSuccess) {
return mojom::ResultCode::kFailed;
}
auto found = device_settings_.find(printer_name);
if (found == device_settings_.end()) {
return mojom::ResultCode::kFailed;
}
settings_ = std::make_unique<PrintSettings>(*found->second);
}
// Capture a snapshot, simluating changes made to platform device context.
applied_settings_ = *settings_;
return mojom::ResultCode::kSuccess;
}
mojom::ResultCode TestPrintingContext::UseDefaultSettings() {
if (use_default_settings_fails_)
return mojom::ResultCode::kFailed;
scoped_refptr<PrintBackend> print_backend =
PrintBackend::CreateInstance(/*locale=*/std::string());
std::string printer_name;
mojom::ResultCode result = print_backend->GetDefaultPrinterName(printer_name);
if (result != mojom::ResultCode::kSuccess)
return result;
auto found = device_settings_.find(printer_name);
if (found == device_settings_.end())
return mojom::ResultCode::kFailed;
settings_ = std::make_unique<PrintSettings>(*found->second);
// Capture a snapshot, simluating changes made to platform device context.
applied_settings_ = *settings_;
return mojom::ResultCode::kSuccess;
}
gfx::Size TestPrintingContext::GetPdfPaperSizeDeviceUnits() {
// Default to A4 paper size, which is an alternative to Letter size that is
// often used as the fallback size for some platform-specific
// implementations.
return gfx::Size(kA4WidthInch * settings_->device_units_per_inch(),
kA4HeightInch * settings_->device_units_per_inch());
}
mojom::ResultCode TestPrintingContext::UpdatePrinterSettings(
const PrinterSettings& printer_settings) {
DCHECK(!in_print_job_);
if (update_printer_settings_fails_) {
return mojom::ResultCode::kFailed;
}
// The printer name is to be embedded in the printing context's existing
// settings.
const std::string& device_name = base::UTF16ToUTF8(settings_->device_name());
auto found = device_settings_.find(device_name);
if (found == device_settings_.end()) {
DLOG(ERROR) << "No such device found in test printing context: `"
<< device_name << "`";
return mojom::ResultCode::kFailed;
}
// Perform some initialization, akin to various platform-specific actions in
// `InitPrintSettings()`.
DVLOG(1) << "Updating context settings for device `" << device_name << "`";
std::unique_ptr<PrintSettings> existing_settings = std::move(settings_);
settings_ = std::make_unique<PrintSettings>(*found->second);
settings_->set_copies(existing_settings->copies());
settings_->set_dpi(existing_settings->dpi());
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
for (const auto& item : existing_settings->advanced_settings())
settings_->advanced_settings().emplace(item.first, item.second.Clone());
#endif
#if BUILDFLAG(IS_WIN)
if (printer_settings.show_system_dialog) {
return AskUserForSettingsImpl(printer_settings.page_count,
/*has_selection=*/false,
/*is_scripted=*/false);
}
#endif
#if BUILDFLAG(IS_MAC)
destination_is_preview_ = printer_settings.external_preview;
#endif
// Capture a snapshot, simluating changes made to platform device context.
applied_settings_ = *settings_;
return mojom::ResultCode::kSuccess;
}
mojom::ResultCode TestPrintingContext::NewDocument(
const std::u16string& document_name) {
DCHECK(!in_print_job_);
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
if (process_behavior() == ProcessBehavior::kOopEnabledPerformSystemCalls &&
!settings_->system_print_dialog_data().empty()) {
// Mimic the update when system print dialog settings are provided to
// Print Backend service from the browser process.
applied_settings_ = *settings_;
}
#endif
if (on_new_document_callback_) {
on_new_document_callback_.Run(
#if BUILDFLAG(IS_MAC)
destination_is_preview_,
#endif
applied_settings_);
}
abort_printing_ = false;
in_print_job_ = true;
#if BUILDFLAG(ENABLE_OOP_PRINTING)
const bool make_system_calls =
process_behavior() != ProcessBehavior::kOopEnabledSkipSystemCalls;
#else
const bool make_system_calls = true;
#endif
if (make_system_calls) {
if (new_document_cancels_) {
return mojom::ResultCode::kCanceled;
}
if (new_document_fails_)
return mojom::ResultCode::kFailed;
if (new_document_blocked_by_permissions_)
return mojom::ResultCode::kAccessDenied;
// A print job is now active, so potentially update `job_id`.
if (new_document_job_id_.has_value()) {
job_id_ = new_document_job_id_.value();
}
}
// No-op.
return mojom::ResultCode::kSuccess;
}
#if BUILDFLAG(IS_WIN)
mojom::ResultCode TestPrintingContext::RenderPage(const PrintedPage& page,
const PageSetup& page_setup) {
if (abort_printing_)
return mojom::ResultCode::kCanceled;
DCHECK(in_print_job_);
DVLOG(1) << "Render page " << page.page_number();
if (render_page_blocked_by_permissions_)
return mojom::ResultCode::kAccessDenied;
if (render_page_fail_for_page_number_.has_value() &&
*render_page_fail_for_page_number_ == page.page_number()) {
return mojom::ResultCode::kFailed;
}
// No-op.
return mojom::ResultCode::kSuccess;
}
#endif // BUILDFLAG(IS_WIN)
mojom::ResultCode TestPrintingContext::PrintDocument(
const MetafilePlayer& metafile,
const PrintSettings& settings,
uint32_t num_pages) {
if (abort_printing_)
return mojom::ResultCode::kCanceled;
DCHECK(in_print_job_);
DVLOG(1) << "Print document";
if (render_document_blocked_by_permissions_)
return mojom::ResultCode::kAccessDenied;
// No-op.
return mojom::ResultCode::kSuccess;
}
mojom::ResultCode TestPrintingContext::DocumentDone() {
DCHECK(in_print_job_);
DVLOG(1) << "Document done";
if (document_done_blocked_by_permissions_)
return mojom::ResultCode::kAccessDenied;
ResetSettings();
return mojom::ResultCode::kSuccess;
}
void TestPrintingContext::Cancel() {
abort_printing_ = true;
in_print_job_ = false;
DVLOG(1) << "Canceling print job";
}
void TestPrintingContext::ReleaseContext() {}
printing::NativeDrawingContext TestPrintingContext::context() const {
// No native context for test.
return nullptr;
}
#if BUILDFLAG(IS_WIN)
mojom::ResultCode TestPrintingContext::InitWithSettingsForTest(
std::unique_ptr<PrintSettings> settings) {
NOTIMPLEMENTED();
return mojom::ResultCode::kFailed;
}
#endif // BUILDFLAG(IS_WIN)
} // namespace printing