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.
5 #include "printing/printing_context_win.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/win/scoped_handle.h"
10 #include "base/win/scoped_hdc.h"
11 #include "printing/backend/printing_info_win.h"
12 #include "printing/backend/win_helper.h"
13 #include "printing/print_settings.h"
14 #include "printing/printing_context_system_dialog_win.h"
15 #include "printing/printing_test.h"
16 #include "testing/gtest/include/gtest/gtest.h"
20 // This test is automatically disabled if no printer is available.
21 class PrintingContextTest
: public PrintingTest
<testing::Test
>,
22 public PrintingContext::Delegate
{
24 void PrintSettingsCallback(PrintingContext::Result result
) {
28 // PrintingContext::Delegate methods.
29 gfx::NativeView
GetParentView() override
{ return NULL
; }
30 std::string
GetAppLocale() override
{ return std::string(); }
33 PrintingContext::Result
result() const { return result_
; }
36 PrintingContext::Result result_
;
40 struct FreeHandleTraits
{
41 typedef HANDLE Handle
;
42 static void CloseHandle(HANDLE handle
) { GlobalFree(handle
); }
43 static bool IsHandleValid(HANDLE handle
) { return handle
!= NULL
; }
44 static HANDLE
NullHandle() { return NULL
; }
46 typedef base::win::GenericScopedHandle
<FreeHandleTraits
,
47 base::win::DummyVerifierTraits
>
51 class MockPrintingContextWin
: public PrintingContextSytemDialogWin
{
53 MockPrintingContextWin(Delegate
* delegate
)
54 : PrintingContextSytemDialogWin(delegate
) {}
57 // This is a fake PrintDlgEx implementation that sets the right fields in
58 // |lppd| to trigger a bug in older revisions of PrintingContext.
59 HRESULT
ShowPrintDialog(PRINTDLGEX
* lppd
) override
{
60 // The interesting bits:
61 // Pretend the user hit print
62 lppd
->dwResultAction
= PD_RESULT_PRINT
;
64 // Pretend the page range is 1-5, but since lppd->Flags does not have
65 // PD_SELECTION set, this really shouldn't matter.
66 lppd
->nPageRanges
= 1;
67 lppd
->lpPageRanges
[0].nFromPage
= 1;
68 lppd
->lpPageRanges
[0].nToPage
= 5;
70 base::string16 printer_name
= PrintingContextTest::GetDefaultPrinter();
71 ScopedPrinterHandle printer
;
72 if (!printer
.OpenPrinter(printer_name
.c_str()))
75 const DEVMODE
* dev_mode
= NULL
;
77 lppd
->hDevMode
= NULL
;
78 lppd
->hDevNames
= NULL
;
81 if (info_2
.Init(printer
.Get()))
82 dev_mode
= info_2
.get()->pDevMode
;
86 base::win::ScopedCreateDC
hdc(
87 CreateDC(L
"WINSPOOL", printer_name
.c_str(), NULL
, dev_mode
));
91 size_t dev_mode_size
= dev_mode
->dmSize
+ dev_mode
->dmDriverExtra
;
92 ScopedGlobalAlloc
dev_mode_mem(GlobalAlloc(GMEM_MOVEABLE
, dev_mode_size
));
93 if (!dev_mode_mem
.Get())
95 void* dev_mode_ptr
= GlobalLock(dev_mode_mem
.Get());
98 memcpy(dev_mode_ptr
, dev_mode
, dev_mode_size
);
99 GlobalUnlock(dev_mode_mem
.Get());
103 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pDriverName
);
104 size_t printer_size
=
105 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pPrinterName
);
106 size_t port_size
= 2 + sizeof(wchar_t) * lstrlen(info_2
.get()->pPortName
);
107 size_t dev_names_size
=
108 sizeof(DEVNAMES
) + driver_size
+ printer_size
+ port_size
;
109 ScopedGlobalAlloc
dev_names_mem(GlobalAlloc(GHND
, dev_names_size
));
110 if (!dev_names_mem
.Get())
112 void* dev_names_ptr
= GlobalLock(dev_names_mem
.Get());
115 DEVNAMES
* dev_names
= reinterpret_cast<DEVNAMES
*>(dev_names_ptr
);
116 dev_names
->wDefault
= 1;
117 dev_names
->wDriverOffset
= sizeof(DEVNAMES
) / sizeof(wchar_t);
118 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wDriverOffset
,
119 info_2
.get()->pDriverName
,
121 dev_names
->wDeviceOffset
=
122 dev_names
->wDriverOffset
+ driver_size
/ sizeof(wchar_t);
123 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wDeviceOffset
,
124 info_2
.get()->pPrinterName
,
126 dev_names
->wOutputOffset
=
127 dev_names
->wDeviceOffset
+ printer_size
/ sizeof(wchar_t);
128 memcpy(reinterpret_cast<uint8
*>(dev_names_ptr
) + dev_names
->wOutputOffset
,
129 info_2
.get()->pPortName
,
131 GlobalUnlock(dev_names_mem
.Get());
132 dev_names_ptr
= NULL
;
134 lppd
->hDC
= hdc
.Take();
135 lppd
->hDevMode
= dev_mode_mem
.Take();
136 lppd
->hDevNames
= dev_names_mem
.Take();
141 TEST_F(PrintingContextTest
, PrintAll
) {
142 base::MessageLoop message_loop
;
143 if (IsTestCaseDisabled())
146 MockPrintingContextWin
context(this);
147 context
.AskUserForSettings(
151 base::Bind(&PrintingContextTest::PrintSettingsCallback
,
152 base::Unretained(this)));
153 EXPECT_EQ(PrintingContext::OK
, result());
154 PrintSettings settings
= context
.settings();
155 EXPECT_EQ(settings
.ranges().size(), 0);
158 TEST_F(PrintingContextTest
, Base
) {
159 if (IsTestCaseDisabled())
162 PrintSettings settings
;
163 settings
.set_device_name(GetDefaultPrinter());
165 scoped_ptr
<PrintingContext
> context(PrintingContext::Create(this));
166 EXPECT_EQ(PrintingContext::OK
, context
->InitWithSettings(settings
));
168 // The print may lie to use and may not support world transformation.
170 XFORM random_matrix
= { 1, 0.1f
, 0, 1.5f
, 0, 1 };
171 EXPECT_TRUE(SetWorldTransform(context
->context(), &random_matrix
));
172 EXPECT_TRUE(ModifyWorldTransform(context
->context(), NULL
, MWT_IDENTITY
));
175 } // namespace printing