Use document from preview for System Dialog printing on Windows.
System dialog shows only properties of selected printers, no system dialog with printers.
Removed global Ctrl+Shift+P shortcut on windows.

BUG=374321

Review URL: https://codereview.chromium.org/480303002

Cr-Commit-Position: refs/heads/master@{#292032}
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 07e754d2..43a760c 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -48,6 +48,9 @@
 }
 
 bool PrintViewManager::PrintForSystemDialogNow() {
+#if defined(OS_WIN)
+  NOTREACHED();
+#endif
   return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id()));
 }
 
diff --git a/chrome/browser/printing/printing_message_filter.cc b/chrome/browser/printing/printing_message_filter.cc
index 57db11bd..b1d003f 100644
--- a/chrome/browser/printing/printing_message_filter.cc
+++ b/chrome/browser/printing/printing_message_filter.cc
@@ -424,7 +424,11 @@
     params.params.document_cookie = printer_query->cookie();
     params.pages = PageRange::GetPages(printer_query->settings().ranges());
   }
-  PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params);
+  PrintHostMsg_UpdatePrintSettings::WriteReplyParams(
+      reply_msg,
+      params,
+      printer_query &&
+          (printer_query->last_status() == printing::PrintingContext::CANCEL));
   Send(reply_msg);
   // If user hasn't cancelled.
   if (printer_query.get()) {
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js
index 308c9c2..5da08fce 100644
--- a/chrome/browser/resources/print_preview/native_layer.js
+++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -273,12 +273,18 @@
      * @param {!print_preview.DocumentInfo} documentInfo Document data model.
      * @param {boolean=} opt_isOpenPdfInPreview Whether to open the PDF in the
      *     system's preview application.
+     * @param {boolean=} opt_showSystemDialog Whether to open system dialog for
+     *     advanced settings.
      */
     startPrint: function(destination, printTicketStore, cloudPrintInterface,
-                         documentInfo, opt_isOpenPdfInPreview) {
+                         documentInfo, opt_isOpenPdfInPreview,
+                         opt_showSystemDialog) {
       assert(printTicketStore.isTicketValid(),
              'Trying to print when ticket is not valid');
 
+      assert(!opt_showSystemDialog || (cr.isWindows && destination.isLocal),
+             'Implemented for Windows only');
+
       var ticket = {
         'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),
         'mediaSize': printTicketStore.mediaSize.getValue(),
@@ -304,7 +310,8 @@
         'requestID': -1,
         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
         'pageWidth': documentInfo.pageSize.width,
-        'pageHeight': documentInfo.pageSize.height
+        'pageHeight': documentInfo.pageSize.height,
+        'showSystemDialog': opt_showSystemDialog
       };
 
       if (!destination.isLocal) {
@@ -347,6 +354,7 @@
 
     /** Shows the system's native printing dialog. */
     startShowSystemDialog: function() {
+      assert(!cr.isWindows);
       chrome.send('showSystemDialog');
     },
 
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index 7e25e22..6c16537 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -231,6 +231,13 @@
     this.isInAppKioskMode_ = false;
 
     /**
+     * Whether Print with System Dialog option is available.
+     * @type {boolean}
+     * @private
+     */
+    this.isSystemDialogAvailable_ = false;
+
+    /**
      * State of the print preview UI.
      * @type {print_preview.PrintPreview.UiState_}
      * @private
@@ -243,6 +250,13 @@
      * @private
      */
     this.isPreviewGenerationInProgress_ = true;
+
+    /**
+     * Whether to show system dialog before next printing.
+     * @type {boolean}
+     * @private
+     */
+    this.showSystemDialogBeforeNextPrint_ = false;
   };
 
   /**
@@ -538,7 +552,9 @@
             this.printTicketStore_,
             this.cloudPrintInterface_,
             this.documentInfo_,
-            this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW);
+            this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW,
+            this.showSystemDialogBeforeNextPrint_);
+        this.showSystemDialogBeforeNextPrint_ = false;
       }
       return PrintPreview.PrintAttemptResult_.PRINTED;
     },
@@ -558,6 +574,13 @@
      * @private
      */
     openSystemPrintDialog_: function() {
+      if (!this.shouldShowSystemDialogLink_())
+        return;
+      if (cr.isWindows) {
+        this.showSystemDialogBeforeNextPrint_ = true;
+        this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
+        return;
+      }
       setIsVisible($('system-dialog-throbber'), true);
       this.setIsEnabled_(false);
       this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
@@ -599,9 +622,9 @@
       this.appState_.setInitialized();
 
       $('document-title').innerText = settings.documentTitle;
-      setIsVisible($('system-dialog-link'),
-                   !settings.hidePrintWithSystemDialogLink &&
-                   !settings.isInAppKioskMode);
+      this.isSystemDialogAvailable_ = !settings.hidePrintWithSystemDialogLink &&
+                                      !settings.isInAppKioskMode;
+      setIsVisible($('system-dialog-link'), this.shouldShowSystemDialogLink_());
     },
 
     /**
@@ -1081,6 +1104,23 @@
     },
 
     /**
+     * Returns true if "Print using system dialog" link should be shown for
+     * current destination.
+     * @return {boolean} Returns true if link should be shown.
+     */
+    shouldShowSystemDialogLink_: function() {
+      if (!this.isSystemDialogAvailable_)
+        return false;
+      if (!cr.isWindows)
+        return true;
+      var selectedDest = this.destinationStore_.selectedDestination;
+      return selectedDest &&
+             selectedDest.origin == print_preview.Destination.Origin.LOCAL &&
+             selectedDest.id !=
+                 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
+    },
+
+    /**
      * Called when the open-cloud-print-dialog link is clicked. Opens the Google
      * Cloud Print web dialog.
      * @private
@@ -1105,6 +1145,9 @@
       setIsVisible(
           $('cloud-print-dialog-link'),
           selectedDest && !cr.isChromeOS && !selectedDest.isLocal);
+      setIsVisible(
+          $('system-dialog-link'),
+          this.shouldShowSystemDialogLink_());
       if (selectedDest && this.isInKioskAutoPrintMode_) {
         this.onPrintButtonClick_();
       }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index f872501..9a1159d 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -832,8 +832,15 @@
     ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT);
     SendCloudPrintJob(data.get());
   } else {
-    UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count);
-    ReportUserActionHistogram(PRINT_TO_PRINTER);
+    bool system_dialog = false;
+    settings->GetBoolean(printing::kSettingShowSystemDialog, &system_dialog);
+    if (system_dialog) {
+      UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.SystemDialog", page_count);
+      ReportUserActionHistogram(FALLBACK_TO_ADVANCED_SETTINGS_DIALOG);
+    } else {
+      UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count);
+      ReportUserActionHistogram(PRINT_TO_PRINTER);
+    }
     ReportPrintSettingsStats(*settings);
 
     // This tries to activate the initiator as well, so do not clear the
diff --git a/chrome/common/print_messages.h b/chrome/common/print_messages.h
index 82443e0..6653b21 100644
--- a/chrome/common/print_messages.h
+++ b/chrome/common/print_messages.h
@@ -383,10 +383,11 @@
 
 // The renderer wants to update the current print settings with new
 // |job_settings|.
-IPC_SYNC_MESSAGE_ROUTED2_1(PrintHostMsg_UpdatePrintSettings,
+IPC_SYNC_MESSAGE_ROUTED2_2(PrintHostMsg_UpdatePrintSettings,
                            int /* document_cookie */,
                            base::DictionaryValue /* job_settings */,
-                           PrintMsg_PrintPages_Params /* current_settings */)
+                           PrintMsg_PrintPages_Params /* current_settings */,
+                           bool /* canceled */)
 
 // It's the renderer that controls the printing process when it is generated
 // by javascript. This step is about showing UI to the user to select the
