[email protected] | 55e8e9f | 2012-03-02 22:50:54 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 5 | #include "printing/printing_context_win.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 6 | |
[email protected] | 19f09a6 | 2011-05-04 23:37:47 | [diff] [blame] | 7 | #include <algorithm> |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 8 | #include <vector> |
[email protected] | 19f09a6 | 2011-05-04 23:37:47 | [diff] [blame] | 9 | |
vitalybuka | 12b8758 | 2014-12-08 18:57:10 | [diff] [blame] | 10 | #include "base/bind.h" |
dcheng | db5935f | 2016-03-26 00:16:27 | [diff] [blame] | 11 | #include "base/memory/free_deleter.h" |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 12 | #include "base/memory/ptr_util.h" |
Gabriel Charette | e41f49a | 2018-04-23 21:14:19 | [diff] [blame] | 13 | #include "base/message_loop/message_loop_current.h" |
[email protected] | ad3b0501 | 2014-06-16 23:02:15 | [diff] [blame] | 14 | #include "base/strings/string_number_conversions.h" |
[email protected] | 90626587 | 2013-06-07 22:40:45 | [diff] [blame] | 15 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 09083eb | 2012-09-20 05:58:43 | [diff] [blame] | 16 | #include "printing/backend/print_backend.h" |
[email protected] | 55e8e9f | 2012-03-02 22:50:54 | [diff] [blame] | 17 | #include "printing/backend/win_helper.h" |
Scott Violet | 318a55f | 2018-03-30 19:08:19 | [diff] [blame] | 18 | #include "printing/buildflags/buildflags.h" |
[email protected] | 4993f34 | 2010-10-26 17:57:52 | [diff] [blame] | 19 | #include "printing/print_settings_initializer_win.h" |
[email protected] | 8ff1d42 | 2009-07-07 21:31:39 | [diff] [blame] | 20 | #include "printing/printed_document.h" |
vitalybuka | f9d0c0c | 2014-09-09 19:53:33 | [diff] [blame] | 21 | #include "printing/printing_context_system_dialog_win.h" |
[email protected] | ec91bfa | 2013-11-09 17:24:27 | [diff] [blame] | 22 | #include "printing/printing_utils.h" |
[email protected] | e5636a5 | 2011-09-28 21:44:42 | [diff] [blame] | 23 | #include "printing/units.h" |
tomhudson | 828dddb | 2015-12-04 14:34:16 | [diff] [blame] | 24 | #include "skia/ext/skia_utils_win.h" |
[email protected] | 6b7bfd2 | 2013-05-28 23:55:15 | [diff] [blame] | 25 | #include "ui/aura/window.h" |
samli | 6d8217f | 2016-01-20 04:12:20 | [diff] [blame] | 26 | #include "ui/aura/window_tree_host.h" |
[email protected] | 6b7bfd2 | 2013-05-28 23:55:15 | [diff] [blame] | 27 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 28 | namespace printing { |
| 29 | |
vitalybuka | 12b8758 | 2014-12-08 18:57:10 | [diff] [blame] | 30 | namespace { |
| 31 | |
thestig | e85e6b6 | 2016-08-25 00:00:06 | [diff] [blame] | 32 | void AssignResult(PrintingContext::Result* out, PrintingContext::Result in) { |
vitalybuka | 12b8758 | 2014-12-08 18:57:10 | [diff] [blame] | 33 | *out = in; |
| 34 | } |
| 35 | |
| 36 | } // namespace |
| 37 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 38 | // static |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 39 | std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { |
Lei Zhang | 1ba7352 | 2018-04-20 22:12:57 | [diff] [blame] | 40 | #if BUILDFLAG(ENABLE_PRINTING) |
Lei Zhang | 48a4a526 | 2018-04-17 20:18:44 | [diff] [blame] | 41 | return base::WrapUnique(new PrintingContextSystemDialogWin(delegate)); |
Lei Zhang | 1ba7352 | 2018-04-20 22:12:57 | [diff] [blame] | 42 | #else |
| 43 | // The code in printing/ is still built when the GN |enable_basic_printing| |
| 44 | // variable is set to false. Just return PrintingContextWin as a dummy |
| 45 | // context. |
| 46 | return base::WrapUnique(new PrintingContextWin(delegate)); |
thestig | e85e6b6 | 2016-08-25 00:00:06 | [diff] [blame] | 47 | #endif |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 48 | } |
| 49 | |
Vitaly Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 50 | PrintingContextWin::PrintingContextWin(Delegate* delegate) |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 51 | : PrintingContext(delegate), context_(nullptr) {} |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 52 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 53 | PrintingContextWin::~PrintingContextWin() { |
| 54 | ReleaseContext(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 55 | } |
| 56 | |
Vladislav Kuzkokov | 48ceab2 | 2018-02-14 16:29:28 | [diff] [blame] | 57 | void PrintingContextWin::AskUserForSettings(int max_pages, |
| 58 | bool has_selection, |
| 59 | bool is_scripted, |
| 60 | PrintSettingsCallback callback) { |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 61 | NOTIMPLEMENTED(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 62 | } |
| 63 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 64 | PrintingContext::Result PrintingContextWin::UseDefaultSettings() { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 65 | DCHECK(!in_print_job_); |
| 66 | |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 67 | scoped_refptr<PrintBackend> backend = PrintBackend::CreateInstance(nullptr); |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 68 | base::string16 default_printer = |
| 69 | base::UTF8ToWide(backend->GetDefaultPrinterName()); |
| 70 | if (!default_printer.empty()) { |
| 71 | ScopedPrinterHandle printer; |
| 72 | if (printer.OpenPrinter(default_printer.c_str())) { |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 73 | std::unique_ptr<DEVMODE, base::FreeDeleter> dev_mode = |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 74 | CreateDevMode(printer.Get(), nullptr); |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 75 | if (InitializeSettings(default_printer, dev_mode.get()) == OK) |
| 76 | return OK; |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | ReleaseContext(); |
[email protected] | ff3ccc2 | 2011-04-18 21:35:48 | [diff] [blame] | 81 | |
| 82 | // No default printer configured, do we have any printers at all? |
| 83 | DWORD bytes_needed = 0; |
| 84 | DWORD count_returned = 0; |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 85 | (void)::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, |
| 86 | 2, nullptr, 0, &bytes_needed, &count_returned); |
[email protected] | ff3ccc2 | 2011-04-18 21:35:48 | [diff] [blame] | 87 | if (bytes_needed) { |
[email protected] | 1b24888 | 2014-02-25 04:39:14 | [diff] [blame] | 88 | DCHECK_GE(bytes_needed, count_returned * sizeof(PRINTER_INFO_2)); |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 89 | std::vector<BYTE> printer_info_buffer(bytes_needed); |
| 90 | BOOL ret = ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, |
| 91 | nullptr, 2, printer_info_buffer.data(), |
| 92 | bytes_needed, &bytes_needed, &count_returned); |
[email protected] | ff3ccc2 | 2011-04-18 21:35:48 | [diff] [blame] | 93 | if (ret && count_returned) { // have printers |
| 94 | // Open the first successfully found printer. |
[email protected] | 1b24888 | 2014-02-25 04:39:14 | [diff] [blame] | 95 | const PRINTER_INFO_2* info_2 = |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 96 | reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.data()); |
[email protected] | 1b24888 | 2014-02-25 04:39:14 | [diff] [blame] | 97 | const PRINTER_INFO_2* info_2_end = info_2 + count_returned; |
| 98 | for (; info_2 < info_2_end; ++info_2) { |
| 99 | ScopedPrinterHandle printer; |
| 100 | if (!printer.OpenPrinter(info_2->pPrinterName)) |
[email protected] | ff3ccc2 | 2011-04-18 21:35:48 | [diff] [blame] | 101 | continue; |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 102 | std::unique_ptr<DEVMODE, base::FreeDeleter> dev_mode = |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 103 | CreateDevMode(printer.Get(), nullptr); |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 104 | if (InitializeSettings(info_2->pPrinterName, dev_mode.get()) == OK) |
[email protected] | 1b24888 | 2014-02-25 04:39:14 | [diff] [blame] | 105 | return OK; |
[email protected] | ff3ccc2 | 2011-04-18 21:35:48 | [diff] [blame] | 106 | } |
| 107 | if (context_) |
| 108 | return OK; |
| 109 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 110 | } |
[email protected] | ff3ccc2 | 2011-04-18 21:35:48 | [diff] [blame] | 111 | |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 112 | return OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 113 | } |
| 114 | |
[email protected] | 4c9054b | 2013-11-04 18:34:29 | [diff] [blame] | 115 | gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() { |
| 116 | // Default fallback to Letter size. |
| 117 | gfx::SizeF paper_size(kLetterWidthInch, kLetterHeightInch); |
| 118 | |
| 119 | // Get settings from locale. Paper type buffer length is at most 4. |
| 120 | const int paper_type_buffer_len = 4; |
| 121 | wchar_t paper_type_buffer[paper_type_buffer_len] = {0}; |
| 122 | GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE, paper_type_buffer, |
| 123 | paper_type_buffer_len); |
| 124 | if (wcslen(paper_type_buffer)) { // The call succeeded. |
| 125 | int paper_code = _wtoi(paper_type_buffer); |
| 126 | switch (paper_code) { |
| 127 | case DMPAPER_LEGAL: |
| 128 | paper_size.SetSize(kLegalWidthInch, kLegalHeightInch); |
| 129 | break; |
| 130 | case DMPAPER_A4: |
| 131 | paper_size.SetSize(kA4WidthInch, kA4HeightInch); |
| 132 | break; |
| 133 | case DMPAPER_A3: |
| 134 | paper_size.SetSize(kA3WidthInch, kA3HeightInch); |
| 135 | break; |
| 136 | default: // DMPAPER_LETTER is used for default fallback. |
| 137 | break; |
| 138 | } |
| 139 | } |
| 140 | return gfx::Size( |
| 141 | paper_size.width() * settings_.device_units_per_inch(), |
| 142 | paper_size.height() * settings_.device_units_per_inch()); |
| 143 | } |
| 144 | |
[email protected] | 55b23a0 | 2011-08-17 23:09:36 | [diff] [blame] | 145 | PrintingContext::Result PrintingContextWin::UpdatePrinterSettings( |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 146 | bool external_preview, |
vitalybuka | 95fa3c9 | 2015-05-05 03:03:32 | [diff] [blame] | 147 | bool show_system_dialog, |
| 148 | int page_count) { |
[email protected] | 7868ecab | 2011-03-05 00:12:53 | [diff] [blame] | 149 | DCHECK(!in_print_job_); |
[email protected] | e5324b5 | 2013-10-29 03:16:37 | [diff] [blame] | 150 | DCHECK(!external_preview) << "Not implemented"; |
[email protected] | 7868ecab | 2011-03-05 00:12:53 | [diff] [blame] | 151 | |
[email protected] | 55e8e9f | 2012-03-02 22:50:54 | [diff] [blame] | 152 | ScopedPrinterHandle printer; |
[email protected] | 1b24888 | 2014-02-25 04:39:14 | [diff] [blame] | 153 | if (!printer.OpenPrinter(settings_.device_name().c_str())) |
[email protected] | bd5baaf | 2011-04-21 20:48:33 | [diff] [blame] | 154 | return OnError(); |
[email protected] | afbdbf11 | 2011-03-28 22:09:37 | [diff] [blame] | 155 | |
[email protected] | 30aaa81a | 2011-05-03 21:08:39 | [diff] [blame] | 156 | // Make printer changes local to Chrome. |
| 157 | // See MSDN documentation regarding DocumentProperties. |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 158 | std::unique_ptr<DEVMODE, base::FreeDeleter> scoped_dev_mode = |
rvargas | 9b7c6b0f | 2014-09-25 19:22:48 | [diff] [blame] | 159 | CreateDevModeWithColor(printer.Get(), settings_.device_name(), |
[email protected] | b3b6b6f | 2014-02-14 20:19:54 | [diff] [blame] | 160 | settings_.color() != GRAY); |
| 161 | if (!scoped_dev_mode) |
[email protected] | bd5baaf | 2011-04-21 20:48:33 | [diff] [blame] | 162 | return OnError(); |
[email protected] | 7868ecab | 2011-03-05 00:12:53 | [diff] [blame] | 163 | |
[email protected] | b3b6b6f | 2014-02-14 20:19:54 | [diff] [blame] | 164 | { |
| 165 | DEVMODE* dev_mode = scoped_dev_mode.get(); |
| 166 | dev_mode->dmCopies = std::max(settings_.copies(), 1); |
[email protected] | 299e3d00 | 2014-06-03 08:46:49 | [diff] [blame] | 167 | if (dev_mode->dmCopies > 1) { // do not change unless multiple copies |
[email protected] | b3b6b6f | 2014-02-14 20:19:54 | [diff] [blame] | 168 | dev_mode->dmFields |= DM_COPIES; |
| 169 | dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE : |
| 170 | DMCOLLATE_FALSE; |
| 171 | } |
[email protected] | f3256b0d8 | 2011-09-04 23:36:29 | [diff] [blame] | 172 | |
[email protected] | b3b6b6f | 2014-02-14 20:19:54 | [diff] [blame] | 173 | switch (settings_.duplex_mode()) { |
| 174 | case LONG_EDGE: |
| 175 | dev_mode->dmFields |= DM_DUPLEX; |
| 176 | dev_mode->dmDuplex = DMDUP_VERTICAL; |
| 177 | break; |
| 178 | case SHORT_EDGE: |
| 179 | dev_mode->dmFields |= DM_DUPLEX; |
| 180 | dev_mode->dmDuplex = DMDUP_HORIZONTAL; |
| 181 | break; |
| 182 | case SIMPLEX: |
| 183 | dev_mode->dmFields |= DM_DUPLEX; |
| 184 | dev_mode->dmDuplex = DMDUP_SIMPLEX; |
| 185 | break; |
| 186 | default: // UNKNOWN_DUPLEX_MODE |
| 187 | break; |
| 188 | } |
| 189 | |
| 190 | dev_mode->dmFields |= DM_ORIENTATION; |
| 191 | dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE : |
| 192 | DMORIENT_PORTRAIT; |
[email protected] | ad3b0501 | 2014-06-16 23:02:15 | [diff] [blame] | 193 | |
rbpotter | 116c2e1 | 2017-04-04 19:21:28 | [diff] [blame] | 194 | if (settings_.dpi_horizontal() > 0) { |
| 195 | dev_mode->dmPrintQuality = settings_.dpi_horizontal(); |
| 196 | dev_mode->dmFields |= DM_PRINTQUALITY; |
| 197 | } |
| 198 | if (settings_.dpi_vertical() > 0) { |
| 199 | dev_mode->dmYResolution = settings_.dpi_vertical(); |
| 200 | dev_mode->dmFields |= DM_YRESOLUTION; |
| 201 | } |
| 202 | |
[email protected] | ad3b0501 | 2014-06-16 23:02:15 | [diff] [blame] | 203 | const PrintSettings::RequestedMedia& requested_media = |
| 204 | settings_.requested_media(); |
[email protected] | ad3b0501 | 2014-06-16 23:02:15 | [diff] [blame] | 205 | unsigned id = 0; |
rbpotter | 1142f50 | 2017-09-29 18:09:19 | [diff] [blame] | 206 | // If the paper size is a custom user size, setting by ID may not work. |
| 207 | if (base::StringToUint(requested_media.vendor_id, &id) && id && |
| 208 | id < DMPAPER_USER) { |
[email protected] | ad3b0501 | 2014-06-16 23:02:15 | [diff] [blame] | 209 | dev_mode->dmFields |= DM_PAPERSIZE; |
| 210 | dev_mode->dmPaperSize = static_cast<short>(id); |
Lei Zhang | 9a9fe64 | 2017-10-03 22:07:24 | [diff] [blame] | 211 | } else if (!requested_media.size_microns.IsEmpty()) { |
| 212 | static constexpr int kFromUm = 100; // Windows uses 0.1mm. |
| 213 | dev_mode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH; |
| 214 | dev_mode->dmPaperWidth = requested_media.size_microns.width() / kFromUm; |
| 215 | dev_mode->dmPaperLength = requested_media.size_microns.height() / kFromUm; |
[email protected] | ad3b0501 | 2014-06-16 23:02:15 | [diff] [blame] | 216 | } |
[email protected] | e5324b5 | 2013-10-29 03:16:37 | [diff] [blame] | 217 | } |
[email protected] | bd5baaf | 2011-04-21 20:48:33 | [diff] [blame] | 218 | |
[email protected] | 30aaa81a | 2011-05-03 21:08:39 | [diff] [blame] | 219 | // Update data using DocumentProperties. |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 220 | if (show_system_dialog) { |
vitalybuka | 12b8758 | 2014-12-08 18:57:10 | [diff] [blame] | 221 | PrintingContext::Result result = PrintingContext::FAILED; |
vitalybuka | 95fa3c9 | 2015-05-05 03:03:32 | [diff] [blame] | 222 | AskUserForSettings(page_count, false, false, |
tzik | ea7713cd | 2018-03-09 09:39:09 | [diff] [blame] | 223 | base::BindOnce(&AssignResult, &result)); |
vitalybuka | 12b8758 | 2014-12-08 18:57:10 | [diff] [blame] | 224 | return result; |
[email protected] | bd5baaf | 2011-04-21 20:48:33 | [diff] [blame] | 225 | } |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 226 | // Set printer then refresh printer settings. |
thestig | e85e6b6 | 2016-08-25 00:00:06 | [diff] [blame] | 227 | scoped_dev_mode = CreateDevMode(printer.Get(), scoped_dev_mode.get()); |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 228 | return InitializeSettings(settings_.device_name(), scoped_dev_mode.get()); |
[email protected] | 7868ecab | 2011-03-05 00:12:53 | [diff] [blame] | 229 | } |
| 230 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 231 | PrintingContext::Result PrintingContextWin::InitWithSettingsForTest( |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 232 | const PrintSettings& settings) { |
| 233 | DCHECK(!in_print_job_); |
[email protected] | 4993f34 | 2010-10-26 17:57:52 | [diff] [blame] | 234 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 235 | settings_ = settings; |
[email protected] | 4993f34 | 2010-10-26 17:57:52 | [diff] [blame] | 236 | |
| 237 | // TODO(maruel): settings_.ToDEVMODE() |
[email protected] | 55e8e9f | 2012-03-02 22:50:54 | [diff] [blame] | 238 | ScopedPrinterHandle printer; |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 239 | if (!printer.OpenPrinter(settings_.device_name().c_str())) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 240 | return FAILED; |
| 241 | |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 242 | std::unique_ptr<DEVMODE, base::FreeDeleter> dev_mode = |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 243 | CreateDevMode(printer.Get(), nullptr); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 244 | |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 245 | return InitializeSettings(settings_.device_name(), dev_mode.get()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 246 | } |
| 247 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 248 | PrintingContext::Result PrintingContextWin::NewDocument( |
[email protected] | b5fa4ee | 2013-10-01 07:19:07 | [diff] [blame] | 249 | const base::string16& document_name) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 250 | DCHECK(!in_print_job_); |
[email protected] | b75dca8 | 2009-10-13 18:46:21 | [diff] [blame] | 251 | if (!context_) |
[email protected] | c8ad40c | 2009-06-08 17:05:21 | [diff] [blame] | 252 | return OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 253 | |
| 254 | // Set the flag used by the AbortPrintJob dialog procedure. |
| 255 | abort_printing_ = false; |
| 256 | |
| 257 | in_print_job_ = true; |
| 258 | |
| 259 | // Register the application's AbortProc function with GDI. |
[email protected] | b75dca8 | 2009-10-13 18:46:21 | [diff] [blame] | 260 | if (SP_ERROR == SetAbortProc(context_, &AbortProc)) |
[email protected] | c8ad40c | 2009-06-08 17:05:21 | [diff] [blame] | 261 | return OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 262 | |
[email protected] | ec91bfa | 2013-11-09 17:24:27 | [diff] [blame] | 263 | DCHECK(SimplifyDocumentTitle(document_name) == document_name); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 264 | DOCINFO di = { sizeof(DOCINFO) }; |
[email protected] | 299e3d00 | 2014-06-03 08:46:49 | [diff] [blame] | 265 | di.lpszDocName = document_name.c_str(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 266 | |
| 267 | // Is there a debug dump directory specified? If so, force to print to a file. |
Lei Zhang | bdd6381 | 2017-12-12 06:29:51 | [diff] [blame] | 268 | if (PrintedDocument::HasDebugDumpPath()) { |
| 269 | base::FilePath debug_dump_path = PrintedDocument::CreateDebugDumpPath( |
| 270 | document_name, FILE_PATH_LITERAL(".prn")); |
| 271 | if (!debug_dump_path.empty()) |
| 272 | di.lpszOutput = debug_dump_path.value().c_str(); |
| 273 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 274 | |
[email protected] | daee497 | 2009-07-09 14:28:24 | [diff] [blame] | 275 | // No message loop running in unit tests. |
Gabriel Charette | e41f49a | 2018-04-23 21:14:19 | [diff] [blame] | 276 | DCHECK(!base::MessageLoopCurrent::Get() || |
| 277 | !base::MessageLoopCurrent::Get()->NestableTasksAllowed()); |
[email protected] | daee497 | 2009-07-09 14:28:24 | [diff] [blame] | 278 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 279 | // Begin a print job by calling the StartDoc function. |
| 280 | // NOTE: StartDoc() starts a message loop. That causes a lot of problems with |
| 281 | // IPC. Make sure recursive task processing is disabled. |
[email protected] | b75dca8 | 2009-10-13 18:46:21 | [diff] [blame] | 282 | if (StartDoc(context_, &di) <= 0) |
[email protected] | c8ad40c | 2009-06-08 17:05:21 | [diff] [blame] | 283 | return OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 284 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 285 | return OK; |
| 286 | } |
| 287 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 288 | PrintingContext::Result PrintingContextWin::NewPage() { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 289 | if (abort_printing_) |
| 290 | return CANCEL; |
[email protected] | 3b52c98 | 2010-09-27 20:40:36 | [diff] [blame] | 291 | DCHECK(context_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 292 | DCHECK(in_print_job_); |
| 293 | |
Wei Li | ab75477 | 2018-08-22 22:41:17 | [diff] [blame] | 294 | // Intentional No-op. MetafileSkia::SafePlayback takes care of calling |
[email protected] | b10c54d | 2011-03-16 18:22:35 | [diff] [blame] | 295 | // ::StartPage(). |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 296 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 297 | return OK; |
| 298 | } |
| 299 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 300 | PrintingContext::Result PrintingContextWin::PageDone() { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 301 | if (abort_printing_) |
| 302 | return CANCEL; |
| 303 | DCHECK(in_print_job_); |
| 304 | |
Wei Li | ab75477 | 2018-08-22 22:41:17 | [diff] [blame] | 305 | // Intentional No-op. MetafileSkia::SafePlayback takes care of calling |
[email protected] | b10c54d | 2011-03-16 18:22:35 | [diff] [blame] | 306 | // ::EndPage(). |
| 307 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 308 | return OK; |
| 309 | } |
| 310 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 311 | PrintingContext::Result PrintingContextWin::DocumentDone() { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 312 | if (abort_printing_) |
| 313 | return CANCEL; |
| 314 | DCHECK(in_print_job_); |
[email protected] | 6074541 | 2010-09-27 23:46:07 | [diff] [blame] | 315 | DCHECK(context_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 316 | |
| 317 | // Inform the driver that document has ended. |
[email protected] | b75dca8 | 2009-10-13 18:46:21 | [diff] [blame] | 318 | if (EndDoc(context_) <= 0) |
[email protected] | c8ad40c | 2009-06-08 17:05:21 | [diff] [blame] | 319 | return OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 320 | |
| 321 | ResetSettings(); |
| 322 | return OK; |
| 323 | } |
| 324 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 325 | void PrintingContextWin::Cancel() { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 326 | abort_printing_ = true; |
| 327 | in_print_job_ = false; |
[email protected] | b75dca8 | 2009-10-13 18:46:21 | [diff] [blame] | 328 | if (context_) |
| 329 | CancelDC(context_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 330 | } |
| 331 | |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 332 | void PrintingContextWin::ReleaseContext() { |
| 333 | if (context_) { |
| 334 | DeleteDC(context_); |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 335 | context_ = nullptr; |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 336 | } |
| 337 | } |
| 338 | |
Nico Weber | 8e55956 | 2017-10-03 01:25:26 | [diff] [blame] | 339 | printing::NativeDrawingContext PrintingContextWin::context() const { |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 340 | return context_; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 341 | } |
| 342 | |
| 343 | // static |
[email protected] | 51e8d935 | 2010-10-06 22:21:17 | [diff] [blame] | 344 | BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 345 | if (nCode) { |
| 346 | // TODO(maruel): Need a way to find the right instance to set. Should |
| 347 | // leverage PrintJobManager here? |
| 348 | // abort_printing_ = true; |
| 349 | } |
| 350 | return true; |
| 351 | } |
| 352 | |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 353 | PrintingContext::Result PrintingContextWin::InitializeSettings( |
| 354 | const std::wstring& device_name, |
| 355 | DEVMODE* dev_mode) { |
| 356 | if (!dev_mode) |
| 357 | return OnError(); |
| 358 | |
| 359 | ReleaseContext(); |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 360 | context_ = CreateDC(L"WINSPOOL", device_name.c_str(), nullptr, dev_mode); |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 361 | if (!context_) |
| 362 | return OnError(); |
| 363 | |
[email protected] | 62f2e80 | 2011-05-26 14:28:35 | [diff] [blame] | 364 | skia::InitializeDC(context_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 365 | |
| 366 | DCHECK(!in_print_job_); |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 367 | settings_.set_device_name(device_name); |
| 368 | PrintSettingsInitializerWin::InitPrintSettings( |
| 369 | context_, *dev_mode, &settings_); |
[email protected] | 4993f34 | 2010-10-26 17:57:52 | [diff] [blame] | 370 | |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 371 | return OK; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 372 | } |
| 373 | |
vitalybuka | f9d0c0c | 2014-09-09 19:53:33 | [diff] [blame] | 374 | HWND PrintingContextWin::GetRootWindow(gfx::NativeView view) { |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 375 | HWND window = nullptr; |
vitalybuka | a58ec6a | 2015-02-23 18:30:49 | [diff] [blame] | 376 | if (view && view->GetHost()) |
vitalybuka | f9d0c0c | 2014-09-09 19:53:33 | [diff] [blame] | 377 | window = view->GetHost()->GetAcceleratedWidget(); |
vitalybuka | f9d0c0c | 2014-09-09 19:53:33 | [diff] [blame] | 378 | if (!window) { |
thestig | b50a0c33 | 2016-09-30 04:22:45 | [diff] [blame] | 379 | // TODO(maruel): b/1214347 Get the right browser window instead. |
vitalybuka | f9d0c0c | 2014-09-09 19:53:33 | [diff] [blame] | 380 | return GetDesktopWindow(); |
| 381 | } |
| 382 | return window; |
| 383 | } |
| 384 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 385 | } // namespace printing |