1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "printing/backend/printing_info_win.h"
15 #include "printing/printing_test.h"
16 #include "printing/printing_context.h"
17 #include "printing/printing_context_win.h"
18 #include "printing/print_settings.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 // This test is automatically disabled if no printer is available.
22 class PrintingContextTest
: public PrintingTest
<testing::Test
> {
24 void PrintSettingsCallback(printing::PrintingContext::Result result
) {
26 base::MessageLoop::current()->QuitWhenIdle();
30 printing::PrintingContext::Result
result() const { return result_
; }
33 printing::PrintingContext::Result result_
;
36 // This is a fake PrintDlgEx implementation that sets the right fields in
37 // |lppd| to trigger a bug in older revisions of PrintingContext.
38 HRESULT WINAPI
PrintDlgExMock(LPPRINTDLGEX lppd
) {
39 // The interesting bits:
40 // Pretend the user hit print
41 lppd
->dwResultAction
= PD_RESULT_PRINT
;
43 // Pretend the page range is 1-5, but since lppd->Flags does not have
44 // PD_SELECTION set, this really shouldn't matter.
45 lppd
->nPageRanges
= 1;
46 lppd
->lpPageRanges
[0].nFromPage
= 1;
47 lppd
->lpPageRanges
[0].nToPage
= 5;
50 std::wstring printer_name
= PrintingContextTest::GetDefaultPrinter();
52 if (!OpenPrinter(const_cast<wchar_t*>(printer_name
.c_str()), &printer
, NULL
))
55 scoped_ptr
<uint8
[]> buffer
;
56 const DEVMODE
* dev_mode
= NULL
;
57 HRESULT result
= S_OK
;
59 lppd
->hDevMode
= NULL
;
60 lppd
->hDevNames
= NULL
;
62 printing::PrinterInfo2 info_2
;
63 if (info_2
.Init(printer
)) {
64 dev_mode
= info_2
.get()->pDevMode
;
71 if (!printing::PrintingContextWin::AllocateContext(printer_name
, dev_mode
,
77 size_t dev_mode_size
= dev_mode
->dmSize
+ dev_mode
->dmDriverExtra
;
78 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, dev_mode_size
);
79 if (!lppd
->hDevMode
) {
83 void* dev_mode_ptr
= GlobalLock(lppd
->hDevMode
);
88 memcpy(dev_mode_ptr
, dev_mode
, dev_mode_size
);
89 GlobalUnlock(lppd
->hDevMode
);
92 size_t driver_size
= 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pDriverName
);
93 size_t printer_size
= 2 + sizeof(wchar_t) *
94 lstrlen(info_2
.get()->pPrinterName
);
95 size_t port_size
= 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pPortName
);
96 size_t dev_names_size
= sizeof(DEVNAMES
) + driver_size
+ printer_size
+
98 lppd
->hDevNames
= GlobalAlloc(GHND
, dev_names_size
);
99 if (!lppd
->hDevNames
) {
103 void* dev_names_ptr
= GlobalLock(lppd
->hDevNames
);
104 if (!dev_names_ptr
) {
108 DEVNAMES
* dev_names
= reinterpret_cast<DEVNAMES
*>(dev_names_ptr
);
109 dev_names
->wDefault
= 1;
110 dev_names
->wDriverOffset
= sizeof(DEVNAMES
) / sizeof(wchar_t);
111 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wDriverOffset
,
112 info_2
.get()->pDriverName
, driver_size
);
113 dev_names
->wDeviceOffset
= dev_names
->wDriverOffset
+
114 driver_size
/ sizeof(wchar_t);
115 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wDeviceOffset
,
116 info_2
.get()->pPrinterName
, printer_size
);
117 dev_names
->wOutputOffset
= dev_names
->wDeviceOffset
+
118 printer_size
/ sizeof(wchar_t);
119 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wOutputOffset
,
120 info_2
.get()->pPortName
, port_size
);
121 GlobalUnlock(lppd
->hDevNames
);
122 dev_names_ptr
= NULL
;
125 // Note: This section does proper deallocation/free of DC/global handles. We
126 // did not use ScopedHGlobal or ScopedHandle because they did not
127 // perform what we need. Goto's are used based on Windows programming
128 // idiom, to avoid deeply nested if's, and try-catch-finally is not
129 // allowed in Chromium.
130 if (FAILED(result
)) {
134 if (lppd
->hDevMode
) {
135 GlobalFree(lppd
->hDevMode
);
137 if (lppd
->hDevNames
) {
138 GlobalFree(lppd
->hDevNames
);
141 ClosePrinter(printer
);
145 TEST_F(PrintingContextTest
, Base
) {
146 if (IsTestCaseDisabled())
149 printing::PrintSettings settings
;
150 settings
.set_device_name(GetDefaultPrinter());
152 scoped_ptr
<printing::PrintingContext
> context(
153 printing::PrintingContext::Create(std::string()));
154 EXPECT_EQ(printing::PrintingContext::OK
, context
->InitWithSettings(settings
));
156 // The print may lie to use and may not support world transformation.
158 XFORM random_matrix
= { 1, 0.1f
, 0, 1.5f
, 0, 1 };
159 EXPECT_TRUE(SetWorldTransform(context
->context(), &random_matrix
));
160 EXPECT_TRUE(ModifyWorldTransform(context
->context(), NULL
, MWT_IDENTITY
));
163 TEST_F(PrintingContextTest
, PrintAll
) {
164 base::MessageLoopForUI loop
;
165 if (IsTestCaseDisabled())
168 std::string dummy_locale
;
169 printing::PrintingContextWin
context(dummy_locale
);
170 context
.SetPrintDialog(&PrintDlgExMock
);
171 context
.AskUserForSettings(
172 NULL
, 123, false, base::Bind(&PrintingContextTest::PrintSettingsCallback
,
173 base::Unretained(this)));
174 base::RunLoop().Run();
175 EXPECT_EQ(printing::PrintingContext::OK
, result());
177 printing::PrintSettings settings
= context
.settings();
178 EXPECT_EQ(settings
.ranges().size(), 0);