diff --git a/chrome/renderer/chrome_mock_render_thread.cc b/chrome/renderer/chrome_mock_render_thread.cc
index b7f3d11..0cb28ab 100644
--- a/chrome/renderer/chrome_mock_render_thread.cc
+++ b/chrome/renderer/chrome_mock_render_thread.cc
@@ -162,7 +162,10 @@
 void ChromeMockRenderThread::OnUpdatePrintSettings(
     int document_cookie,
     const base::DictionaryValue& job_settings,
-    PrintMsg_PrintPages_Params* params) {
+    PrintMsg_PrintPages_Params* params,
+    bool* canceled) {
+  if (canceled)
+    *canceled = false;
   // Check and make sure the required settings are all there.
   // We don't actually care about the values.
   std::string dummy_string;
diff --git a/chrome/renderer/chrome_mock_render_thread.h b/chrome/renderer/chrome_mock_render_thread.h
index f9e88f80..72a8f2a6 100644
--- a/chrome/renderer/chrome_mock_render_thread.h
+++ b/chrome/renderer/chrome_mock_render_thread.h
@@ -96,7 +96,8 @@
   // For print preview, PrintWebViewHelper will update settings.
   void OnUpdatePrintSettings(int document_cookie,
                              const base::DictionaryValue& job_settings,
-                             PrintMsg_PrintPages_Params* params);
+                             PrintMsg_PrintPages_Params* params,
+                             bool* canceled);
 
   // A mock printer device used for printing tests.
   scoped_ptr<MockPrinter> printer_;
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index 02ccfcff..f1d4cfd7 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -1464,8 +1464,13 @@
   int cookie = print_pages_params_ ?
       print_pages_params_->params.document_cookie : 0;
   PrintMsg_PrintPages_Params settings;
