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/message_loop/message_loop.h"
14 #include "printing/backend/printing_info_win.h"
15 #include "printing/backend/win_helper.h"
16 #include "printing/printing_test.h"
17 #include "printing/printing_context.h"
18 #include "printing/printing_context_win.h"
19 #include "printing/print_settings.h"
20 #include "testing/gtest/include/gtest/gtest.h"
24 // This test is automatically disabled if no printer is available.
25 class PrintingContextTest
: public PrintingTest
<testing::Test
> {
27 void PrintSettingsCallback(PrintingContext::Result result
) {
32 PrintingContext::Result
result() const { return result_
; }
35 PrintingContext::Result result_
;
38 // This is a fake PrintDlgEx implementation that sets the right fields in
39 // |lppd| to trigger a bug in older revisions of PrintingContext.
40 HRESULT WINAPI
PrintDlgExMock(LPPRINTDLGEX lppd
) {
41 // The interesting bits:
42 // Pretend the user hit print
43 lppd
->dwResultAction
= PD_RESULT_PRINT
;
45 // Pretend the page range is 1-5, but since lppd->Flags does not have
46 // PD_SELECTION set, this really shouldn't matter.
47 lppd
->nPageRanges
= 1;
48 lppd
->lpPageRanges
[0].nFromPage
= 1;
49 lppd
->lpPageRanges
[0].nToPage
= 5;
51 base::string16 printer_name
= PrintingContextTest::GetDefaultPrinter();
52 ScopedPrinterHandle printer
;
53 if (!printer
.OpenPrinter(printer_name
.c_str()))
56 scoped_ptr
<uint8
[]> buffer
;
57 const DEVMODE
* dev_mode
= NULL
;
58 HRESULT result
= S_OK
;
60 lppd
->hDevMode
= NULL
;
61 lppd
->hDevNames
= NULL
;
64 if (info_2
.Init(printer
)) {
65 dev_mode
= info_2
.get()->pDevMode
;
72 if (!PrintingContextWin::AllocateContext(printer_name
, dev_mode
,
78 size_t dev_mode_size
= dev_mode
->dmSize
+ dev_mode
->dmDriverExtra
;
79 lppd
->hDevMode
= GlobalAlloc(GMEM_MOVEABLE
, dev_mode_size
);
80 if (!lppd
->hDevMode
) {
84 void* dev_mode_ptr
= GlobalLock(lppd
->hDevMode
);
89 memcpy(dev_mode_ptr
, dev_mode
, dev_mode_size
);
90 GlobalUnlock(lppd
->hDevMode
);
93 size_t driver_size
= 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pDriverName
);
94 size_t printer_size
= 2 + sizeof(wchar_t) *
95 lstrlen(info_2
.get()->pPrinterName
);
96 size_t port_size
= 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pPortName
);
97 size_t dev_names_size
= sizeof(DEVNAMES
) + driver_size
+ printer_size
+
99 lppd
->hDevNames
= GlobalAlloc(GHND
, dev_names_size
);
100 if (!lppd
->hDevNames
) {
104 void* dev_names_ptr
= GlobalLock(lppd
->hDevNames
);
105 if (!dev_names_ptr
) {
109 DEVNAMES
* dev_names
= reinterpret_cast<DEVNAMES
*>(dev_names_ptr
);
110 dev_names
->wDefault
= 1;
111 dev_names
->wDriverOffset
= sizeof(DEVNAMES
) / sizeof(wchar_t);
112 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wDriverOffset
,
113 info_2
.get()->pDriverName
, driver_size
);
114 dev_names
->wDeviceOffset
= dev_names
->wDriverOffset
+
115 driver_size
/ sizeof(wchar_t);
116 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wDeviceOffset
,
117 info_2
.get()->pPrinterName
, printer_size
);
118 dev_names
->wOutputOffset
= dev_names
->wDeviceOffset
+
119 printer_size
/ sizeof(wchar_t);
120 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wOutputOffset
,
121 info_2
.get()->pPortName
, port_size
);
122 GlobalUnlock(lppd
->hDevNames
);
123 dev_names_ptr
= NULL
;
126 // Note: This section does proper deallocation/free of DC/global handles. We
127 // did not use ScopedHGlobal or ScopedHandle because they did not
128 // perform what we need. Goto's are used based on Windows programming
129 // idiom, to avoid deeply nested if's, and try-catch-finally is not
130 // allowed in Chromium.
131 if (FAILED(result
)) {
135 if (lppd
->hDevMode
) {
136 GlobalFree(lppd
->hDevMode
);
138 if (lppd
->hDevNames
) {
139 GlobalFree(lppd
->hDevNames
);
145 TEST_F(PrintingContextTest
, Base
) {
146 if (IsTestCaseDisabled())
149 PrintSettings settings
;
150 settings
.set_device_name(GetDefaultPrinter());
152 scoped_ptr
<PrintingContext
> context(PrintingContext::Create(std::string()));
153 EXPECT_EQ(PrintingContext::OK
, context
->InitWithSettings(settings
));
155 // The print may lie to use and may not support world transformation.
157 XFORM random_matrix
= { 1, 0.1f
, 0, 1.5f
, 0, 1 };
158 EXPECT_TRUE(SetWorldTransform(context
->context(), &random_matrix
));
159 EXPECT_TRUE(ModifyWorldTransform(context
->context(), NULL
, MWT_IDENTITY
));
162 TEST_F(PrintingContextTest
, PrintAll
) {
163 base::MessageLoop message_loop
;
164 if (IsTestCaseDisabled())
167 std::string dummy_locale
;
168 PrintingContextWin
context(dummy_locale
);
169 context
.SetPrintDialog(&PrintDlgExMock
);
170 context
.AskUserForSettings(
171 NULL
, 123, false, base::Bind(&PrintingContextTest::PrintSettingsCallback
,
172 base::Unretained(this)));
173 EXPECT_EQ(PrintingContext::OK
, result());
174 PrintSettings settings
= context
.settings();
175 EXPECT_EQ(settings
.ranges().size(), 0);
178 } // namespace printing