1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "printing/test_printing_context.h"
10 #include "base/check.h"
11 #include "base/containers/flat_map.h"
12 #include "base/notreached.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "build/build_config.h"
15 #include "printing/backend/print_backend.h"
16 #include "printing/buildflags/buildflags.h"
17 #include "printing/mojom/print.mojom.h"
18 #include "printing/print_settings.h"
19 #include "printing/printing_context.h"
20 #include "printing/units.h"
21 #include "ui/gfx/geometry/size.h"
23 #if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
24 #include "printing/printing_features.h"
28 #include "printing/printed_page_win.h"
33 TestPrintingContextDelegate::TestPrintingContextDelegate() = default;
35 TestPrintingContextDelegate::~TestPrintingContextDelegate() = default;
37 gfx::NativeView TestPrintingContextDelegate::GetParentView() {
38 return gfx::NativeView();
41 std::string TestPrintingContextDelegate::GetAppLocale() {
45 TestPrintingContext::TestPrintingContext(Delegate* delegate,
46 bool skip_system_calls)
47 : PrintingContext(delegate) {
48 #if BUILDFLAG(ENABLE_OOP_PRINTING)
49 if (skip_system_calls)
50 set_skip_system_calls();
54 TestPrintingContext::~TestPrintingContext() = default;
56 void TestPrintingContext::SetDeviceSettings(
57 const std::string& device_name,
58 std::unique_ptr<PrintSettings> settings) {
59 device_settings_.emplace(device_name, std::move(settings));
62 void TestPrintingContext::SetUserSettings(const PrintSettings& settings) {
63 user_settings_ = settings;
66 void TestPrintingContext::AskUserForSettings(int max_pages,
69 PrintSettingsCallback callback) {
70 std::move(callback).Run(
71 AskUserForSettingsImpl(max_pages, has_selection, is_scripted));
74 mojom::ResultCode TestPrintingContext::AskUserForSettingsImpl(
78 // Do not actually ask the user with a dialog, just pretend like user
79 // made some kind of interaction.
80 if (ask_user_for_settings_cancel_) {
81 // Pretend the user hit the Cancel button.
82 return mojom::ResultCode::kCanceled;
85 // Allow for test-specific user modifications.
86 if (user_settings_.has_value()) {
87 *settings_ = *user_settings_;
89 // Pretend the user selected the default printer and used the default
91 scoped_refptr<PrintBackend> print_backend =
92 PrintBackend::CreateInstance(/*locale=*/std::string());
93 std::string printer_name;
94 if (print_backend->GetDefaultPrinterName(printer_name) !=
95 mojom::ResultCode::kSuccess) {
96 return mojom::ResultCode::kFailed;
98 auto found = device_settings_.find(printer_name);
99 if (found == device_settings_.end()) {
100 return mojom::ResultCode::kFailed;
102 settings_ = std::make_unique<PrintSettings>(*found->second);
105 // Capture a snapshot, simluating changes made to platform device context.
106 applied_settings_ = *settings_;
108 return mojom::ResultCode::kSuccess;
111 mojom::ResultCode TestPrintingContext::UseDefaultSettings() {
112 if (use_default_settings_fails_)
113 return mojom::ResultCode::kFailed;
115 scoped_refptr<PrintBackend> print_backend =
116 PrintBackend::CreateInstance(/*locale=*/std::string());
117 std::string printer_name;
118 mojom::ResultCode result = print_backend->GetDefaultPrinterName(printer_name);
119 if (result != mojom::ResultCode::kSuccess)
121 auto found = device_settings_.find(printer_name);
122 if (found == device_settings_.end())
123 return mojom::ResultCode::kFailed;
124 settings_ = std::make_unique<PrintSettings>(*found->second);
126 // Capture a snapshot, simluating changes made to platform device context.
127 applied_settings_ = *settings_;
129 return mojom::ResultCode::kSuccess;
132 gfx::Size TestPrintingContext::GetPdfPaperSizeDeviceUnits() {
133 // Default to A4 paper size, which is an alternative to Letter size that is
134 // often used as the fallback size for some platform-specific
136 return gfx::Size(kA4WidthInch * settings_->device_units_per_inch(),
137 kA4HeightInch * settings_->device_units_per_inch());
140 mojom::ResultCode TestPrintingContext::UpdatePrinterSettings(
141 const PrinterSettings& printer_settings) {
142 DCHECK(!in_print_job_);
144 // The printer name is to be embedded in the printing context's existing
146 const std::string& device_name = base::UTF16ToUTF8(settings_->device_name());
147 auto found = device_settings_.find(device_name);
148 if (found == device_settings_.end()) {
149 DLOG(ERROR) << "No such device found in test printing context: `"
150 << device_name << "`";
151 return mojom::ResultCode::kFailed;
154 // Perform some initialization, akin to various platform-specific actions in
155 // `InitPrintSettings()`.
156 DVLOG(1) << "Updating context settings for device `" << device_name << "`";
157 std::unique_ptr<PrintSettings> existing_settings = std::move(settings_);
158 settings_ = std::make_unique<PrintSettings>(*found->second);
159 settings_->set_dpi(existing_settings->dpi());
160 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
161 for (const auto& item : existing_settings->advanced_settings())
162 settings_->advanced_settings().emplace(item.first, item.second.Clone());
165 #if BUILDFLAG(IS_WIN)
166 if (printer_settings.show_system_dialog) {
167 return AskUserForSettingsImpl(printer_settings.page_count,
168 /*has_selection=*/false,
169 /*is_scripted=*/false);
173 #if BUILDFLAG(IS_MAC)
174 destination_is_preview_ = printer_settings.external_preview;
177 // Capture a snapshot, simluating changes made to platform device context.
178 applied_settings_ = *settings_;
180 return mojom::ResultCode::kSuccess;
183 mojom::ResultCode TestPrintingContext::NewDocument(
184 const std::u16string& document_name) {
185 DCHECK(!in_print_job_);
187 #if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
188 if (!skip_system_calls() && features::ShouldPrintJobOop() &&
189 !settings_->system_print_dialog_data().empty()) {
190 // Mimic the update when system print dialog settings are provided to
191 // Print Backend service from the browser process.
192 applied_settings_ = *settings_;
196 if (on_new_document_callback_) {
197 on_new_document_callback_.Run(
198 #if BUILDFLAG(IS_MAC)
199 destination_is_preview_,
204 abort_printing_ = false;
205 in_print_job_ = true;
207 if (!skip_system_calls()) {
208 if (new_document_cancels_) {
209 return mojom::ResultCode::kCanceled;
211 if (new_document_fails_)
212 return mojom::ResultCode::kFailed;
213 if (new_document_blocked_by_permissions_)
214 return mojom::ResultCode::kAccessDenied;
218 return mojom::ResultCode::kSuccess;
221 #if BUILDFLAG(IS_WIN)
222 mojom::ResultCode TestPrintingContext::RenderPage(const PrintedPage& page,
223 const PageSetup& page_setup) {
225 return mojom::ResultCode::kCanceled;
226 DCHECK(in_print_job_);
227 DVLOG(1) << "Render page " << page.page_number();
229 if (render_page_blocked_by_permissions_)
230 return mojom::ResultCode::kAccessDenied;
232 if (render_page_fail_for_page_number_.has_value() &&
233 *render_page_fail_for_page_number_ == page.page_number()) {
234 return mojom::ResultCode::kFailed;
238 return mojom::ResultCode::kSuccess;
240 #endif // BUILDFLAG(IS_WIN)
242 mojom::ResultCode TestPrintingContext::PrintDocument(
243 const MetafilePlayer& metafile,
244 const PrintSettings& settings,
245 uint32_t num_pages) {
247 return mojom::ResultCode::kCanceled;
248 DCHECK(in_print_job_);
249 DVLOG(1) << "Print document";
251 if (render_document_blocked_by_permissions_)
252 return mojom::ResultCode::kAccessDenied;
255 return mojom::ResultCode::kSuccess;
258 mojom::ResultCode TestPrintingContext::DocumentDone() {
259 DCHECK(in_print_job_);
260 DVLOG(1) << "Document done";
262 if (document_done_blocked_by_permissions_)
263 return mojom::ResultCode::kAccessDenied;
266 return mojom::ResultCode::kSuccess;
269 void TestPrintingContext::Cancel() {
270 abort_printing_ = true;
271 in_print_job_ = false;
272 DVLOG(1) << "Canceling print job";
274 void TestPrintingContext::ReleaseContext() {}
276 printing::NativeDrawingContext TestPrintingContext::context() const {
277 // No native context for test.
281 #if BUILDFLAG(IS_WIN)
282 mojom::ResultCode TestPrintingContext::InitWithSettingsForTest(
283 std::unique_ptr<PrintSettings> settings) {
285 return mojom::ResultCode::kFailed;
287 #endif // BUILDFLAG(IS_WIN)
289 } // namespace printing