blob: 88ca0fcb8a12a54fc9b5ee35dfc670b26ac5a3cb [file] [log] [blame]
[email protected]128bec3c2011-01-20 22:57:351// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]51e8d9352010-10-06 22:21:175#include "printing/printing_context_win.h"
vitalybuka92ab8ce2014-08-26 23:41:456
avi126e93c2015-12-21 21:48:167#include <stddef.h>
8#include <stdint.h>
9
Vladislav Kuzkokov19998222019-08-12 14:26:0910#include <utility>
11
vitalybukaf9d0c0c2014-09-09 19:53:3312#include "base/bind.h"
Gabriel Charettec7108742019-08-23 03:31:4013#include "base/test/task_environment.h"
thakise03b42a2015-07-14 18:44:1014#include "base/win/scoped_handle.h"
15#include "base/win/scoped_hdc.h"
vitalybukaf9d0c0c2014-09-09 19:53:3316#include "printing/backend/printing_info_win.h"
17#include "printing/backend/win_helper.h"
Alan Screen3fb63bf2020-08-19 00:11:2318#include "printing/mojom/print.mojom.h"
[email protected]8ff1d422009-07-07 21:31:3919#include "printing/print_settings.h"
vitalybukaf9d0c0c2014-09-09 19:53:3320#include "printing/printing_context_system_dialog_win.h"
21#include "printing/printing_test.h"
initial.commit09911bf2008-07-26 23:55:2922#include "testing/gtest/include/gtest/gtest.h"
initial.commit09911bf2008-07-26 23:55:2923
[email protected]1b248882014-02-25 04:39:1424namespace printing {
25
initial.commit09911bf2008-07-26 23:55:2926// This test is automatically disabled if no printer is available.
Vitaly Bukabd7c9812014-08-26 08:57:5427class PrintingContextTest : public PrintingTest<testing::Test>,
28 public PrintingContext::Delegate {
[email protected]b7191422010-09-21 19:18:0529 public:
[email protected]1b248882014-02-25 04:39:1430 void PrintSettingsCallback(PrintingContext::Result result) {
[email protected]b7191422010-09-21 19:18:0531 result_ = result;
32 }
33
Vitaly Bukabd7c9812014-08-26 08:57:5434 // PrintingContext::Delegate methods.
thestig5f683912016-09-30 22:42:1635 gfx::NativeView GetParentView() override { return nullptr; }
nickbc761612015-04-27 23:30:4636 std::string GetAppLocale() override { return std::string(); }
Vitaly Bukabd7c9812014-08-26 08:57:5437
[email protected]b7191422010-09-21 19:18:0538 protected:
[email protected]1b248882014-02-25 04:39:1439 PrintingContext::Result result() const { return result_; }
[email protected]b7191422010-09-21 19:18:0540
41 private:
[email protected]1b248882014-02-25 04:39:1442 PrintingContext::Result result_;
initial.commit09911bf2008-07-26 23:55:2943};
44
thakise03b42a2015-07-14 18:44:1045namespace {
thestige85e6b62016-08-25 00:00:0646
thakise03b42a2015-07-14 18:44:1047struct FreeHandleTraits {
48 typedef HANDLE Handle;
49 static void CloseHandle(HANDLE handle) { GlobalFree(handle); }
thestig5f683912016-09-30 22:42:1650 static bool IsHandleValid(HANDLE handle) { return handle != nullptr; }
51 static HANDLE NullHandle() { return nullptr; }
thakise03b42a2015-07-14 18:44:1052};
thestig5f683912016-09-30 22:42:1653
54using ScopedGlobalAlloc =
55 base::win::GenericScopedHandle<FreeHandleTraits,
56 base::win::DummyVerifierTraits>;
thakise03b42a2015-07-14 18:44:1057
thestige85e6b62016-08-25 00:00:0658} // namespace
59
60class MockPrintingContextWin : public PrintingContextSystemDialogWin {
vitalybukaf9d0c0c2014-09-09 19:53:3361 public:
thestige85e6b62016-08-25 00:00:0662 explicit MockPrintingContextWin(Delegate* delegate)
63 : PrintingContextSystemDialogWin(delegate) {}
vitalybukaf9d0c0c2014-09-09 19:53:3364
65 protected:
66 // This is a fake PrintDlgEx implementation that sets the right fields in
67 // |lppd| to trigger a bug in older revisions of PrintingContext.
anujk.sharma263c3132014-10-07 07:29:4268 HRESULT ShowPrintDialog(PRINTDLGEX* lppd) override {
vitalybukaf9d0c0c2014-09-09 19:53:3369 // The interesting bits:
70 // Pretend the user hit print
71 lppd->dwResultAction = PD_RESULT_PRINT;
72
73 // Pretend the page range is 1-5, but since lppd->Flags does not have
74 // PD_SELECTION set, this really shouldn't matter.
75 lppd->nPageRanges = 1;
76 lppd->lpPageRanges[0].nFromPage = 1;
77 lppd->lpPageRanges[0].nToPage = 5;
78
79 base::string16 printer_name = PrintingContextTest::GetDefaultPrinter();
80 ScopedPrinterHandle printer;
Lei Zhang151b1b92019-05-24 20:48:3081 if (!printer.OpenPrinterWithName(printer_name.c_str()))
vitalybukaf9d0c0c2014-09-09 19:53:3382 return E_FAIL;
83
thestig5f683912016-09-30 22:42:1684 const DEVMODE* dev_mode = nullptr;
85 lppd->hDC = nullptr;
86 lppd->hDevMode = nullptr;
87 lppd->hDevNames = nullptr;
vitalybukaf9d0c0c2014-09-09 19:53:3388
89 PrinterInfo2 info_2;
thakise03b42a2015-07-14 18:44:1090 if (info_2.Init(printer.Get()))
vitalybukaf9d0c0c2014-09-09 19:53:3391 dev_mode = info_2.get()->pDevMode;
thakise03b42a2015-07-14 18:44:1092 if (!dev_mode)
93 return E_FAIL;
vitalybukaf9d0c0c2014-09-09 19:53:3394
thakise03b42a2015-07-14 18:44:1095 base::win::ScopedCreateDC hdc(
thestig5f683912016-09-30 22:42:1696 CreateDC(L"WINSPOOL", printer_name.c_str(), nullptr, dev_mode));
thakise03b42a2015-07-14 18:44:1097 if (!hdc.Get())
98 return E_FAIL;
vitalybukaf9d0c0c2014-09-09 19:53:3399
100 size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
thakise03b42a2015-07-14 18:44:10101 ScopedGlobalAlloc dev_mode_mem(GlobalAlloc(GMEM_MOVEABLE, dev_mode_size));
102 if (!dev_mode_mem.Get())
103 return E_FAIL;
104 void* dev_mode_ptr = GlobalLock(dev_mode_mem.Get());
105 if (!dev_mode_ptr)
106 return E_FAIL;
vitalybukaf9d0c0c2014-09-09 19:53:33107 memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
thakise03b42a2015-07-14 18:44:10108 GlobalUnlock(dev_mode_mem.Get());
thestig5f683912016-09-30 22:42:16109 dev_mode_ptr = nullptr;
vitalybukaf9d0c0c2014-09-09 19:53:33110
111 size_t driver_size =
112 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pDriverName);
113 size_t printer_size =
114 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPrinterName);
115 size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPortName);
116 size_t dev_names_size =
117 sizeof(DEVNAMES) + driver_size + printer_size + port_size;
thakise03b42a2015-07-14 18:44:10118 ScopedGlobalAlloc dev_names_mem(GlobalAlloc(GHND, dev_names_size));
119 if (!dev_names_mem.Get())
120 return E_FAIL;
121 void* dev_names_ptr = GlobalLock(dev_names_mem.Get());
122 if (!dev_names_ptr)
123 return E_FAIL;
vitalybukaf9d0c0c2014-09-09 19:53:33124 DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
125 dev_names->wDefault = 1;
126 dev_names->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
avi126e93c2015-12-21 21:48:16127 memcpy(reinterpret_cast<uint8_t*>(dev_names_ptr) + dev_names->wDriverOffset,
128 info_2.get()->pDriverName, driver_size);
brucedawsonc8e9e0d002015-12-03 01:54:27129 dev_names->wDeviceOffset = base::checked_cast<WORD>(
130 dev_names->wDriverOffset + driver_size / sizeof(wchar_t));
avi126e93c2015-12-21 21:48:16131 memcpy(reinterpret_cast<uint8_t*>(dev_names_ptr) + dev_names->wDeviceOffset,
132 info_2.get()->pPrinterName, printer_size);
brucedawsonc8e9e0d002015-12-03 01:54:27133 dev_names->wOutputOffset = base::checked_cast<WORD>(
134 dev_names->wDeviceOffset + printer_size / sizeof(wchar_t));
avi126e93c2015-12-21 21:48:16135 memcpy(reinterpret_cast<uint8_t*>(dev_names_ptr) + dev_names->wOutputOffset,
136 info_2.get()->pPortName, port_size);
thakise03b42a2015-07-14 18:44:10137 GlobalUnlock(dev_names_mem.Get());
thestig5f683912016-09-30 22:42:16138 dev_names_ptr = nullptr;
vitalybukaf9d0c0c2014-09-09 19:53:33139
thakise03b42a2015-07-14 18:44:10140 lppd->hDC = hdc.Take();
141 lppd->hDevMode = dev_mode_mem.Take();
142 lppd->hDevNames = dev_names_mem.Take();
143 return S_OK;
vitalybukaf9d0c0c2014-09-09 19:53:33144 }
145};
146
147TEST_F(PrintingContextTest, PrintAll) {
vitalybukaf9d0c0c2014-09-09 19:53:33148 if (IsTestCaseDisabled())
149 return;
150
Gabriel Charette7f4fc23d2019-09-05 18:07:39151 base::test::SingleThreadTaskEnvironment task_environment;
vitalybukaf9d0c0c2014-09-09 19:53:33152 MockPrintingContextWin context(this);
153 context.AskUserForSettings(
tzikea7713cd2018-03-09 09:39:09154 123, false, false,
155 base::BindOnce(&PrintingContextTest::PrintSettingsCallback,
156 base::Unretained(this)));
vitalybukaf9d0c0c2014-09-09 19:53:33157 EXPECT_EQ(PrintingContext::OK, result());
Lei Zhang0c4f392de2018-05-15 23:05:26158 const PrintSettings& settings = context.settings();
thakis6ef917b2015-12-10 19:29:57159 EXPECT_EQ(0u, settings.ranges().size());
vitalybukaf9d0c0c2014-09-09 19:53:33160}
161
Lei Zhang0c4f392de2018-05-15 23:05:26162TEST_F(PrintingContextTest, Color) {
163 if (IsTestCaseDisabled())
164 return;
165
Gabriel Charette7f4fc23d2019-09-05 18:07:39166 base::test::SingleThreadTaskEnvironment task_environment;
Lei Zhang0c4f392de2018-05-15 23:05:26167 MockPrintingContextWin context(this);
168 context.AskUserForSettings(
169 123, false, false,
170 base::BindOnce(&PrintingContextTest::PrintSettingsCallback,
171 base::Unretained(this)));
172 EXPECT_EQ(PrintingContext::OK, result());
173 const PrintSettings& settings = context.settings();
Alan Screen3fb63bf2020-08-19 00:11:23174 EXPECT_NE(settings.color(), mojom::ColorModel::kUnknownColorModel);
Lei Zhang0c4f392de2018-05-15 23:05:26175}
176
[email protected]e055fe2b2010-12-01 02:05:39177TEST_F(PrintingContextTest, Base) {
[email protected]e055fe2b2010-12-01 02:05:39178 if (IsTestCaseDisabled())
179 return;
initial.commit09911bf2008-07-26 23:55:29180
Vladislav Kuzkokov19998222019-08-12 14:26:09181 auto settings = std::make_unique<PrintSettings>();
182 settings->set_device_name(GetDefaultPrinter());
initial.commit09911bf2008-07-26 23:55:29183 // Initialize it.
thestig5f683912016-09-30 22:42:16184 PrintingContextWin context(this);
Vladislav Kuzkokov19998222019-08-12 14:26:09185 EXPECT_EQ(PrintingContext::OK,
186 context.InitWithSettingsForTest(std::move(settings)));
initial.commit09911bf2008-07-26 23:55:29187
initial.commit09911bf2008-07-26 23:55:29188 // The print may lie to use and may not support world transformation.
189 // Verify right now.
Lei Zhang01a1d3c02019-05-21 04:59:10190 XFORM random_matrix = {1, 0.1f, 0, 1.5f, 0, 1};
thestig5f683912016-09-30 22:42:16191 EXPECT_TRUE(SetWorldTransform(context.context(), &random_matrix));
192 EXPECT_TRUE(ModifyWorldTransform(context.context(), nullptr, MWT_IDENTITY));
initial.commit09911bf2008-07-26 23:55:29193}
[email protected]d8254622010-08-13 19:15:46194
[email protected]1b248882014-02-25 04:39:14195} // namespace printing