15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/printing_context_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/win_helper.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/print_settings_initializer_win.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/printed_document.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "printing/printing_context_system_dialog_win.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "printing/printing_utils.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/units.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_device.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_AURA)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/remote_window_tree_host_win.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/window.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace printing {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) {
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(DISABLE_BASIC_PRINTING)
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return make_scoped_ptr<PrintingContext>(new PrintingContextWin(delegate));
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else   // DISABLE_BASIC_PRINTING
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return make_scoped_ptr<PrintingContext>(
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new PrintingContextSytemDialogWin(delegate));
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // DISABLE_BASIC_PRINTING
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPrintingContextWin::PrintingContextWin(Delegate* delegate)
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : PrintingContext(delegate), context_(NULL) {
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContextWin::~PrintingContextWin() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseContext();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintingContextWin::AskUserForSettings(
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int max_pages,
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool has_selection,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PrintSettingsCallback& callback) {
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NOTIMPLEMENTED();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::UseDefaultSettings() {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_print_job_);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<PrintBackend> backend = PrintBackend::CreateInstance(NULL);
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::string16 default_printer =
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::UTF8ToWide(backend->GetDefaultPrinterName());
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!default_printer.empty()) {
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedPrinterHandle printer;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (printer.OpenPrinter(default_printer.c_str())) {
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          CreateDevMode(printer.Get(), NULL);
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (InitializeSettings(default_printer, dev_mode.get()) == OK)
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return OK;
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReleaseContext();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No default printer configured, do we have any printers at all?
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD bytes_needed = 0;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD count_returned = 0;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void)::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       NULL, 2, NULL, 0, &bytes_needed, &count_returned);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_needed) {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_GE(bytes_needed, count_returned * sizeof(PRINTER_INFO_2));
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<BYTE[]> printer_info_buffer(new BYTE[bytes_needed]);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOL ret = ::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              NULL, 2, printer_info_buffer.get(),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bytes_needed, &bytes_needed,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &count_returned);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret && count_returned) {  // have printers
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Open the first successfully found printer.
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const PRINTER_INFO_2* info_2 =
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get());
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const PRINTER_INFO_2* info_2_end = info_2 + count_returned;
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      for (; info_2 < info_2_end; ++info_2) {
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ScopedPrinterHandle printer;
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (!printer.OpenPrinter(info_2->pPrinterName))
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            CreateDevMode(printer.Get(), NULL);
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (InitializeSettings(info_2->pPrinterName, dev_mode.get()) == OK)
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          return OK;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (context_)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return OK;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return OnError();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() {
1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Default fallback to Letter size.
1060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  gfx::SizeF paper_size(kLetterWidthInch, kLetterHeightInch);
1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Get settings from locale. Paper type buffer length is at most 4.
1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const int paper_type_buffer_len = 4;
1100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  wchar_t paper_type_buffer[paper_type_buffer_len] = {0};
1110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE, paper_type_buffer,
1120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                paper_type_buffer_len);
1130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (wcslen(paper_type_buffer)) {  // The call succeeded.
1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int paper_code = _wtoi(paper_type_buffer);
1150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    switch (paper_code) {
1160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      case DMPAPER_LEGAL:
1170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        paper_size.SetSize(kLegalWidthInch, kLegalHeightInch);
1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
1190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      case DMPAPER_A4:
1200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        paper_size.SetSize(kA4WidthInch, kA4HeightInch);
1210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      case DMPAPER_A3:
1230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        paper_size.SetSize(kA3WidthInch, kA3HeightInch);
1240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
1250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      default:  // DMPAPER_LETTER is used for default fallback.
1260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
1270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
1280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return gfx::Size(
1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      paper_size.width() * settings_.device_units_per_inch(),
1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      paper_size.height() * settings_.device_units_per_inch());
1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::UpdatePrinterSettings(
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool external_preview,
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool show_system_dialog) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_print_job_);
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!external_preview) << "Not implemented";
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedPrinterHandle printer;
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!printer.OpenPrinter(settings_.device_name().c_str()))
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnError();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make printer changes local to Chrome.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See MSDN documentation regarding DocumentProperties.
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<DEVMODE, base::FreeDeleter> scoped_dev_mode =
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateDevModeWithColor(printer.Get(), settings_.device_name(),
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             settings_.color() != GRAY);
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!scoped_dev_mode)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnError();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DEVMODE* dev_mode = scoped_dev_mode.get();
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dev_mode->dmCopies = std::max(settings_.copies(), 1);
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (dev_mode->dmCopies > 1) {  // do not change unless multiple copies
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dev_mode->dmFields |= DM_COPIES;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE :
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                  DMCOLLATE_FALSE;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (settings_.duplex_mode()) {
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case LONG_EDGE:
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dev_mode->dmFields |= DM_DUPLEX;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dev_mode->dmDuplex = DMDUP_VERTICAL;
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case SHORT_EDGE:
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dev_mode->dmFields |= DM_DUPLEX;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dev_mode->dmDuplex = DMDUP_HORIZONTAL;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case SIMPLEX:
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dev_mode->dmFields |= DM_DUPLEX;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dev_mode->dmDuplex = DMDUP_SIMPLEX;
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      default:  // UNKNOWN_DUPLEX_MODE
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dev_mode->dmFields |= DM_ORIENTATION;
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE :
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      DMORIENT_PORTRAIT;
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const PrintSettings::RequestedMedia& requested_media =
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        settings_.requested_media();
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    static const int kFromUm = 100;  // Windows uses 0.1mm.
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int width = requested_media.size_microns.width() / kFromUm;
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int height = requested_media.size_microns.height() / kFromUm;
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    unsigned id = 0;
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (base::StringToUint(requested_media.vendor_id, &id) && id) {
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dev_mode->dmFields |= DM_PAPERSIZE;
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dev_mode->dmPaperSize = static_cast<short>(id);
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else if (width > 0 && height > 0) {
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dev_mode->dmFields |= DM_PAPERWIDTH;
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dev_mode->dmPaperWidth = width;
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dev_mode->dmFields |= DM_PAPERLENGTH;
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dev_mode->dmPaperLength = height;
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update data using DocumentProperties.
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (show_system_dialog) {
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_dev_mode = ShowPrintDialog(
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        printer.Get(), delegate_->GetParentView(), scoped_dev_mode.get());
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_dev_mode = CreateDevMode(printer.Get(), scoped_dev_mode.get());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Set printer then refresh printer settings.
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return InitializeSettings(settings_.device_name(), scoped_dev_mode.get());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::InitWithSettings(
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PrintSettings& settings) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_print_job_);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings_ = settings;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(maruel): settings_.ToDEVMODE()
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedPrinterHandle printer;
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!printer.OpenPrinter(settings_.device_name().c_str()))
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FAILED;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateDevMode(printer.Get(), NULL);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return InitializeSettings(settings_.device_name(), dev_mode.get());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::NewDocument(
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::string16& document_name) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_print_job_);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!context_)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnError();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the flag used by the AbortPrintJob dialog procedure.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  abort_printing_ = false;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_print_job_ = true;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register the application's AbortProc function with GDI.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SP_ERROR == SetAbortProc(context_, &AbortProc))
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnError();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(SimplifyDocumentTitle(document_name) == document_name);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DOCINFO di = { sizeof(DOCINFO) };
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  di.lpszDocName = document_name.c_str();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Is there a debug dump directory specified? If so, force to print to a file.
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::string16 debug_dump_path =
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      PrintedDocument::CreateDebugDumpPath(document_name,
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           FILE_PATH_LITERAL(".prn")).value();
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!debug_dump_path.empty())
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    di.lpszOutput = debug_dump_path.c_str();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No message loop running in unit tests.
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!base::MessageLoop::current() ||
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         !base::MessageLoop::current()->NestableTasksAllowed());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begin a print job by calling the StartDoc function.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: StartDoc() starts a message loop. That causes a lot of problems with
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPC. Make sure recursive task processing is disabled.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (StartDoc(context_, &di) <= 0)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnError();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::NewPage() {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (abort_printing_)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CANCEL;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context_);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(in_print_job_);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Intentional No-op. PdfMetafileSkia::SafePlayback takes care of calling
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::StartPage().
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::PageDone() {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (abort_printing_)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CANCEL;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(in_print_job_);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Intentional No-op. PdfMetafileSkia::SafePlayback takes care of calling
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ::EndPage().
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintingContext::Result PrintingContextWin::DocumentDone() {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (abort_printing_)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CANCEL;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(in_print_job_);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context_);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform the driver that document has ended.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (EndDoc(context_) <= 0)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnError();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetSettings();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintingContextWin::Cancel() {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  abort_printing_ = true;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_print_job_ = false;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelDC(context_);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintingContextWin::ReleaseContext() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteDC(context_);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_ = NULL;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::NativeDrawingContext PrintingContextWin::context() const {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nCode) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(maruel):  Need a way to find the right instance to set. Should
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // leverage PrintJobManager here?
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // abort_printing_ = true;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPrintingContext::Result PrintingContextWin::InitializeSettings(
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::wstring& device_name,
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DEVMODE* dev_mode) {
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!dev_mode)
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return OnError();
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReleaseContext();
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  context_ = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode);
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!context_)
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return OnError();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  skia::InitializeDC(context_);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_print_job_);
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  settings_.set_device_name(device_name);
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PrintSettingsInitializerWin::InitPrintSettings(
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      context_, *dev_mode, &settings_);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return OK;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciHWND PrintingContextWin::GetRootWindow(gfx::NativeView view) {
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  HWND window = NULL;
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(USE_AURA)
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (view)
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window = view->GetHost()->GetAcceleratedWidget();
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (view && IsWindow(view)) {
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window = GetAncestor(view, GA_ROOTOWNER);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!window) {
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(maruel):  crbug.com/1214347 Get the right browser window instead.
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return GetDesktopWindow();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return window;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<DEVMODE, base::FreeDeleter> PrintingContextWin::ShowPrintDialog(
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    HANDLE printer,
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::NativeView parent_view,
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DEVMODE* dev_mode) {
373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Note that this cannot use ui::BaseShellDialog as the print dialog is
374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // system modal: opening it from a background thread can cause Windows to
375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // get the wrong Z-order which will make the print dialog appear behind the
376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // browser frame (but still being modal) so neither the browser frame nor
377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // the print dialog will get any input. See http://crbug.com/342697
378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // http://crbug.com/180997 for details.
379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::MessageLoop::ScopedNestableTaskAllower allow(
380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::MessageLoop::current());
381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool canceled = false;
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<DEVMODE, base::FreeDeleter> result =
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PromptDevMode(printer,
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    settings_.device_name(),
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    dev_mode,
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    GetRootWindow(parent_view),
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    &canceled);
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (canceled) {
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    result.reset();
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    abort_printing_ = true;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return result.Pass();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace printing
399