summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvitalybuka <vitalybuka@chromium.org>2014-09-09 12:53:33 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-09 19:59:05 +0000
commitf9d0c0ca61adcc78669177583c701607d70cdb0f (patch)
tree87512338a2aa0516805c1b942e199cd0fdcf1bcb
parent75844fdb8b70aa957fc8bc6bba019c2026fde28f (diff)
downloadchromium_src-f9d0c0ca61adcc78669177583c701607d70cdb0f.zip
chromium_src-f9d0c0ca61adcc78669177583c701607d70cdb0f.tar.gz
chromium_src-f9d0c0ca61adcc78669177583c701607d70cdb0f.tar.bz2
Restored printing windows context for builds without preview.
This is code placed into separate file that was removed in https://codereview.chromium.org/478183005 Code is still used by CEF. BUG=374321 NOTRY=true Review URL: https://codereview.chromium.org/557663002 Cr-Commit-Position: refs/heads/master@{#293992}
-rw-r--r--printing/printing.gyp8
-rw-r--r--printing/printing_context_system_dialog_win.cc269
-rw-r--r--printing/printing_context_system_dialog_win.h56
-rw-r--r--printing/printing_context_win.cc44
-rw-r--r--printing/printing_context_win.h24
-rw-r--r--printing/printing_context_win_unittest.cc141
6 files changed, 507 insertions, 35 deletions
diff --git a/printing/printing.gyp b/printing/printing.gyp
index fe2aeda..43f903d 100644
--- a/printing/printing.gyp
+++ b/printing/printing.gyp
@@ -33,6 +33,7 @@
'backend/print_backend_consts.cc',
'backend/print_backend_consts.h',
'backend/print_backend_dummy.cc',
+ 'backend/print_backend_win.cc',
'backend/printing_info_win.cc',
'backend/printing_info_win.h',
'emf_win.cc',
@@ -78,6 +79,10 @@
'printed_pages_source.h',
'printing_context.cc',
'printing_context.h',
+ 'printing_context_system_dialog_win.cc',
+ 'printing_context_system_dialog_win.h',
+ 'printing_context_win.cc',
+ 'printing_context_win.h',
'printing_utils.cc',
'printing_utils.h',
'units.cc',
@@ -120,9 +125,6 @@
'sources': [
'backend/win_helper.cc',
'backend/win_helper.h',
- 'backend/print_backend_win.cc',
- 'printing_context_win.cc',
- 'printing_context_win.h',
],
}],
['chromeos==1',{
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc
new file mode 100644
index 0000000..4e1e8f1
--- /dev/null
+++ b/printing/printing_context_system_dialog_win.cc
@@ -0,0 +1,269 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "printing/printing_context_system_dialog_win.h"
+
+#include "base/message_loop/message_loop.h"
+#include "printing/backend/win_helper.h"
+#include "printing/print_settings_initializer_win.h"
+#include "skia/ext/platform_device.h"
+
+namespace printing {
+
+PrintingContextSytemDialogWin::PrintingContextSytemDialogWin(Delegate* delegate)
+ : PrintingContextWin(delegate), dialog_box_(NULL) {
+}
+
+PrintingContextSytemDialogWin::~PrintingContextSytemDialogWin() {
+}
+
+void PrintingContextSytemDialogWin::AskUserForSettings(
+ int max_pages,
+ bool has_selection,
+ const PrintSettingsCallback& callback) {
+ DCHECK(!in_print_job_);
+ dialog_box_dismissed_ = false;
+
+ HWND window = GetRootWindow(delegate_->GetParentView());
+ DCHECK(window);
+
+ // Show the OS-dependent dialog box.
+ // If the user press
+ // - OK, the settings are reset and reinitialized with the new settings. OK
+ // is
+ // returned.
+ // - Apply then Cancel, the settings are reset and reinitialized with the
+ // new
+ // settings. CANCEL is returned.
+ // - Cancel, the settings are not changed, the previous setting, if it was
+ // initialized before, are kept. CANCEL is returned.
+ // On failure, the settings are reset and FAILED is returned.
+ PRINTDLGEX dialog_options = {sizeof(PRINTDLGEX)};
+ dialog_options.hwndOwner = window;
+ // Disable options we don't support currently.
+ // TODO(maruel): Reuse the previously loaded settings!
+ dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE |
+ PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE;
+ if (!has_selection)
+ dialog_options.Flags |= PD_NOSELECTION;
+
+ PRINTPAGERANGE ranges[32];
+ dialog_options.nStartPage = START_PAGE_GENERAL;
+ if (max_pages) {
+ // Default initialize to print all the pages.
+ memset(ranges, 0, sizeof(ranges));
+ ranges[0].nFromPage = 1;
+ ranges[0].nToPage = max_pages;
+ dialog_options.nPageRanges = 1;
+ dialog_options.nMaxPageRanges = arraysize(ranges);
+ dialog_options.nMinPage = 1;
+ dialog_options.nMaxPage = max_pages;
+ dialog_options.lpPageRanges = ranges;
+ } else {
+ // No need to bother, we don't know how many pages are available.
+ dialog_options.Flags |= PD_NOPAGENUMS;
+ }
+
+ if (ShowPrintDialog(&dialog_options) != S_OK) {
+ ResetSettings();
+ callback.Run(FAILED);
+ }
+
+ // TODO(maruel): Support PD_PRINTTOFILE.
+ callback.Run(ParseDialogResultEx(dialog_options));
+}
+
+void PrintingContextSytemDialogWin::Cancel() {
+ PrintingContextWin::Cancel();
+ if (dialog_box_) {
+ DestroyWindow(dialog_box_);
+ dialog_box_dismissed_ = true;
+ }
+}
+
+HRESULT PrintingContextSytemDialogWin::ShowPrintDialog(PRINTDLGEX* options) {
+ // Note that this cannot use ui::BaseShellDialog as the print dialog is
+ // system modal: opening it from a background thread can cause Windows to
+ // get the wrong Z-order which will make the print dialog appear behind the
+ // browser frame (but still being modal) so neither the browser frame nor
+ // the print dialog will get any input. See http://crbug.com/342697
+ // http://crbug.com/180997 for details.
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+
+ return PrintDlgEx(options);
+}
+
+bool PrintingContextSytemDialogWin::InitializeSettings(
+ const DEVMODE& dev_mode,
+ const std::wstring& new_device_name,
+ const PRINTPAGERANGE* ranges,
+ int number_ranges,
+ bool selection_only) {
+ DCHECK(GetDeviceCaps(context(), CLIPCAPS));
+ DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_STRETCHDIB);
+ DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_BITMAP64);
+ // Some printers don't advertise these.
+ // DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_SCALING);
+ // DCHECK(GetDeviceCaps(context(), SHADEBLENDCAPS) & SB_CONST_ALPHA);
+ // DCHECK(GetDeviceCaps(context(), SHADEBLENDCAPS) & SB_PIXEL_ALPHA);
+
+ // StretchDIBits() support is needed for printing.
+ if (!(GetDeviceCaps(context(), RASTERCAPS) & RC_STRETCHDIB) ||
+ !(GetDeviceCaps(context(), RASTERCAPS) & RC_BITMAP64)) {
+ NOTREACHED();
+ ResetSettings();
+ return false;
+ }
+
+ DCHECK(!in_print_job_);
+ DCHECK(context());
+ PageRanges ranges_vector;
+ if (!selection_only) {
+ // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector.
+ ranges_vector.reserve(number_ranges);
+ for (int i = 0; i < number_ranges; ++i) {
+ PageRange range;
+ // Transfer from 1-based to 0-based.
+ range.from = ranges[i].nFromPage - 1;
+ range.to = ranges[i].nToPage - 1;
+ ranges_vector.push_back(range);
+ }
+ }
+
+ settings_.set_ranges(ranges_vector);
+ settings_.set_device_name(new_device_name);
+ settings_.set_selection_only(selection_only);
+ PrintSettingsInitializerWin::InitPrintSettings(
+ context(), dev_mode, &settings_);
+
+ return true;
+}
+
+PrintingContext::Result PrintingContextSytemDialogWin::ParseDialogResultEx(
+ const PRINTDLGEX& dialog_options) {
+ // If the user clicked OK or Apply then Cancel, but not only Cancel.
+ if (dialog_options.dwResultAction != PD_RESULT_CANCEL) {
+ // Start fresh.
+ ResetSettings();
+
+ DEVMODE* dev_mode = NULL;
+ if (dialog_options.hDevMode) {
+ dev_mode =
+ reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
+ DCHECK(dev_mode);
+ }
+
+ std::wstring device_name;
+ if (dialog_options.hDevNames) {
+ DEVNAMES* dev_names =
+ reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
+ DCHECK(dev_names);
+ if (dev_names) {
+ device_name = reinterpret_cast<const wchar_t*>(dev_names) +
+ dev_names->wDeviceOffset;
+ GlobalUnlock(dialog_options.hDevNames);
+ }
+ }
+
+ bool success = false;
+ if (dev_mode && !device_name.empty()) {
+ set_context(dialog_options.hDC);
+ PRINTPAGERANGE* page_ranges = NULL;
+ DWORD num_page_ranges = 0;
+ bool print_selection_only = false;
+ if (dialog_options.Flags & PD_PAGENUMS) {
+ page_ranges = dialog_options.lpPageRanges;
+ num_page_ranges = dialog_options.nPageRanges;
+ }
+ if (dialog_options.Flags & PD_SELECTION) {
+ print_selection_only = true;
+ }
+ success = InitializeSettings(*dev_mode,
+ device_name,
+ page_ranges,
+ num_page_ranges,
+ print_selection_only);
+ }
+
+ if (!success && dialog_options.hDC) {
+ DeleteDC(dialog_options.hDC);
+ set_context(NULL);
+ }
+
+ if (dev_mode) {
+ GlobalUnlock(dialog_options.hDevMode);
+ }
+ } else {
+ if (dialog_options.hDC) {
+ DeleteDC(dialog_options.hDC);
+ }
+ }
+
+ if (dialog_options.hDevMode != NULL)
+ GlobalFree(dialog_options.hDevMode);
+ if (dialog_options.hDevNames != NULL)
+ GlobalFree(dialog_options.hDevNames);
+
+ switch (dialog_options.dwResultAction) {
+ case PD_RESULT_PRINT:
+ return context() ? OK : FAILED;
+ case PD_RESULT_APPLY:
+ return context() ? CANCEL : FAILED;
+ case PD_RESULT_CANCEL:
+ return CANCEL;
+ default:
+ return FAILED;
+ }
+}
+
+PrintingContext::Result PrintingContextSytemDialogWin::ParseDialogResult(
+ const PRINTDLG& dialog_options) {
+ // If the user clicked OK or Apply then Cancel, but not only Cancel.
+ // Start fresh.
+ ResetSettings();
+
+ DEVMODE* dev_mode = NULL;
+ if (dialog_options.hDevMode) {
+ dev_mode = reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
+ DCHECK(dev_mode);
+ }
+
+ std::wstring device_name;
+ if (dialog_options.hDevNames) {
+ DEVNAMES* dev_names =
+ reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
+ DCHECK(dev_names);
+ if (dev_names) {
+ device_name = reinterpret_cast<const wchar_t*>(
+ reinterpret_cast<const wchar_t*>(dev_names) +
+ dev_names->wDeviceOffset);
+ GlobalUnlock(dialog_options.hDevNames);
+ }
+ }
+
+ bool success = false;
+ if (dev_mode && !device_name.empty()) {
+ set_context(dialog_options.hDC);
+ success = InitializeSettings(*dev_mode, device_name, NULL, 0, false);
+ }
+
+ if (!success && dialog_options.hDC) {
+ DeleteDC(dialog_options.hDC);
+ set_context(NULL);
+ }
+
+ if (dev_mode) {
+ GlobalUnlock(dialog_options.hDevMode);
+ }
+
+ if (dialog_options.hDevMode != NULL)
+ GlobalFree(dialog_options.hDevMode);
+ if (dialog_options.hDevNames != NULL)
+ GlobalFree(dialog_options.hDevNames);
+
+ return context() ? OK : FAILED;
+}
+
+} // namespace printing
diff --git a/printing/printing_context_system_dialog_win.h b/printing/printing_context_system_dialog_win.h
new file mode 100644
index 0000000..9f07b0e
--- /dev/null
+++ b/printing/printing_context_system_dialog_win.h
@@ -0,0 +1,56 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_
+#define PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_
+
+#include <ocidl.h>
+#include <commdlg.h>
+
+#include <string>
+
+#include "printing/printing_context_win.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace printing {
+
+class PRINTING_EXPORT PrintingContextSytemDialogWin
+ : public PrintingContextWin {
+ public:
+ explicit PrintingContextSytemDialogWin(Delegate* delegate);
+ virtual ~PrintingContextSytemDialogWin();
+
+ // PrintingContext implementation.
+ virtual void AskUserForSettings(
+ int max_pages,
+ bool has_selection,
+ const PrintSettingsCallback& callback) OVERRIDE;
+ virtual void Cancel() OVERRIDE;
+
+ private:
+ friend class MockPrintingContextWin;
+
+ virtual HRESULT ShowPrintDialog(PRINTDLGEX* options);
+
+ // Reads the settings from the selected device context. Updates settings_ and
+ // its margins.
+ bool InitializeSettings(const DEVMODE& dev_mode,
+ const std::wstring& new_device_name,
+ const PRINTPAGERANGE* ranges,
+ int number_ranges,
+ bool selection_only);
+
+ // Parses the result of a PRINTDLGEX result.
+ Result ParseDialogResultEx(const PRINTDLGEX& dialog_options);
+ Result ParseDialogResult(const PRINTDLG& dialog_options);
+
+ // The dialog box for the time it is shown.
+ volatile HWND dialog_box_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrintingContextSytemDialogWin);
+};
+
+} // namespace printing
+
+#endif // PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 3e4e6e9..42ebb1a 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -12,6 +12,7 @@
#include "printing/backend/win_helper.h"
#include "printing/print_settings_initializer_win.h"
#include "printing/printed_document.h"
+#include "printing/printing_context_system_dialog_win.h"
#include "printing/printing_utils.h"
#include "printing/units.h"
#include "skia/ext/platform_device.h"
@@ -21,32 +22,16 @@
#include "ui/aura/window.h"
#endif
-namespace {
-
-HWND GetRootWindow(gfx::NativeView view) {
- HWND window = NULL;
-#if defined(USE_AURA)
- if (view)
- window = view->GetHost()->GetAcceleratedWidget();
-#else
- if (view && IsWindow(view)) {
- window = GetAncestor(view, GA_ROOTOWNER);
- }
-#endif
- if (!window) {
- // TODO(maruel): bug 1214347 Get the right browser window instead.
- return GetDesktopWindow();
- }
- return window;
-}
-
-} // anonymous namespace
-
namespace printing {
// static
scoped_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) {
+#if defined(DISABLE_BASIC_PRINTING)
return make_scoped_ptr<PrintingContext>(new PrintingContextWin(delegate));
+#else // DISABLE_BASIC_PRINTING
+ return make_scoped_ptr<PrintingContext>(
+ new PrintingContextSytemDialogWin(delegate));
+#endif // DISABLE_BASIC_PRINTING
}
PrintingContextWin::PrintingContextWin(Delegate* delegate)
@@ -364,6 +349,23 @@ PrintingContext::Result PrintingContextWin::InitializeSettings(
return OK;
}
+HWND PrintingContextWin::GetRootWindow(gfx::NativeView view) {
+ HWND window = NULL;
+#if defined(USE_AURA)
+ if (view)
+ window = view->GetHost()->GetAcceleratedWidget();
+#else
+ if (view && IsWindow(view)) {
+ window = GetAncestor(view, GA_ROOTOWNER);
+ }
+#endif
+ if (!window) {
+ // TODO(maruel): crbug.com/1214347 Get the right browser window instead.
+ return GetDesktopWindow();
+ }
+ return window;
+}
+
scoped_ptr<DEVMODE, base::FreeDeleter> PrintingContextWin::ShowPrintDialog(
HANDLE printer,
gfx::NativeView parent_view,
diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h
index 99a7e3e..e7869dc 100644
--- a/printing/printing_context_win.h
+++ b/printing/printing_context_win.h
@@ -5,18 +5,16 @@
#ifndef PRINTING_PRINTING_CONTEXT_WIN_H_
#define PRINTING_PRINTING_CONTEXT_WIN_H_
-#include <ocidl.h>
-#include <commdlg.h>
-
#include <string>
#include "base/memory/scoped_ptr.h"
-#include "build/build_config.h"
#include "printing/printing_context.h"
#include "ui/gfx/native_widget_types.h"
namespace printing {
+class PrintSettings;
+
class PRINTING_EXPORT PrintingContextWin : public PrintingContext {
public:
explicit PrintingContextWin(Delegate* delegate);
@@ -41,20 +39,26 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext {
virtual gfx::NativeDrawingContext context() const OVERRIDE;
protected:
+ static HWND GetRootWindow(gfx::NativeView view);
+
+ // Reads the settings from the selected device context. Updates settings_ and
+ // its margins.
+ virtual Result InitializeSettings(const base::string16& device_name,
+ DEVMODE* dev_mode);
+
+ HDC contest() const { return context_; }
+
+ void set_context(HDC context) { context_ = context; }
+
+ private:
virtual scoped_ptr<DEVMODE, base::FreeDeleter> ShowPrintDialog(
HANDLE printer,
gfx::NativeView parent_view,
DEVMODE* dev_mode);
- private:
// Used in response to the user canceling the printing.
static BOOL CALLBACK AbortProc(HDC hdc, int nCode);
- // Reads the settings from the selected device context. Updates settings_ and
- // its margins.
- virtual Result InitializeSettings(const base::string16& device_name,
- DEVMODE* dev_mode);
-
// The selected printer context.
HDC context_;
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc
index 5147249..eb6de5ca 100644
--- a/printing/printing_context_win_unittest.cc
+++ b/printing/printing_context_win_unittest.cc
@@ -4,8 +4,13 @@
#include "printing/printing_context_win.h"
-#include "printing/printing_test.h"
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "printing/backend/printing_info_win.h"
+#include "printing/backend/win_helper.h"
#include "printing/print_settings.h"
+#include "printing/printing_context_system_dialog_win.h"
+#include "printing/printing_test.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace printing {
@@ -29,6 +34,140 @@ class PrintingContextTest : public PrintingTest<testing::Test>,
PrintingContext::Result result_;
};
+class MockPrintingContextWin : public PrintingContextSytemDialogWin {
+ public:
+ MockPrintingContextWin(Delegate* delegate)
+ : PrintingContextSytemDialogWin(delegate) {}
+
+ protected:
+ // This is a fake PrintDlgEx implementation that sets the right fields in
+ // |lppd| to trigger a bug in older revisions of PrintingContext.
+ HRESULT ShowPrintDialog(PRINTDLGEX* lppd) OVERRIDE {
+ // The interesting bits:
+ // Pretend the user hit print
+ lppd->dwResultAction = PD_RESULT_PRINT;
+
+ // Pretend the page range is 1-5, but since lppd->Flags does not have
+ // PD_SELECTION set, this really shouldn't matter.
+ lppd->nPageRanges = 1;
+ lppd->lpPageRanges[0].nFromPage = 1;
+ lppd->lpPageRanges[0].nToPage = 5;
+
+ base::string16 printer_name = PrintingContextTest::GetDefaultPrinter();
+ ScopedPrinterHandle printer;
+ if (!printer.OpenPrinter(printer_name.c_str()))
+ return E_FAIL;
+
+ scoped_ptr<uint8[]> buffer;
+ const DEVMODE* dev_mode = NULL;
+ HRESULT result = S_OK;
+ lppd->hDC = NULL;
+ lppd->hDevMode = NULL;
+ lppd->hDevNames = NULL;
+
+ PrinterInfo2 info_2;
+ if (info_2.Init(printer)) {
+ dev_mode = info_2.get()->pDevMode;
+ }
+ if (!dev_mode) {
+ result = E_FAIL;
+ goto Cleanup;
+ }
+
+ lppd->hDC = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode);
+ if (!lppd->hDC) {
+ result = E_FAIL;
+ goto Cleanup;
+ }
+
+ size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
+ lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size);
+ if (!lppd->hDevMode) {
+ result = E_FAIL;
+ goto Cleanup;
+ }
+ void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
+ if (!dev_mode_ptr) {
+ result = E_FAIL;
+ goto Cleanup;
+ }
+ memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
+ GlobalUnlock(lppd->hDevMode);
+ dev_mode_ptr = NULL;
+
+ size_t driver_size =
+ 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pDriverName);
+ size_t printer_size =
+ 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPrinterName);
+ size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPortName);
+ size_t dev_names_size =
+ sizeof(DEVNAMES) + driver_size + printer_size + port_size;
+ lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
+ if (!lppd->hDevNames) {
+ result = E_FAIL;
+ goto Cleanup;
+ }
+ void* dev_names_ptr = GlobalLock(lppd->hDevNames);
+ if (!dev_names_ptr) {
+ result = E_FAIL;
+ goto Cleanup;
+ }
+ DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
+ dev_names->wDefault = 1;
+ dev_names->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
+ memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
+ info_2.get()->pDriverName,
+ driver_size);
+ dev_names->wDeviceOffset =
+ dev_names->wDriverOffset + driver_size / sizeof(wchar_t);
+ memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
+ info_2.get()->pPrinterName,
+ printer_size);
+ dev_names->wOutputOffset =
+ dev_names->wDeviceOffset + printer_size / sizeof(wchar_t);
+ memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
+ info_2.get()->pPortName,
+ port_size);
+ GlobalUnlock(lppd->hDevNames);
+ dev_names_ptr = NULL;
+
+ Cleanup:
+ // Note: This section does proper deallocation/free of DC/global handles. We
+ // did not use ScopedHGlobal or ScopedHandle because they did not
+ // perform what we need. Goto's are used based on Windows programming
+ // idiom, to avoid deeply nested if's, and try-catch-finally is not
+ // allowed in Chromium.
+ if (FAILED(result)) {
+ if (lppd->hDC) {
+ DeleteDC(lppd->hDC);
+ }
+ if (lppd->hDevMode) {
+ GlobalFree(lppd->hDevMode);
+ }
+ if (lppd->hDevNames) {
+ GlobalFree(lppd->hDevNames);
+ }
+ }
+ return result;
+ }
+};
+
+TEST_F(PrintingContextTest, PrintAll) {
+ base::MessageLoop message_loop;
+ if (IsTestCaseDisabled())
+ return;
+
+ MockPrintingContextWin context(this);
+ context.AskUserForSettings(
+ 123,
+ false,
+ base::Bind(&PrintingContextTest::PrintSettingsCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(PrintingContext::OK, result());
+ PrintSettings settings = context.settings();
+ EXPECT_EQ(settings.ranges().size(), 0);
+}
+
TEST_F(PrintingContextTest, Base) {
if (IsTestCaseDisabled())
return;