+  bool canceled = false;
   Send(new PrintHostMsg_UpdatePrintSettings(
-      routing_id(), cookie, *job_settings, &settings));
+      routing_id(), cookie, *job_settings, &settings, &canceled));
+  if (canceled) {
+    notify_browser_of_print_failure_ = false;
+    return false;
+  }
 
   if (!job_settings->GetInteger(kPreviewUIID, &settings.params.preview_ui_id)) {
     NOTREACHED();
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc
index 6aba7c6a..db8d735 100644
--- a/printing/backend/win_helper.cc
+++ b/printing/backend/win_helper.cc
@@ -488,4 +488,36 @@
   return out.Pass();
 }
 
+scoped_ptr<DEVMODE, base::FreeDeleter> PromptDevMode(
+    HANDLE printer,
+    const base::string16& printer_name,
+    DEVMODE* in,
+    HWND window,
+    bool* canceled) {
+  LONG buffer_size =
+      DocumentProperties(window,
+                         printer,
+                         const_cast<wchar_t*>(printer_name.c_str()),
+                         NULL,
+                         NULL,
+                         0);
+  if (buffer_size < static_cast<int>(sizeof(DEVMODE)))
+    return scoped_ptr<DEVMODE, base::FreeDeleter>();
+  scoped_ptr<DEVMODE, base::FreeDeleter> out(
+      reinterpret_cast<DEVMODE*>(malloc(buffer_size)));
+  DWORD flags = (in ? (DM_IN_BUFFER) : 0) | DM_OUT_BUFFER | DM_IN_PROMPT;
+  LONG result = DocumentProperties(window,
+                                   printer,
+                                   const_cast<wchar_t*>(printer_name.c_str()),
+                                   out.get(),
+                                   in,
+                                   flags);
+  if (canceled)
+    *canceled = (result == IDCANCEL);
+  if (result != IDOK)
+    return scoped_ptr<DEVMODE, base::FreeDeleter>();
+  CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra);
+  return out.Pass();
+}
+
 }  // namespace printing
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h
index 18d03555..c6665f4 100644
--- a/printing/backend/win_helper.h
+++ b/printing/backend/win_helper.h
@@ -186,6 +186,14 @@
     HANDLE printer,
     DEVMODE* in);
 
+// Prompts for new DEVMODE. If |in| is not NULL copy settings from there.
+PRINTING_EXPORT scoped_ptr<DEVMODE, base::FreeDeleter> PromptDevMode(
+    HANDLE printer,
+    const base::string16& printer_name,
+    DEVMODE* in,
+    HWND window,
+    bool* canceled);
+
 }  // namespace printing
 
 #endif  // PRINTING_BACKEND_WIN_HELPER_H_
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc
index 6ac461c..ed4d1e2 100644
--- a/printing/print_job_constants.cc
+++ b/printing/print_job_constants.cc
@@ -163,6 +163,9 @@
 // Whether to print selection only.
 const char kSettingShouldPrintSelectionOnly[] = "shouldPrintSelectionOnly";
 
+// Whether to print selection only.
+const char kSettingShowSystemDialog[] = "showSystemDialog";
+
 // Indices used to represent first preview page and complete preview document.
 const int FIRST_PAGE_INDEX = 0;
 const int COMPLETE_PREVIEW_DOCUMENT_INDEX = -1;
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index 646191b..35f036d2 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -63,6 +63,7 @@
 PRINTING_EXPORT extern const char kSettingTicket[];
 PRINTING_EXPORT extern const char kSettingShouldPrintBackgrounds[];
 PRINTING_EXPORT extern const char kSettingShouldPrintSelectionOnly[];
