| // 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(IS_WIN) |
| #include "printing/printed_page_win.h" |
| #endif |
| |
| namespace printing { |
| |
| namespace { |
| |
| #if BUILDFLAG(IS_WIN) |
| void CaptureResult(mojom::ResultCode& capture_result, |
| mojom::ResultCode result) { |
| capture_result = result; |
| } |
| #endif |
| |
| } // namespace |
| |
| TestPrintingContextDelegate::TestPrintingContextDelegate() = default; |
| |
| TestPrintingContextDelegate::~TestPrintingContextDelegate() = default; |
| |
| gfx::NativeView TestPrintingContextDelegate::GetParentView() { |
| return nullptr; |
| } |
| |
| std::string TestPrintingContextDelegate::GetAppLocale() { |
| return std::string(); |
| } |
| |
| TestPrintingContext::TestPrintingContext(Delegate* delegate, |
| bool skip_system_calls) |
| : PrintingContext(delegate) { |
| #if BUILDFLAG(ENABLE_OOP_PRINTING) |
| if (skip_system_calls) |
| set_skip_system_calls(); |
| #endif |
| } |
| |
| 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::AskUserForSettings(int max_pages, |
| bool has_selection, |
| bool is_scripted, |
| PrintSettingsCallback callback) { |
| // 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. |
| std::move(callback).Run(mojom::ResultCode::kCanceled); |
| return; |
| } |
| |
| // 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) { |
| std::move(callback).Run(mojom::ResultCode::kFailed); |
| return; |
| } |
| auto found = device_settings_.find(printer_name); |
| if (found == device_settings_.end()) { |
| std::move(callback).Run(mojom::ResultCode::kFailed); |
| return; |
| } |
| settings_ = std::make_unique<PrintSettings>(*found->second); |
| std::move(callback).Run(mojom::ResultCode::kSuccess); |
| } |
| |
| mojom::ResultCode TestPrintingContext::UseDefaultSettings() { |
| scoped_refptr<PrintBackend> print_backend = |
| PrintBackend::CreateInstance(/*locale=*/std::string()); |
| if (use_default_settings_fails_) |
| return mojom::ResultCode::kFailed; |
| |
| 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); |
| 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 BUILDFLAG(IS_MAC) |
| DCHECK(!printer_settings.external_preview) << "Not implemented"; |
| #endif |
| |
| // Windows is special case where system dialog can be shown from here. |
| #if !BUILDFLAG(IS_WIN) |
| DCHECK(!printer_settings.show_system_dialog) << "Not implemented"; |
| #endif |
| |
| // 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_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) { |
| mojom::ResultCode result = mojom::ResultCode::kFailed; |
| AskUserForSettings(printer_settings.page_count, /*has_selection=*/false, |
| /*is_scripted=*/false, |
| base::BindOnce(&CaptureResult, std::ref(result))); |
| return result; |
| } |
| #endif |
| |
| return mojom::ResultCode::kSuccess; |
| } |
| |
| mojom::ResultCode TestPrintingContext::NewDocument( |
| const std::u16string& document_name) { |
| DCHECK(!in_print_job_); |
| |
| if (!new_document_called_.is_null()) |
| new_document_called_.Run(); |
| |
| abort_printing_ = false; |
| in_print_job_ = true; |
| |
| if (!skip_system_calls()) { |
| if (new_document_fails_) |
| return mojom::ResultCode::kFailed; |
| if (new_document_blocked_by_permissions_) |
| return mojom::ResultCode::kAccessDenied; |
| } |
| |
| // 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 |