Improve performance of registering font preferences
[chromium-blink-merge.git] / printing / printing_context_win_unittest.cc
blob5917b65c928e4d64761b4aaa0b5e357209f1971d
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 <ocidl.h>
6 #include <commdlg.h>
8 #include <string>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "printing/printing_test.h"
14 #include "printing/printing_context.h"
15 #include "printing/printing_context_win.h"
16 #include "printing/print_settings.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 // This test is automatically disabled if no printer is available.
20 class PrintingContextTest : public PrintingTest<testing::Test> {
21 public:
22 void PrintSettingsCallback(printing::PrintingContext::Result result) {
23 result_ = result;
26 protected:
27 printing::PrintingContext::Result result() const { return result_; }
29 private:
30 printing::PrintingContext::Result result_;
33 // This is a fake PrintDlgEx implementation that sets the right fields in
34 // |lppd| to trigger a bug in older revisions of PrintingContext.
35 HRESULT WINAPI PrintDlgExMock(LPPRINTDLGEX lppd) {
36 // The interesting bits:
37 // Pretend the user hit print
38 lppd->dwResultAction = PD_RESULT_PRINT;
40 // Pretend the page range is 1-5, but since lppd->Flags does not have
41 // PD_SELECTION set, this really shouldn't matter.
42 lppd->nPageRanges = 1;
43 lppd->lpPageRanges[0].nFromPage = 1;
44 lppd->lpPageRanges[0].nToPage = 5;
46 // Painful paperwork.
47 std::wstring printer_name = PrintingContextTest::GetDefaultPrinter();
48 HANDLE printer;
49 if (!OpenPrinter(const_cast<wchar_t*>(printer_name.c_str()), &printer, NULL))
50 return E_FAIL;
52 scoped_array<uint8> buffer;
53 DEVMODE* dev_mode = NULL;
54 PRINTER_INFO_2* info_2 = NULL;
55 HRESULT result = S_OK;
56 lppd->hDC = NULL;
57 lppd->hDevMode = NULL;
58 lppd->hDevNames = NULL;
60 printing::PrintingContextWin::GetPrinterHelper(printer, 2, &buffer);
61 if (buffer.get()) {
62 info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get());
63 if (info_2->pDevMode != NULL)
64 dev_mode = info_2->pDevMode;
66 if (!dev_mode) {
67 result = E_FAIL;
68 goto Cleanup;
71 if (!printing::PrintingContextWin::AllocateContext(printer_name, dev_mode,
72 &lppd->hDC)) {
73 result = E_FAIL;
74 goto Cleanup;
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) {
80 result = E_FAIL;
81 goto Cleanup;
83 void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
84 if (!dev_mode_ptr) {
85 result = E_FAIL;
86 goto Cleanup;
88 memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
89 GlobalUnlock(lppd->hDevMode);
90 dev_mode_ptr = NULL;
92 size_t driver_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pDriverName);
93 size_t printer_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPrinterName);
94 size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPortName);
95 size_t dev_names_size = sizeof(DEVNAMES) + driver_size + printer_size +
96 port_size;
97 lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
98 if (!lppd->hDevNames) {
99 result = E_FAIL;
100 goto Cleanup;
102 void* dev_names_ptr = GlobalLock(lppd->hDevNames);
103 if (!dev_names_ptr) {
104 result = E_FAIL;
105 goto Cleanup;
107 DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
108 dev_names->wDefault = 1;
109 dev_names->wDriverOffset = sizeof(DEVNAMES);
110 memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
111 info_2->pDriverName, driver_size);
112 dev_names->wDeviceOffset = dev_names->wDriverOffset + driver_size;
113 memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
114 info_2->pPrinterName, printer_size);
115 dev_names->wOutputOffset = dev_names->wDeviceOffset + printer_size;
116 memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
117 info_2->pPortName, port_size);
118 GlobalUnlock(lppd->hDevNames);
119 dev_names_ptr = NULL;
121 Cleanup:
122 // Note: This section does proper deallocation/free of DC/global handles. We
123 // did not use ScopedHGlobal or ScopedHandle because they did not
124 // perform what we need. Goto's are used based on Windows programming
125 // idiom, to avoid deeply nested if's, and try-catch-finally is not
126 // allowed in Chromium.
127 if (FAILED(result)) {
128 if (lppd->hDC) {
129 DeleteDC(lppd->hDC);
131 if (lppd->hDevMode) {
132 GlobalFree(lppd->hDevMode);
134 if (lppd->hDevNames) {
135 GlobalFree(lppd->hDevNames);
138 ClosePrinter(printer);
139 return result;
142 TEST_F(PrintingContextTest, Base) {
143 // Sometimes ::GetDefaultPrinter() fails? bug 61509.
144 if (IsTestCaseDisabled())
145 return;
147 printing::PrintSettings settings;
148 settings.set_device_name(GetDefaultPrinter());
149 // Initialize it.
150 scoped_ptr<printing::PrintingContext> context(
151 printing::PrintingContext::Create(std::string()));
152 EXPECT_EQ(printing::PrintingContext::OK, context->InitWithSettings(settings));
154 // The print may lie to use and may not support world transformation.
155 // Verify right now.
156 XFORM random_matrix = { 1, 0.1f, 0, 1.5f, 0, 1 };
157 EXPECT_TRUE(SetWorldTransform(context->context(), &random_matrix));
158 EXPECT_TRUE(ModifyWorldTransform(context->context(), NULL, MWT_IDENTITY));
161 TEST_F(PrintingContextTest, PrintAll) {
162 // Sometimes ::GetDefaultPrinter() fails? bug 61509.
163 if (IsTestCaseDisabled())
164 return;
166 std::string dummy_locale;
167 printing::PrintingContextWin context(dummy_locale);
168 context.SetPrintDialog(&PrintDlgExMock);
169 context.AskUserForSettings(
170 NULL, 123, false, base::Bind(&PrintingContextTest::PrintSettingsCallback,
171 base::Unretained(this)));
172 EXPECT_EQ(printing::PrintingContext::OK, result());
173 printing::PrintSettings settings = context.settings();
174 EXPECT_EQ(settings.ranges.size(), 0);