+PRINTING_EXPORT extern const char kSettingShowSystemDialog[];
 
 PRINTING_EXPORT extern const int FIRST_PAGE_INDEX;
 PRINTING_EXPORT extern const int COMPLETE_PREVIEW_DOCUMENT_INDEX;
diff --git a/printing/printing_context.cc b/printing/printing_context.cc
index d2b1e68..35288289 100644
--- a/printing/printing_context.cc
+++ b/printing/printing_context.cc
@@ -114,7 +114,11 @@
     return OK;
   }
 
-  return UpdatePrinterSettings(open_in_external_preview);
+  bool show_system_dialog = false;
+  job_settings.GetBoolean(printing::kSettingShowSystemDialog,
+                          &show_system_dialog);
+
+  return UpdatePrinterSettings(open_in_external_preview, show_system_dialog);
 }
 
 }  // namespace printing
diff --git a/printing/printing_context.h b/printing/printing_context.h
index 875c0703..0cc4731 100644
--- a/printing/printing_context.h
+++ b/printing/printing_context.h
@@ -72,7 +72,8 @@
   // Updates printer settings.
   // |external_preview| is true if pdf is going to be opened in external
   // preview. Used by MacOS only now to open Preview.app.
-  virtual Result UpdatePrinterSettings(bool external_preview) = 0;
+  virtual Result UpdatePrinterSettings(bool external_preview,
+                                       bool show_system_dialog) = 0;
 
   // Updates Print Settings. |job_settings| contains all print job
   // settings information. |ranges| has the new page range settings.
diff --git a/printing/printing_context_android.cc b/printing/printing_context_android.cc
index 39f1c6d..64139c8b 100644
--- a/printing/printing_context_android.cc
+++ b/printing/printing_context_android.cc
@@ -170,7 +170,9 @@
 }
 
 PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
-    bool external_preview) {
+    bool external_preview,
+    bool show_system_dialog) {
+  DCHECK(!show_system_dialog);
   DCHECK(!in_print_job_);
 
   // Intentional No-op.
diff --git a/printing/printing_context_android.h b/printing/printing_context_android.h
index 56068a1..fee2259 100644
--- a/printing/printing_context_android.h
+++ b/printing/printing_context_android.h
@@ -37,7 +37,8 @@
       const PrintSettingsCallback& callback) OVERRIDE;
   virtual Result UseDefaultSettings() OVERRIDE;
   virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
-  virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
+  virtual Result UpdatePrinterSettings(bool external_preview,
+                                       bool show_system_dialog) OVERRIDE;
   virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
   virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
   virtual Result NewPage() OVERRIDE;
diff --git a/printing/printing_context_linux.cc b/printing/printing_context_linux.cc
index c267478..926d4e2b 100644
--- a/printing/printing_context_linux.cc
+++ b/printing/printing_context_linux.cc
@@ -106,7 +106,9 @@
 }
 
 PrintingContext::Result PrintingContextLinux::UpdatePrinterSettings(
-    bool external_preview) {
+    bool external_preview,
+    bool show_system_dialog) {
+  DCHECK(!show_system_dialog);
   DCHECK(!in_print_job_);
   DCHECK(!external_preview) << "Not implemented";
 
diff --git a/printing/printing_context_linux.h b/printing/printing_context_linux.h
index 984d7dc..af598062 100644
--- a/printing/printing_context_linux.h
+++ b/printing/printing_context_linux.h
@@ -43,7 +43,8 @@
       const PrintSettingsCallback& callback) OVERRIDE;
   virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
   virtual Result UseDefaultSettings() OVERRIDE;
-  virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
+  virtual Result UpdatePrinterSettings(bool external_preview,
+                                       bool show_system_dialog) OVERRIDE;
   virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
   virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
   virtual Result NewPage() OVERRIDE;
diff --git a/printing/printing_context_mac.h b/printing/printing_context_mac.h
index 9eb924ad..609080e 100644
--- a/printing/printing_context_mac.h
+++ b/printing/printing_context_mac.h
@@ -31,7 +31,8 @@
       const PrintSettingsCallback& callback) OVERRIDE;
   virtual Result UseDefaultSettings() OVERRIDE;
   virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
