- add sources.
[platform/framework/web/crosswalk.git] / src / printing / printing_context_win_unittest.cc
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.
4
5 #include <ocidl.h>
6 #include <commdlg.h>
7
8 #include <string>
9
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"
20
21 // This test is automatically disabled if no printer is available.
22 class PrintingContextTest : public PrintingTest<testing::Test> {
23  public:
24   void PrintSettingsCallback(printing::PrintingContext::Result result) {
25     result_ = result;
26     base::MessageLoop::current()->QuitWhenIdle();
27   }
28
29  protected:
30   printing::PrintingContext::Result result() const { return result_; }
31
32  private:
33   printing::PrintingContext::Result result_;
34 };
35
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;
42
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;
48
49   // Painful paperwork.
50   std::wstring printer_name = PrintingContextTest::GetDefaultPrinter();
51   HANDLE printer;
52   if (!OpenPrinter(const_cast<wchar_t*>(printer_name.c_str()), &printer, NULL))
53     return E_FAIL;
54
55   scoped_ptr<uint8[]> buffer;
56   const DEVMODE* dev_mode = NULL;
57   HRESULT result = S_OK;
58   lppd->hDC = NULL;
59   lppd->hDevMode = NULL;
60   lppd->hDevNames = NULL;
61
62   printing::PrinterInfo2 info_2;
63   if (info_2.Init(printer)) {
64     dev_mode = info_2.get()->pDevMode;
65   }
66   if (!dev_mode) {
67     result = E_FAIL;
68     goto Cleanup;
69   }
70
71   if (!printing::PrintingContextWin::AllocateContext(printer_name, dev_mode,
72       &lppd->hDC)) {
73     result = E_FAIL;
74     goto Cleanup;
75   }
76
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;
82   }
83   void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
84   if (!dev_mode_ptr) {
85     result = E_FAIL;
86     goto Cleanup;
87   }
88   memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
89   GlobalUnlock(lppd->hDevMode);
90   dev_mode_ptr = NULL;
91
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 +
97                           port_size;
98   lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
99   if (!lppd->hDevNames) {
100     result = E_FAIL;
101     goto Cleanup;
102   }
103   void* dev_names_ptr = GlobalLock(lppd->hDevNames);
104   if (!dev_names_ptr) {
105     result = E_FAIL;
106     goto Cleanup;
107   }
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;
123
124 Cleanup:
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)) {
131     if (lppd->hDC) {
132       DeleteDC(lppd->hDC);
133     }
134     if (lppd->hDevMode) {
135       GlobalFree(lppd->hDevMode);
136     }
137     if (lppd->hDevNames) {
138       GlobalFree(lppd->hDevNames);
139     }
140   }
141   ClosePrinter(printer);
142   return result;
143 }
144
145 TEST_F(PrintingContextTest, Base) {
146   if (IsTestCaseDisabled())
147     return;
148
149   printing::PrintSettings settings;
150   settings.set_device_name(GetDefaultPrinter());
151   // Initialize it.
152   scoped_ptr<printing::PrintingContext> context(
153       printing::PrintingContext::Create(std::string()));
154   EXPECT_EQ(printing::PrintingContext::OK, context->InitWithSettings(settings));
155
156   // The print may lie to use and may not support world transformation.
157   // Verify right now.
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));
161 }
162
163 TEST_F(PrintingContextTest, PrintAll) {
164   base::MessageLoopForUI loop;
165   if (IsTestCaseDisabled())
166     return;
167
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());
176
177   printing::PrintSettings settings = context.settings();
178   EXPECT_EQ(settings.ranges().size(), 0);
179 }