-  virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
+  virtual Result UpdatePrinterSettings(bool external_preview,
+                                       bool show_system_dialog) OVERRIDE;
   virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
   virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
   virtual Result NewPage() OVERRIDE;
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index fa907b5..23d2d84c 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -168,7 +168,9 @@
 }
 
 PrintingContext::Result PrintingContextMac::UpdatePrinterSettings(
-    bool external_preview) {
+    bool external_preview,
+    bool show_system_dialog) {
+  DCHECK(!show_system_dialog);
   DCHECK(!in_print_job_);
 
   // NOTE: Reset |print_info_| with a copy of |sharedPrintInfo| so as to start
diff --git a/printing/printing_context_no_system_dialog.cc b/printing/printing_context_no_system_dialog.cc
index fd6e1663..7ae10dd 100644
--- a/printing/printing_context_no_system_dialog.cc
+++ b/printing/printing_context_no_system_dialog.cc
@@ -75,7 +75,9 @@
 }
 
 PrintingContext::Result PrintingContextNoSystemDialog::UpdatePrinterSettings(
-    bool external_preview) {
+    bool external_preview,
+    bool show_system_dialog) {
+  DCHECK(!show_system_dialog);
 
   if (settings_.dpi() == 0)
     UseDefaultSettings();
diff --git a/printing/printing_context_no_system_dialog.h b/printing/printing_context_no_system_dialog.h
index fbc69aa..0c5e0b5 100644
--- a/printing/printing_context_no_system_dialog.h
+++ b/printing/printing_context_no_system_dialog.h
@@ -27,7 +27,8 @@
       const PrintSettingsCallback& callback) OVERRIDE;
   virtual Result UseDefaultSettings() OVERRIDE;
   virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
-  virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
+  virtual Result UpdatePrinterSettings(bool external_preview,
+                                       bool show_system_dialog) OVERRIDE;
   virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
   virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
   virtual Result NewPage() OVERRIDE;
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index dd0e2c4..4d7ea92b 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -50,7 +50,7 @@
 }
 
 PrintingContextWin::PrintingContextWin(Delegate* delegate)
-    : PrintingContext(delegate), context_(NULL), dialog_box_(NULL) {
+    : PrintingContext(delegate), context_(NULL) {
 }
 
 PrintingContextWin::~PrintingContextWin() {
@@ -61,63 +61,26 @@
     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));
+  NOTIMPLEMENTED();
 }
 
 PrintingContext::Result PrintingContextWin::UseDefaultSettings() {
   DCHECK(!in_print_job_);
 
-  PRINTDLG dialog_options = { sizeof(PRINTDLG) };
-  dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
-  if (PrintDlg(&dialog_options))
-    return ParseDialogResult(dialog_options);
+  scoped_refptr<PrintBackend> backend = PrintBackend::CreateInstance(NULL);
+  base::string16 default_printer =
+      base::UTF8ToWide(backend->GetDefaultPrinterName());
+  if (!default_printer.empty()) {
+    ScopedPrinterHandle printer;
+    if (printer.OpenPrinter(default_printer.c_str())) {
+      scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
+          CreateDevMode(printer, NULL);
+      if (InitializeSettings(default_printer, dev_mode.get()) == OK)
+        return OK;
+    }
+  }
+
+  ReleaseContext();
 
   // No default printer configured, do we have any printers at all?
   DWORD bytes_needed = 0;
@@ -142,23 +105,15 @@
           continue;
         scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
             CreateDevMode(printer, NULL);
-        if (!dev_mode || !AllocateContext(info_2->pPrinterName, dev_mode.get(),
-                                          &context_)) {
-          continue;
-        }
-        if (InitializeSettings(*dev_mode.get(), info_2->pPrinterName, NULL, 0,
-                               false)) {
+        if (InitializeSettings(info_2->pPrinterName, dev_mode.get()) == OK)
           return OK;
-        }
-        ReleaseContext();
       }
       if (context_)
         return OK;
     }
   }
 
-  ResetSettings();
-  return FAILED;
+  return OnError();
 }
 
 gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() {
@@ -192,7 +147,8 @@
 }
 
 PrintingContext::Result PrintingContextWin::UpdatePrinterSettings(
-    bool external_preview) {
+    bool external_preview,
+    bool show_system_dialog) {
   DCHECK(!in_print_job_);
   DCHECK(!external_preview) << "Not implemented";
 
@@ -256,19 +212,14 @@
   }
 
   // Update data using DocumentProperties.
-  scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get());
-  if (!scoped_dev_mode)
-    return OnError();
-
-  // Set printer then refresh printer settings.
-  if (!AllocateContext(settings_.device_name(), scoped_dev_mode.get(),
-                       &context_)) {
-    return OnError();
+  if (show_system_dialog) {
+    scoped_dev_mode = ShowPrintDialog(
+        printer, delegate_->GetParentView(), scoped_dev_mode.get());
+  } else {
+    scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get());
   }
-  PrintSettingsInitializerWin::InitPrintSettings(context_,
-                                                 *scoped_dev_mode.get(),
-                                                 &settings_);
-  return OK;
+  // Set printer then refresh printer settings.
+  return InitializeSettings(settings_.device_name(), scoped_dev_mode.get());
 }
 
 PrintingContext::Result PrintingContextWin::InitWithSettings(
@@ -279,18 +230,13 @@
 
   // TODO(maruel): settings_.ToDEVMODE()
   ScopedPrinterHandle printer;
-  if (!printer.OpenPrinter(settings_.device_name().c_str())) {
+  if (!printer.OpenPrinter(settings_.device_name().c_str()))
     return FAILED;
-  }
 
-  Result status = OK;
+  scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
+      CreateDevMode(printer, NULL);
 
-  if (!GetPrinterSettings(printer, settings_.device_name()))
-    status = FAILED;
-
-  if (status != OK)
-    ResetSettings();
-  return status;
+  return InitializeSettings(settings_.device_name(), dev_mode.get());
 }
 
 PrintingContext::Result PrintingContextWin::NewDocument(
@@ -374,10 +320,6 @@
   in_print_job_ = false;
   if (context_)
     CancelDC(context_);
-  if (dialog_box_) {
-    DestroyWindow(dialog_box_);
-    dialog_box_dismissed_ = true;
-  }
 }
 
 void PrintingContextWin::ReleaseContext() {
@@ -401,154 +343,31 @@
   return true;
 }
 
-bool PrintingContextWin::InitializeSettings(const DEVMODE& dev_mode,
-                                            const std::wstring& new_device_name,
-                                            const PRINTPAGERANGE* ranges,
-                                            int number_ranges,
-                                            bool selection_only) {
+PrintingContext::Result PrintingContextWin::InitializeSettings(
+    const std::wstring& device_name,
+    DEVMODE* dev_mode) {
+  if (!dev_mode)
+    return OnError();
+
+  ReleaseContext();
+  context_ = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode);
+  if (!context_)
+    return OnError();
+
   skia::InitializeDC(context_);
-  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_device_name(device_name);
+  PrintSettingsInitializerWin::InitPrintSettings(
+      context_, *dev_mode, &settings_);
 
-  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;
+  return OK;
 }
 
-bool PrintingContextWin::GetPrinterSettings(HANDLE printer,
-                                            const std::wstring& device_name) {
-  DCHECK(!in_print_job_);
-
-  scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
-      CreateDevMode(printer, NULL);
-
-  if (!dev_mode || !AllocateContext(device_name, dev_mode.get(), &context_)) {
-    ResetSettings();
-    return false;
-  }
-
-  return InitializeSettings(*dev_mode.get(), device_name, NULL, 0, false);
-}
-
-// static
-bool PrintingContextWin::AllocateContext(const std::wstring& device_name,
-                                         const DEVMODE* dev_mode,
-                                         gfx::NativeDrawingContext* context) {
-  *context = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode);
-  DCHECK(*context);
-  return *context != NULL;
-}
-
-PrintingContext::Result PrintingContextWin::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()) {
-      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);
-      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;
-  }
-}
-
-HRESULT PrintingContextWin::ShowPrintDialog(PRINTDLGEX* options) {
+scoped_ptr<DEVMODE, base::FreeDeleter> PrintingContextWin::ShowPrintDialog(
+    HANDLE printer,
+    gfx::NativeView parent_view,
+    DEVMODE* dev_mode) {
   // 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
@@ -558,57 +377,20 @@
   base::MessageLoop::ScopedNestableTaskAllower allow(
       base::MessageLoop::current());
 
-  return PrintDlgEx(options);
-}
+  bool canceled = false;
+  scoped_ptr<DEVMODE, base::FreeDeleter> result =
+      PromptDevMode(printer,
+                    settings_.device_name(),
+                    dev_mode,
+                    GetRootWindow(parent_view),
+                    &canceled);
 
-PrintingContext::Result PrintingContextWin::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);
+  if (canceled) {
+    result.reset();
+    abort_printing_ = true;
   }
 
-  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()) {
-    context_ = dialog_options.hDC;
-    success = InitializeSettings(*dev_mode, device_name, NULL, 0, false);
-  }
-
-  if (!success && dialog_options.hDC) {
-    DeleteDC(dialog_options.hDC);
-    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;
+  return result.Pass();
 }
 
 }  // namespace printing
diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h
index 94fd041..99a7e3ef 100644
--- a/printing/printing_context_win.h
+++ b/printing/printing_context_win.h
@@ -29,7 +29,8 @@
       const PrintSettingsCallback& callback) OVERRIDE;
   virtual Result UseDefaultSettings() OVERRIDE;
   virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
-  virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
+  virtual Result UpdatePrinterSettings(bool external_preview,
+                                       bool show_system_dialog) OVERRIDE;
   virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
   virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
   virtual Result NewPage() OVERRIDE;
@@ -39,45 +40,24 @@
   virtual void ReleaseContext() OVERRIDE;
   virtual gfx::NativeDrawingContext context() const OVERRIDE;
 
-  // Allocates the HDC for a specific DEVMODE.
-  static bool AllocateContext(const std::wstring& printer_name,
-                              const DEVMODE* dev_mode,
-                              gfx::NativeDrawingContext* context);
-
  protected:
-  virtual HRESULT ShowPrintDialog(PRINTDLGEX* options);
+  virtual scoped_ptr<DEVMODE, base::FreeDeleter> ShowPrintDialog(
+      HANDLE printer,
+      gfx::NativeView parent_view,
+      DEVMODE* dev_mode);
 
  private:
-  // Class that manages the PrintDlgEx() callbacks. This is meant to be a
-  // temporary object used during the Print... dialog display.
-  class CallbackHandler;
-
   // 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.
-  bool InitializeSettings(const DEVMODE& dev_mode,
-                          const std::wstring& new_device_name,
-                          const PRINTPAGERANGE* ranges,
-                          int number_ranges,
-                          bool selection_only);
-
-  // Retrieves the printer's default low-level settings. On Windows, context_ is
-  // allocated with this call.
-  bool GetPrinterSettings(HANDLE printer,
-                          const std::wstring& device_name);
-
-  // Parses the result of a PRINTDLGEX result.
-  Result ParseDialogResultEx(const PRINTDLGEX& dialog_options);
-  Result ParseDialogResult(const PRINTDLG& dialog_options);
+  virtual Result InitializeSettings(const base::string16& device_name,
+                                    DEVMODE* dev_mode);
 
   // The selected printer context.
   HDC context_;
 
-  // The dialog box for the time it is shown.
-  volatile HWND dialog_box_;
-
   DISALLOW_COPY_AND_ASSIGN(PrintingContextWin);
 };
 
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc
index 1d27935..51472491 100644
--- a/printing/printing_context_win_unittest.cc
+++ b/printing/printing_context_win_unittest.cc
@@ -2,20 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <ocidl.h>
-#include <commdlg.h>
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "printing/backend/printing_info_win.h"
-#include "printing/backend/win_helper.h"
-#include "printing/printing_test.h"
-#include "printing/printing_context.h"
 #include "printing/printing_context_win.h"
+
+#include "printing/printing_test.h"
 #include "printing/print_settings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -40,123 +29,6 @@
   PrintingContext::Result result_;
 };
 
-class MockPrintingContextWin : public PrintingContextWin {
- public:
-  MockPrintingContextWin(Delegate* delegate) : PrintingContextWin(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;
-    }
-
-    if (!PrintingContextWin::AllocateContext(
-            printer_name, dev_mode, &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, Base) {
   if (IsTestCaseDisabled())
     return;
@@ -174,20 +46,4 @@
   EXPECT_TRUE(ModifyWorldTransform(context->context(), NULL, MWT_IDENTITY));
 }
 
-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);
-}
-
 }  // namespace printing