summaryrefslogtreecommitdiffstats
path: root/embedding/components/printingui/win
diff options
context:
space:
mode:
Diffstat (limited to 'embedding/components/printingui/win')
-rw-r--r--embedding/components/printingui/win/moz.build18
-rw-r--r--embedding/components/printingui/win/nsPrintDialogUtil.cpp854
-rw-r--r--embedding/components/printingui/win/nsPrintDialogUtil.h12
-rw-r--r--embedding/components/printingui/win/nsPrintProgress.cpp293
-rw-r--r--embedding/components/printingui/win/nsPrintProgress.h43
-rw-r--r--embedding/components/printingui/win/nsPrintProgressParams.cpp47
-rw-r--r--embedding/components/printingui/win/nsPrintProgressParams.h27
-rw-r--r--embedding/components/printingui/win/nsPrintingPromptService.cpp341
-rw-r--r--embedding/components/printingui/win/nsPrintingPromptService.h58
9 files changed, 1693 insertions, 0 deletions
diff --git a/embedding/components/printingui/win/moz.build b/embedding/components/printingui/win/moz.build
new file mode 100644
index 000000000..fe7b11b2d
--- /dev/null
+++ b/embedding/components/printingui/win/moz.build
@@ -0,0 +1,18 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ 'nsPrintDialogUtil.cpp',
+ 'nsPrintingPromptService.cpp',
+ 'nsPrintProgress.cpp',
+ 'nsPrintProgressParams.cpp',
+]
+
+EXPORTS += [
+ 'nsPrintDialogUtil.h',
+]
+
+FINAL_LIBRARY = 'xul'
diff --git a/embedding/components/printingui/win/nsPrintDialogUtil.cpp b/embedding/components/printingui/win/nsPrintDialogUtil.cpp
new file mode 100644
index 000000000..896c58e85
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintDialogUtil.cpp
@@ -0,0 +1,854 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* -------------------------------------------------------------------
+To Build This:
+
+ You need to add this to the the makefile.win in mozilla/dom/base:
+
+ .\$(OBJDIR)\nsFlyOwnPrintDialog.obj \
+
+
+ And this to the makefile.win in mozilla/content/build:
+
+WIN_LIBS= \
+ winspool.lib \
+ comctl32.lib \
+ comdlg32.lib
+
+---------------------------------------------------------------------- */
+
+#include "plstr.h"
+#include <windows.h>
+#include <tchar.h>
+
+#include <unknwn.h>
+#include <commdlg.h>
+
+#include "nsIWebBrowserPrint.h"
+#include "nsString.h"
+#include "nsIServiceManager.h"
+#include "nsReadableUtils.h"
+#include "nsIPrintSettings.h"
+#include "nsIPrintSettingsWin.h"
+#include "nsIPrinterEnumerator.h"
+
+#include "nsRect.h"
+
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+
+#include "nsCRT.h"
+#include "prenv.h" /* for PR_GetEnv */
+
+#include <windows.h>
+#include <winspool.h>
+
+// For Localization
+#include "nsIStringBundle.h"
+
+// For NS_CopyUnicodeToNative
+#include "nsNativeCharsetUtils.h"
+
+// This is for extending the dialog
+#include <dlgs.h>
+
+#include "nsWindowsHelpers.h"
+#include "WinUtils.h"
+
+// Default labels for the radio buttons
+static const char* kAsLaidOutOnScreenStr = "As &laid out on the screen";
+static const char* kTheSelectedFrameStr = "The selected &frame";
+static const char* kEachFrameSeparately = "&Each frame separately";
+
+
+//-----------------------------------------------
+// Global Data
+//-----------------------------------------------
+// Identifies which new radio btn was cliked on
+static UINT gFrameSelectedRadioBtn = 0;
+
+// Indicates whether the native print dialog was successfully extended
+static bool gDialogWasExtended = false;
+
+#define PRINTDLG_PROPERTIES "chrome://global/locale/printdialog.properties"
+
+static HWND gParentWnd = nullptr;
+
+//----------------------------------------------------------------------------------
+// Return localized bundle for resource strings
+static nsresult
+GetLocalizedBundle(const char * aPropFileName, nsIStringBundle** aStrBundle)
+{
+ NS_ENSURE_ARG_POINTER(aPropFileName);
+ NS_ENSURE_ARG_POINTER(aStrBundle);
+
+ nsresult rv;
+ nsCOMPtr<nsIStringBundle> bundle;
+
+
+ // Create bundle
+ nsCOMPtr<nsIStringBundleService> stringService =
+ do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv) && stringService) {
+ rv = stringService->CreateBundle(aPropFileName, aStrBundle);
+ }
+
+ return rv;
+}
+
+//--------------------------------------------------------
+// Return localized string
+static nsresult
+GetLocalizedString(nsIStringBundle* aStrBundle, const char* aKey, nsString& oVal)
+{
+ NS_ENSURE_ARG_POINTER(aStrBundle);
+ NS_ENSURE_ARG_POINTER(aKey);
+
+ // Determine default label from string bundle
+ nsXPIDLString valUni;
+ nsAutoString key;
+ key.AssignWithConversion(aKey);
+ nsresult rv = aStrBundle->GetStringFromName(key.get(), getter_Copies(valUni));
+ if (NS_SUCCEEDED(rv) && valUni) {
+ oVal.Assign(valUni);
+ } else {
+ oVal.Truncate();
+ }
+ return rv;
+}
+
+//--------------------------------------------------------
+// Set a multi-byte string in the control
+static void SetTextOnWnd(HWND aControl, const nsString& aStr)
+{
+ nsAutoCString text;
+ if (NS_SUCCEEDED(NS_CopyUnicodeToNative(aStr, text))) {
+ ::SetWindowText(aControl, text.get());
+ }
+}
+
+//--------------------------------------------------------
+// Will get the control and localized string by "key"
+static void SetText(HWND aParent,
+ UINT aId,
+ nsIStringBundle* aStrBundle,
+ const char* aKey)
+{
+ HWND wnd = GetDlgItem (aParent, aId);
+ if (!wnd) {
+ return;
+ }
+ nsAutoString str;
+ nsresult rv = GetLocalizedString(aStrBundle, aKey, str);
+ if (NS_SUCCEEDED(rv)) {
+ SetTextOnWnd(wnd, str);
+ }
+}
+
+//--------------------------------------------------------
+static void SetRadio(HWND aParent,
+ UINT aId,
+ bool aIsSet,
+ bool isEnabled = true)
+{
+ HWND wnd = ::GetDlgItem (aParent, aId);
+ if (!wnd) {
+ return;
+ }
+ if (!isEnabled) {
+ ::EnableWindow(wnd, FALSE);
+ return;
+ }
+ ::EnableWindow(wnd, TRUE);
+ ::SendMessage(wnd, BM_SETCHECK, (WPARAM)aIsSet, (LPARAM)0);
+}
+
+//--------------------------------------------------------
+static void SetRadioOfGroup(HWND aDlg, int aRadId)
+{
+ int radioIds[] = {rad4, rad5, rad6};
+ int numRads = 3;
+
+ for (int i=0;i<numRads;i++) {
+ HWND radWnd = ::GetDlgItem(aDlg, radioIds[i]);
+ if (radWnd != nullptr) {
+ ::SendMessage(radWnd, BM_SETCHECK, (WPARAM)(radioIds[i] == aRadId), (LPARAM)0);
+ }
+ }
+}
+
+//--------------------------------------------------------
+typedef struct {
+ const char * mKeyStr;
+ long mKeyId;
+} PropKeyInfo;
+
+// These are the control ids used in the dialog and
+// defined by MS-Windows in commdlg.h
+static PropKeyInfo gAllPropKeys[] = {
+ {"printFramesTitleWindows", grp3},
+ {"asLaidOutWindows", rad4},
+ {"selectedFrameWindows", rad5},
+ {"separateFramesWindows", rad6},
+ {nullptr, 0}};
+
+//--------------------------------------------------------
+//--------------------------------------------------------
+//--------------------------------------------------------
+//--------------------------------------------------------
+// Get the absolute coords of the child windows relative
+// to its parent window
+static void GetLocalRect(HWND aWnd, RECT& aRect, HWND aParent)
+{
+ ::GetWindowRect(aWnd, &aRect);
+
+ // MapWindowPoints converts screen coordinates to client coordinates.
+ // It works correctly in both left-to-right and right-to-left windows.
+ ::MapWindowPoints(nullptr, aParent, (LPPOINT)&aRect, 2);
+}
+
+//--------------------------------------------------------
+// Show or Hide the control
+static void Show(HWND aWnd, bool bState)
+{
+ if (aWnd) {
+ ::ShowWindow(aWnd, bState?SW_SHOW:SW_HIDE);
+ }
+}
+
+//--------------------------------------------------------
+// Create a child window "control"
+static HWND CreateControl(LPCTSTR aType,
+ DWORD aStyle,
+ HINSTANCE aHInst,
+ HWND aHdlg,
+ int aId,
+ const nsAString& aStr,
+ const nsIntRect& aRect)
+{
+ nsAutoCString str;
+ if (NS_FAILED(NS_CopyUnicodeToNative(aStr, str)))
+ return nullptr;
+
+ HWND hWnd = ::CreateWindow (aType, str.get(),
+ WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | aStyle,
+ aRect.x, aRect.y, aRect.width, aRect.height,
+ (HWND)aHdlg, (HMENU)(intptr_t)aId,
+ aHInst, nullptr);
+ if (hWnd == nullptr) return nullptr;
+
+ // get the native font for the dialog and
+ // set it into the new control
+ HFONT hFont = (HFONT)::SendMessage(aHdlg, WM_GETFONT, (WPARAM)0, (LPARAM)0);
+ if (hFont != nullptr) {
+ ::SendMessage(hWnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0);
+ }
+ return hWnd;
+}
+
+//--------------------------------------------------------
+// Create a Radio Button
+static HWND CreateRadioBtn(HINSTANCE aHInst,
+ HWND aHdlg,
+ int aId,
+ const char* aStr,
+ const nsIntRect& aRect)
+{
+ nsString cStr;
+ cStr.AssignWithConversion(aStr);
+ return CreateControl("BUTTON", BS_RADIOBUTTON, aHInst, aHdlg, aId, cStr, aRect);
+}
+
+//--------------------------------------------------------
+// Create a Group Box
+static HWND CreateGroupBox(HINSTANCE aHInst,
+ HWND aHdlg,
+ int aId,
+ const nsAString& aStr,
+ const nsIntRect& aRect)
+{
+ return CreateControl("BUTTON", BS_GROUPBOX, aHInst, aHdlg, aId, aStr, aRect);
+}
+
+//--------------------------------------------------------
+// Localizes and initializes the radio buttons and group
+static void InitializeExtendedDialog(HWND hdlg, int16_t aHowToEnableFrameUI)
+{
+ MOZ_ASSERT(aHowToEnableFrameUI != nsIPrintSettings::kFrameEnableNone,
+ "should not be called");
+
+ // Localize the new controls in the print dialog
+ nsCOMPtr<nsIStringBundle> strBundle;
+ if (NS_SUCCEEDED(GetLocalizedBundle(PRINTDLG_PROPERTIES, getter_AddRefs(strBundle)))) {
+ int32_t i = 0;
+ while (gAllPropKeys[i].mKeyStr != nullptr) {
+ SetText(hdlg, gAllPropKeys[i].mKeyId, strBundle, gAllPropKeys[i].mKeyStr);
+ i++;
+ }
+ }
+
+ // Set up radio buttons
+ if (aHowToEnableFrameUI == nsIPrintSettings::kFrameEnableAll) {
+ SetRadio(hdlg, rad4, false);
+ SetRadio(hdlg, rad5, true);
+ SetRadio(hdlg, rad6, false);
+ // set default so user doesn't have to actually press on it
+ gFrameSelectedRadioBtn = rad5;
+
+ } else { // nsIPrintSettings::kFrameEnableAsIsAndEach
+ SetRadio(hdlg, rad4, false);
+ SetRadio(hdlg, rad5, false, false);
+ SetRadio(hdlg, rad6, true);
+ // set default so user doesn't have to actually press on it
+ gFrameSelectedRadioBtn = rad6;
+ }
+}
+
+
+//--------------------------------------------------------
+// Special Hook Procedure for handling the print dialog messages
+static UINT CALLBACK PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+
+ if (uiMsg == WM_COMMAND) {
+ UINT id = LOWORD(wParam);
+ if (id == rad4 || id == rad5 || id == rad6) {
+ gFrameSelectedRadioBtn = id;
+ SetRadioOfGroup(hdlg, id);
+ }
+
+ } else if (uiMsg == WM_INITDIALOG) {
+ PRINTDLG * printDlg = (PRINTDLG *)lParam;
+ if (printDlg == nullptr) return 0L;
+
+ int16_t howToEnableFrameUI = (int16_t)printDlg->lCustData;
+ // don't add frame options if they would be disabled anyway
+ // because there are no frames
+ if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableNone)
+ return TRUE;
+
+ HINSTANCE hInst = (HINSTANCE)::GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
+ if (hInst == nullptr) return 0L;
+
+ // Start by getting the local rects of several of the controls
+ // so we can calculate where the new controls are
+ HWND wnd = ::GetDlgItem(hdlg, grp1);
+ if (wnd == nullptr) return 0L;
+ RECT dlgRect;
+ GetLocalRect(wnd, dlgRect, hdlg);
+
+ wnd = ::GetDlgItem(hdlg, rad1); // this is the top control "All"
+ if (wnd == nullptr) return 0L;
+ RECT rad1Rect;
+ GetLocalRect(wnd, rad1Rect, hdlg);
+
+ wnd = ::GetDlgItem(hdlg, rad2); // this is the bottom control "Selection"
+ if (wnd == nullptr) return 0L;
+ RECT rad2Rect;
+ GetLocalRect(wnd, rad2Rect, hdlg);
+
+ wnd = ::GetDlgItem(hdlg, rad3); // this is the middle control "Pages"
+ if (wnd == nullptr) return 0L;
+ RECT rad3Rect;
+ GetLocalRect(wnd, rad3Rect, hdlg);
+
+ HWND okWnd = ::GetDlgItem(hdlg, IDOK);
+ if (okWnd == nullptr) return 0L;
+ RECT okRect;
+ GetLocalRect(okWnd, okRect, hdlg);
+
+ wnd = ::GetDlgItem(hdlg, grp4); // this is the "Print range" groupbox
+ if (wnd == nullptr) return 0L;
+ RECT prtRect;
+ GetLocalRect(wnd, prtRect, hdlg);
+
+
+ // calculate various different "gaps" for layout purposes
+
+ int rbGap = rad3Rect.top - rad1Rect.bottom; // gap between radiobtns
+ int grpBotGap = dlgRect.bottom - rad2Rect.bottom; // gap from bottom rb to bottom of grpbox
+ int grpGap = dlgRect.top - prtRect.bottom ; // gap between group boxes
+ int top = dlgRect.bottom + grpGap;
+ int radHgt = rad1Rect.bottom - rad1Rect.top + 1; // top of new group box
+ int y = top+(rad1Rect.top-dlgRect.top); // starting pos of first radio
+ int rbWidth = dlgRect.right - rad1Rect.left - 5; // measure from rb left to the edge of the groupbox
+ // (5 is arbitrary)
+ nsIntRect rect;
+
+ // Create and position the radio buttons
+ //
+ // If any one control cannot be created then
+ // hide the others and bail out
+ //
+ rect.SetRect(rad1Rect.left, y, rbWidth,radHgt);
+ HWND rad4Wnd = CreateRadioBtn(hInst, hdlg, rad4, kAsLaidOutOnScreenStr, rect);
+ if (rad4Wnd == nullptr) return 0L;
+ y += radHgt + rbGap;
+
+ rect.SetRect(rad1Rect.left, y, rbWidth, radHgt);
+ HWND rad5Wnd = CreateRadioBtn(hInst, hdlg, rad5, kTheSelectedFrameStr, rect);
+ if (rad5Wnd == nullptr) {
+ Show(rad4Wnd, FALSE); // hide
+ return 0L;
+ }
+ y += radHgt + rbGap;
+
+ rect.SetRect(rad1Rect.left, y, rbWidth, radHgt);
+ HWND rad6Wnd = CreateRadioBtn(hInst, hdlg, rad6, kEachFrameSeparately, rect);
+ if (rad6Wnd == nullptr) {
+ Show(rad4Wnd, FALSE); // hide
+ Show(rad5Wnd, FALSE); // hide
+ return 0L;
+ }
+ y += radHgt + grpBotGap;
+
+ // Create and position the group box
+ rect.SetRect (dlgRect.left, top, dlgRect.right-dlgRect.left+1, y-top+1);
+ HWND grpBoxWnd = CreateGroupBox(hInst, hdlg, grp3, NS_LITERAL_STRING("Print Frame"), rect);
+ if (grpBoxWnd == nullptr) {
+ Show(rad4Wnd, FALSE); // hide
+ Show(rad5Wnd, FALSE); // hide
+ Show(rad6Wnd, FALSE); // hide
+ return 0L;
+ }
+
+ // Here we figure out the old height of the dlg
+ // then figure its gap from the old grpbx to the bottom
+ // then size the dlg
+ RECT pr, cr;
+ ::GetWindowRect(hdlg, &pr);
+ ::GetClientRect(hdlg, &cr);
+
+ int dlgHgt = (cr.bottom - cr.top) + 1;
+ int bottomGap = dlgHgt - okRect.bottom;
+ pr.bottom += (dlgRect.bottom-dlgRect.top) + grpGap + 1 - (dlgHgt-dlgRect.bottom) + bottomGap;
+
+ ::SetWindowPos(hdlg, nullptr, pr.left, pr.top, pr.right-pr.left+1, pr.bottom-pr.top+1,
+ SWP_NOMOVE|SWP_NOREDRAW|SWP_NOZORDER);
+
+ // figure out the new height of the dialog
+ ::GetClientRect(hdlg, &cr);
+ dlgHgt = (cr.bottom - cr.top) + 1;
+
+ // Reposition the OK and Cancel btns
+ int okHgt = okRect.bottom - okRect.top + 1;
+ ::SetWindowPos(okWnd, nullptr, okRect.left, dlgHgt-bottomGap-okHgt, 0, 0,
+ SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER);
+
+ HWND cancelWnd = ::GetDlgItem(hdlg, IDCANCEL);
+ if (cancelWnd == nullptr) return 0L;
+
+ RECT cancelRect;
+ GetLocalRect(cancelWnd, cancelRect, hdlg);
+ int cancelHgt = cancelRect.bottom - cancelRect.top + 1;
+ ::SetWindowPos(cancelWnd, nullptr, cancelRect.left, dlgHgt-bottomGap-cancelHgt, 0, 0,
+ SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER);
+
+ // localize and initialize the groupbox and radiobuttons
+ InitializeExtendedDialog(hdlg, howToEnableFrameUI);
+
+ // Looks like we were able to extend the dialog
+ gDialogWasExtended = true;
+ return TRUE;
+ }
+ return 0L;
+}
+
+//----------------------------------------------------------------------------------
+// Returns a Global Moveable Memory Handle to a DevMode
+// from the Printer by the name of aPrintName
+//
+// NOTE:
+// This function assumes that aPrintName has already been converted from
+// unicode
+//
+static nsReturnRef<nsHGLOBAL>
+CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName,
+ nsIPrintSettings* aPS)
+{
+ nsHPRINTER hPrinter = nullptr;
+ // const cast kludge for silly Win32 api's
+ LPWSTR printName = const_cast<wchar_t*>(static_cast<const wchar_t*>(aPrintName.get()));
+ BOOL status = ::OpenPrinterW(printName, &hPrinter, nullptr);
+ if (!status) {
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ // Make sure hPrinter is closed on all paths
+ nsAutoPrinter autoPrinter(hPrinter);
+
+ // Get the buffer size
+ LONG needed = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr,
+ nullptr, 0);
+ if (needed < 0) {
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ // Allocate a buffer of the correct size.
+ nsAutoDevMode newDevMode((LPDEVMODEW)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,
+ needed));
+ if (!newDevMode) {
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ nsHGLOBAL hDevMode = ::GlobalAlloc(GHND, needed);
+ nsAutoGlobalMem globalDevMode(hDevMode);
+ if (!hDevMode) {
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ LONG ret = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, newDevMode,
+ nullptr, DM_OUT_BUFFER);
+ if (ret != IDOK) {
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ // Lock memory and copy contents from DEVMODE (current printer)
+ // to Global Memory DEVMODE
+ LPDEVMODEW devMode = (DEVMODEW *)::GlobalLock(hDevMode);
+ if (!devMode) {
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ memcpy(devMode, newDevMode.get(), needed);
+ // Initialize values from the PrintSettings
+ nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
+ MOZ_ASSERT(psWin);
+ psWin->CopyToNative(devMode);
+
+ // Sets back the changes we made to the DevMode into the Printer Driver
+ ret = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode,
+ DM_IN_BUFFER | DM_OUT_BUFFER);
+ if (ret != IDOK) {
+ ::GlobalUnlock(hDevMode);
+ return nsReturnRef<nsHGLOBAL>();
+ }
+
+ ::GlobalUnlock(hDevMode);
+
+ return globalDevMode.out();
+}
+
+//------------------------------------------------------------------
+// helper
+static void GetDefaultPrinterNameFromGlobalPrinters(nsXPIDLString &printerName)
+{
+ nsCOMPtr<nsIPrinterEnumerator> prtEnum = do_GetService("@mozilla.org/gfx/printerenumerator;1");
+ if (prtEnum) {
+ prtEnum->GetDefaultPrinterName(getter_Copies(printerName));
+ }
+}
+
+// Determine whether we have a completely native dialog
+// or whether we cshould extend it
+static bool ShouldExtendPrintDialog()
+{
+ nsresult rv;
+ nsCOMPtr<nsIPrefService> prefs =
+ do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, true);
+ nsCOMPtr<nsIPrefBranch> prefBranch;
+ rv = prefs->GetBranch(nullptr, getter_AddRefs(prefBranch));
+ NS_ENSURE_SUCCESS(rv, true);
+
+ bool result;
+ rv = prefBranch->GetBoolPref("print.extend_native_print_dialog", &result);
+ NS_ENSURE_SUCCESS(rv, true);
+ return result;
+}
+
+//------------------------------------------------------------------
+// Displays the native Print Dialog
+static nsresult
+ShowNativePrintDialog(HWND aHWnd,
+ nsIPrintSettings* aPrintSettings)
+{
+ //NS_ENSURE_ARG_POINTER(aHWnd);
+ NS_ENSURE_ARG_POINTER(aPrintSettings);
+
+ gDialogWasExtended = false;
+
+ // Get the Print Name to be used
+ nsXPIDLString printerName;
+ aPrintSettings->GetPrinterName(getter_Copies(printerName));
+
+ // If there is no name then use the default printer
+ if (printerName.IsEmpty()) {
+ GetDefaultPrinterNameFromGlobalPrinters(printerName);
+ } else {
+ HANDLE hPrinter = nullptr;
+ if(!::OpenPrinterW(const_cast<wchar_t*>(static_cast<const wchar_t*>(printerName.get())),
+ &hPrinter, nullptr)) {
+ // If the last used printer is not found, we should use default printer.
+ GetDefaultPrinterNameFromGlobalPrinters(printerName);
+ } else {
+ ::ClosePrinter(hPrinter);
+ }
+ }
+
+ // Now create a DEVNAMES struct so the the dialog is initialized correctly.
+
+ uint32_t len = printerName.Length();
+ nsHGLOBAL hDevNames = ::GlobalAlloc(GHND, sizeof(wchar_t) * (len + 1)
+ + sizeof(DEVNAMES));
+ nsAutoGlobalMem autoDevNames(hDevNames);
+ if (!hDevNames) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ DEVNAMES* pDevNames = (DEVNAMES*)::GlobalLock(hDevNames);
+ if (!pDevNames) {
+ return NS_ERROR_FAILURE;
+ }
+ pDevNames->wDriverOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
+ pDevNames->wDeviceOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
+ pDevNames->wOutputOffset = sizeof(DEVNAMES)/sizeof(wchar_t)+len;
+ pDevNames->wDefault = 0;
+
+ memcpy(pDevNames+1, printerName, (len + 1) * sizeof(wchar_t));
+ ::GlobalUnlock(hDevNames);
+
+ // Create a Moveable Memory Object that holds a new DevMode
+ // from the Printer Name
+ // The PRINTDLG.hDevMode requires that it be a moveable memory object
+ // NOTE: autoDevMode is automatically freed when any error occurred
+ nsAutoGlobalMem autoDevMode(CreateGlobalDevModeAndInit(printerName, aPrintSettings));
+
+ // Prepare to Display the Print Dialog
+ PRINTDLGW prntdlg;
+ memset(&prntdlg, 0, sizeof(PRINTDLGW));
+
+ prntdlg.lStructSize = sizeof(prntdlg);
+ prntdlg.hwndOwner = aHWnd;
+ prntdlg.hDevMode = autoDevMode.get();
+ prntdlg.hDevNames = hDevNames;
+ prntdlg.hDC = nullptr;
+ prntdlg.Flags = PD_ALLPAGES | PD_RETURNIC |
+ PD_USEDEVMODECOPIESANDCOLLATE | PD_COLLATE;
+
+ // if there is a current selection then enable the "Selection" radio button
+ int16_t howToEnableFrameUI = nsIPrintSettings::kFrameEnableNone;
+ bool isOn;
+ aPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &isOn);
+ if (!isOn) {
+ prntdlg.Flags |= PD_NOSELECTION;
+ }
+ aPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI);
+
+ int32_t pg = 1;
+ aPrintSettings->GetStartPageRange(&pg);
+ prntdlg.nFromPage = pg;
+
+ aPrintSettings->GetEndPageRange(&pg);
+ prntdlg.nToPage = pg;
+
+ prntdlg.nMinPage = 1;
+ prntdlg.nMaxPage = 0xFFFF;
+ prntdlg.nCopies = 1;
+ prntdlg.lpfnSetupHook = nullptr;
+ prntdlg.lpSetupTemplateName = nullptr;
+ prntdlg.hPrintTemplate = nullptr;
+ prntdlg.hSetupTemplate = nullptr;
+
+ prntdlg.hInstance = nullptr;
+ prntdlg.lpPrintTemplateName = nullptr;
+
+ if (!ShouldExtendPrintDialog()) {
+ prntdlg.lCustData = 0;
+ prntdlg.lpfnPrintHook = nullptr;
+ } else {
+ // Set up print dialog "hook" procedure for extending the dialog
+ prntdlg.lCustData = (DWORD)howToEnableFrameUI;
+ prntdlg.lpfnPrintHook = (LPPRINTHOOKPROC)PrintHookProc;
+ prntdlg.Flags |= PD_ENABLEPRINTHOOK;
+ }
+
+ BOOL result;
+ {
+ mozilla::widget::WinUtils::AutoSystemDpiAware dpiAwareness;
+ result = ::PrintDlgW(&prntdlg);
+ }
+
+ if (TRUE == result) {
+ // check to make sure we don't have any nullptr pointers
+ NS_ENSURE_TRUE(aPrintSettings && prntdlg.hDevMode, NS_ERROR_FAILURE);
+
+ if (prntdlg.hDevNames == nullptr) {
+ return NS_ERROR_FAILURE;
+ }
+ // Lock the deviceNames and check for nullptr
+ DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(prntdlg.hDevNames);
+ if (devnames == nullptr) {
+ return NS_ERROR_FAILURE;
+ }
+
+ char16_t* device = &(((char16_t *)devnames)[devnames->wDeviceOffset]);
+ char16_t* driver = &(((char16_t *)devnames)[devnames->wDriverOffset]);
+
+ // Check to see if the "Print To File" control is checked
+ // then take the name from devNames and set it in the PrintSettings
+ //
+ // NOTE:
+ // As per Microsoft SDK documentation the returned value offset from
+ // devnames->wOutputOffset is either "FILE:" or nullptr
+ // if the "Print To File" checkbox is checked it MUST be "FILE:"
+ // We assert as an extra safety check.
+ if (prntdlg.Flags & PD_PRINTTOFILE) {
+ char16ptr_t fileName = &(((wchar_t *)devnames)[devnames->wOutputOffset]);
+ NS_ASSERTION(wcscmp(fileName, L"FILE:") == 0, "FileName must be `FILE:`");
+ aPrintSettings->SetToFileName(fileName);
+ aPrintSettings->SetPrintToFile(true);
+ } else {
+ // clear "print to file" info
+ aPrintSettings->SetPrintToFile(false);
+ aPrintSettings->SetToFileName(nullptr);
+ }
+
+ nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings));
+ if (!psWin) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Setup local Data members
+ psWin->SetDeviceName(device);
+ psWin->SetDriverName(driver);
+
+#if defined(DEBUG_rods) || defined(DEBUG_dcone)
+ wprintf(L"printer: driver %s, device %s flags: %d\n", driver, device, prntdlg.Flags);
+#endif
+ // fill the print options with the info from the dialog
+
+ aPrintSettings->SetPrinterName(device);
+
+ if (prntdlg.Flags & PD_SELECTION) {
+ aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSelection);
+
+ } else if (prntdlg.Flags & PD_PAGENUMS) {
+ aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange);
+ aPrintSettings->SetStartPageRange(prntdlg.nFromPage);
+ aPrintSettings->SetEndPageRange(prntdlg.nToPage);
+
+ } else { // (prntdlg.Flags & PD_ALLPAGES)
+ aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
+ }
+
+ if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) {
+ // make sure the dialog got extended
+ if (gDialogWasExtended) {
+ // check to see about the frame radio buttons
+ switch (gFrameSelectedRadioBtn) {
+ case rad4:
+ aPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
+ break;
+ case rad5:
+ aPrintSettings->SetPrintFrameType(nsIPrintSettings::kSelectedFrame);
+ break;
+ case rad6:
+ aPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
+ break;
+ } // switch
+ } else {
+ // if it didn't get extended then have it default to printing
+ // each frame separately
+ aPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
+ }
+ } else {
+ aPrintSettings->SetPrintFrameType(nsIPrintSettings::kNoFrames);
+ }
+ // Unlock DeviceNames
+ ::GlobalUnlock(prntdlg.hDevNames);
+
+ // Transfer the settings from the native data to the PrintSettings
+ LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(prntdlg.hDevMode);
+ if (!devMode || !prntdlg.hDC) {
+ return NS_ERROR_FAILURE;
+ }
+ psWin->SetDevMode(devMode); // copies DevMode
+ psWin->CopyFromNative(prntdlg.hDC, devMode);
+ ::GlobalUnlock(prntdlg.hDevMode);
+ ::DeleteDC(prntdlg.hDC);
+
+#if defined(DEBUG_rods) || defined(DEBUG_dcone)
+ bool printSelection = prntdlg.Flags & PD_SELECTION;
+ bool printAllPages = prntdlg.Flags & PD_ALLPAGES;
+ bool printNumPages = prntdlg.Flags & PD_PAGENUMS;
+ int32_t fromPageNum = 0;
+ int32_t toPageNum = 0;
+
+ if (printNumPages) {
+ fromPageNum = prntdlg.nFromPage;
+ toPageNum = prntdlg.nToPage;
+ }
+ if (printSelection) {
+ printf("Printing the selection\n");
+
+ } else if (printAllPages) {
+ printf("Printing all the pages\n");
+
+ } else {
+ printf("Printing from page no. %d to %d\n", fromPageNum, toPageNum);
+ }
+#endif
+
+ } else {
+ ::SetFocus(aHWnd);
+ aPrintSettings->SetIsCancelled(true);
+ return NS_ERROR_ABORT;
+ }
+
+ return NS_OK;
+}
+
+//------------------------------------------------------------------
+static void
+PrepareForPrintDialog(nsIWebBrowserPrint* aWebBrowserPrint, nsIPrintSettings* aPS)
+{
+ NS_ASSERTION(aWebBrowserPrint, "Can't be null");
+ NS_ASSERTION(aPS, "Can't be null");
+
+ bool isFramesetDocument;
+ bool isFramesetFrameSelected;
+ bool isIFrameSelected;
+ bool isRangeSelection;
+
+ aWebBrowserPrint->GetIsFramesetDocument(&isFramesetDocument);
+ aWebBrowserPrint->GetIsFramesetFrameSelected(&isFramesetFrameSelected);
+ aWebBrowserPrint->GetIsIFrameSelected(&isIFrameSelected);
+ aWebBrowserPrint->GetIsRangeSelection(&isRangeSelection);
+
+ // Setup print options for UI
+ if (isFramesetDocument) {
+ if (isFramesetFrameSelected) {
+ aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll);
+ } else {
+ aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach);
+ }
+ } else {
+ aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone);
+ }
+
+ // Now determine how to set up the Frame print UI
+ aPS->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isRangeSelection || isIFrameSelected);
+
+}
+
+//----------------------------------------------------------------------------------
+//-- Show Print Dialog
+//----------------------------------------------------------------------------------
+nsresult NativeShowPrintDialog(HWND aHWnd,
+ nsIWebBrowserPrint* aWebBrowserPrint,
+ nsIPrintSettings* aPrintSettings)
+{
+ PrepareForPrintDialog(aWebBrowserPrint, aPrintSettings);
+
+ nsresult rv = ShowNativePrintDialog(aHWnd, aPrintSettings);
+ if (aHWnd) {
+ ::DestroyWindow(aHWnd);
+ }
+
+ return rv;
+}
+
diff --git a/embedding/components/printingui/win/nsPrintDialogUtil.h b/embedding/components/printingui/win/nsPrintDialogUtil.h
new file mode 100644
index 000000000..ada3da239
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintDialogUtil.h
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsFlyOwnDialog_h___
+#define nsFlyOwnDialog_h___
+
+nsresult NativeShowPrintDialog(HWND aHWnd,
+ nsIWebBrowserPrint* aWebBrowserPrint,
+ nsIPrintSettings* aPrintSettings);
+
+#endif /* nsFlyOwnDialog_h___ */
diff --git a/embedding/components/printingui/win/nsPrintProgress.cpp b/embedding/components/printingui/win/nsPrintProgress.cpp
new file mode 100644
index 000000000..0b1c10a2c
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintProgress.cpp
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsPrintProgress.h"
+
+#include "nsArray.h"
+#include "nsIBaseWindow.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIXULWindow.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsPIDOMWindow.h"
+
+#if 0
+NS_IMPL_ADDREF(nsPrintProgress)
+NS_IMPL_RELEASE(nsPrintProgress)
+#else
+NS_IMETHODIMP_(MozExternalRefCountType) nsPrintProgress::AddRef(void)
+{
+ NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
+ nsrefcnt count;
+ count = ++mRefCnt;
+ //NS_LOG_ADDREF(this, count, "nsPrintProgress", sizeof(*this));
+ return count;
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType) nsPrintProgress::Release(void)
+{
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ count = --mRefCnt;
+ //NS_LOG_RELEASE(this, count, "nsPrintProgress");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+ /* enable this to find non-threadsafe destructors: */
+ /* NS_ASSERT_OWNINGTHREAD(nsPrintProgress); */
+ delete this;
+ return 0;
+ }
+ return count;
+}
+
+#endif
+
+NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
+ NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
+ NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
+ NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
+NS_INTERFACE_MAP_END_THREADSAFE
+
+
+nsPrintProgress::nsPrintProgress()
+{
+ m_closeProgress = false;
+ m_processCanceled = false;
+ m_pendingStateFlags = -1;
+ m_pendingStateValue = NS_OK;
+}
+
+nsPrintProgress::~nsPrintProgress()
+{
+ (void)ReleaseListeners();
+}
+
+NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(mozIDOMWindowProxy *parent,
+ const char *dialogURL,
+ nsISupports *parameters,
+ nsIObserver *openDialogObserver,
+ bool *notifyOnOpen)
+{
+ *notifyOnOpen = true;
+ m_observer = openDialogObserver;
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (m_dialog)
+ return NS_ERROR_ALREADY_INITIALIZED;
+
+ if (!dialogURL || !*dialogURL)
+ return NS_ERROR_INVALID_ARG;
+
+ if (parent)
+ {
+ // Set up window.arguments[0]...
+ nsCOMPtr<nsIMutableArray> array = nsArray::Create();
+
+ nsCOMPtr<nsISupportsInterfacePointer> ifptr =
+ do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ifptr->SetData(static_cast<nsIPrintProgress*>(this));
+ ifptr->SetDataIID(&NS_GET_IID(nsIPrintProgress));
+
+ array->AppendElement(ifptr, /*weak =*/ false);
+
+ array->AppendElement(parameters, /*weak = */ false);
+
+ // We will set the opener of the dialog to be the nsIDOMWindow for the
+ // browser XUL window itself, as opposed to the content. That way, the
+ // progress window has access to the opener.
+ nsCOMPtr<nsPIDOMWindowOuter> pParentWindow = nsPIDOMWindowOuter::From(parent);
+ NS_ENSURE_STATE(pParentWindow);
+
+ nsCOMPtr<nsIDocShell> docShell = pParentWindow->GetDocShell();
+ NS_ENSURE_STATE(docShell);
+
+ nsCOMPtr<nsIDocShellTreeOwner> owner;
+ docShell->GetTreeOwner(getter_AddRefs(owner));
+
+ nsCOMPtr<nsIXULWindow> ownerXULWindow = do_GetInterface(owner);
+ nsCOMPtr<mozIDOMWindowProxy> ownerWindow = do_GetInterface(ownerXULWindow);
+ NS_ENSURE_STATE(ownerWindow);
+
+ nsCOMPtr<nsPIDOMWindowOuter> piOwnerWindow = nsPIDOMWindowOuter::From(ownerWindow);
+
+ // Open the dialog.
+ nsCOMPtr<nsPIDOMWindowOuter> newWindow;
+ rv = piOwnerWindow->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
+ NS_LITERAL_STRING("_blank"),
+ NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
+ array, getter_AddRefs(newWindow));
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP nsPrintProgress::CloseProgressDialog(bool forceClose)
+{
+ m_closeProgress = true;
+ // XXX Casting from bool to nsresult
+ return OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP,
+ static_cast<nsresult>(forceClose));
+}
+
+NS_IMETHODIMP nsPrintProgress::GetPrompter(nsIPrompt **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nullptr;
+
+ if (! m_closeProgress && m_dialog) {
+ nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(m_dialog);
+ MOZ_ASSERT(window);
+ return window->GetPrompter(_retval);
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP nsPrintProgress::GetProcessCanceledByUser(bool *aProcessCanceledByUser)
+{
+ NS_ENSURE_ARG_POINTER(aProcessCanceledByUser);
+ *aProcessCanceledByUser = m_processCanceled;
+ return NS_OK;
+}
+NS_IMETHODIMP nsPrintProgress::SetProcessCanceledByUser(bool aProcessCanceledByUser)
+{
+ m_processCanceled = aProcessCanceledByUser;
+ OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
+{
+ if (!listener) //Nothing to do with a null listener!
+ return NS_OK;
+
+ m_listenerList.AppendObject(listener);
+ if (m_closeProgress || m_processCanceled)
+ listener->OnStateChange(nullptr, nullptr,
+ nsIWebProgressListener::STATE_STOP, NS_OK);
+ else
+ {
+ listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
+ if (m_pendingStateFlags != -1)
+ listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
+{
+ if (listener)
+ m_listenerList.RemoveObject(listener);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::DoneIniting()
+{
+ if (m_observer) {
+ m_observer->Observe(nullptr, nullptr, nullptr);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
+{
+ m_pendingStateFlags = aStateFlags;
+ m_pendingStateValue = aStatus;
+
+ uint32_t count = m_listenerList.Count();
+ for (uint32_t i = count - 1; i < count; i --)
+ {
+ nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+ if (progressListener)
+ progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
+{
+ uint32_t count = m_listenerList.Count();
+ for (uint32_t i = count - 1; i < count; i --)
+ {
+ nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+ if (progressListener)
+ progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
+{
+ if (aMessage && *aMessage)
+ m_pendingStatus = aMessage;
+
+ uint32_t count = m_listenerList.Count();
+ for (uint32_t i = count - 1; i < count; i --)
+ {
+ nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+ if (progressListener)
+ progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
+{
+ return NS_OK;
+}
+
+nsresult nsPrintProgress::ReleaseListeners()
+{
+ m_listenerList.Clear();
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgress::ShowStatusString(const char16_t *status)
+{
+ return OnStatusChange(nullptr, nullptr, NS_OK, status);
+}
+
+NS_IMETHODIMP nsPrintProgress::StartMeteors()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsPrintProgress::StopMeteors()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsPrintProgress::ShowProgress(int32_t percent)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsPrintProgress::SetDocShell(nsIDocShell *shell, mozIDOMWindowProxy *window)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsPrintProgress::CloseWindow()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/embedding/components/printingui/win/nsPrintProgress.h b/embedding/components/printingui/win/nsPrintProgress.h
new file mode 100644
index 000000000..adc5a14cc
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintProgress.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __nsPrintProgress_h
+#define __nsPrintProgress_h
+
+#include "nsIPrintProgress.h"
+
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+#include "nsIDOMWindow.h"
+#include "nsIPrintStatusFeedback.h"
+#include "nsString.h"
+#include "nsIWindowWatcher.h"
+#include "nsIObserver.h"
+
+class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIPRINTPROGRESS
+ NS_DECL_NSIWEBPROGRESSLISTENER
+ NS_DECL_NSIPRINTSTATUSFEEDBACK
+
+ nsPrintProgress();
+ virtual ~nsPrintProgress();
+
+private:
+ nsresult ReleaseListeners();
+
+ bool m_closeProgress;
+ bool m_processCanceled;
+ nsString m_pendingStatus;
+ int32_t m_pendingStateFlags;
+ nsresult m_pendingStateValue;
+ nsCOMPtr<nsIDOMWindow> m_dialog;
+ nsCOMArray<nsIWebProgressListener> m_listenerList;
+ nsCOMPtr<nsIObserver> m_observer;
+};
+
+#endif
diff --git a/embedding/components/printingui/win/nsPrintProgressParams.cpp b/embedding/components/printingui/win/nsPrintProgressParams.cpp
new file mode 100644
index 000000000..eba86b298
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintProgressParams.cpp
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsPrintProgressParams.h"
+#include "nsReadableUtils.h"
+
+
+NS_IMPL_ISUPPORTS(nsPrintProgressParams, nsIPrintProgressParams)
+
+nsPrintProgressParams::nsPrintProgressParams()
+{
+}
+
+nsPrintProgressParams::~nsPrintProgressParams()
+{
+}
+
+NS_IMETHODIMP nsPrintProgressParams::GetDocTitle(char16_t * *aDocTitle)
+{
+ NS_ENSURE_ARG(aDocTitle);
+
+ *aDocTitle = ToNewUnicode(mDocTitle);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgressParams::SetDocTitle(const char16_t * aDocTitle)
+{
+ mDocTitle = aDocTitle;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgressParams::GetDocURL(char16_t * *aDocURL)
+{
+ NS_ENSURE_ARG(aDocURL);
+
+ *aDocURL = ToNewUnicode(mDocURL);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsPrintProgressParams::SetDocURL(const char16_t * aDocURL)
+{
+ mDocURL = aDocURL;
+ return NS_OK;
+}
+
diff --git a/embedding/components/printingui/win/nsPrintProgressParams.h b/embedding/components/printingui/win/nsPrintProgressParams.h
new file mode 100644
index 000000000..aebfbff7f
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintProgressParams.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __nsPrintProgressParams_h
+#define __nsPrintProgressParams_h
+
+#include "nsIPrintProgressParams.h"
+#include "nsString.h"
+
+class nsPrintProgressParams : public nsIPrintProgressParams
+{
+ virtual ~nsPrintProgressParams();
+
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPRINTPROGRESSPARAMS
+
+ nsPrintProgressParams();
+
+private:
+ nsString mDocTitle;
+ nsString mDocURL;
+};
+
+#endif
diff --git a/embedding/components/printingui/win/nsPrintingPromptService.cpp b/embedding/components/printingui/win/nsPrintingPromptService.cpp
new file mode 100644
index 000000000..83727ee4e
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintingPromptService.cpp
@@ -0,0 +1,341 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCOMPtr.h"
+
+#include "nsPrintingPromptService.h"
+#include "nsIPrintingPromptService.h"
+#include "nsIFactory.h"
+#include "nsPIDOMWindow.h"
+#include "nsReadableUtils.h"
+#include "nsIEmbeddingSiteWindow.h"
+#include "nsIServiceManager.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsIWindowWatcher.h"
+#include "nsPrintDialogUtil.h"
+
+// Printing Progress Includes
+#include "nsPrintProgress.h"
+#include "nsPrintProgressParams.h"
+#include "nsIWebProgressListener.h"
+
+// XP Dialog includes
+#include "nsArray.h"
+#include "nsIDialogParamBlock.h"
+#include "nsISupportsUtils.h"
+
+// Includes need to locate the native Window
+#include "nsIWidget.h"
+#include "nsIBaseWindow.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocShell.h"
+#include "nsIInterfaceRequestorUtils.h"
+
+
+static const char *kPrintProgressDialogURL = "chrome://global/content/printProgress.xul";
+static const char *kPrtPrvProgressDialogURL = "chrome://global/content/printPreviewProgress.xul";
+static const char *kPageSetupDialogURL = "chrome://global/content/printPageSetup.xul";
+
+/****************************************************************
+ ************************* ParamBlock ***************************
+ ****************************************************************/
+
+class ParamBlock {
+
+public:
+ ParamBlock()
+ {
+ mBlock = 0;
+ }
+ ~ParamBlock()
+ {
+ NS_IF_RELEASE(mBlock);
+ }
+ nsresult Init() {
+ return CallCreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &mBlock);
+ }
+ nsIDialogParamBlock * operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mBlock; }
+ operator nsIDialogParamBlock * const () { return mBlock; }
+
+private:
+ nsIDialogParamBlock *mBlock;
+};
+
+//*****************************************************************************
+
+NS_IMPL_ISUPPORTS(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener)
+
+nsPrintingPromptService::nsPrintingPromptService()
+{
+}
+
+//-----------------------------------------------------------
+nsPrintingPromptService::~nsPrintingPromptService()
+{
+}
+
+//-----------------------------------------------------------
+nsresult
+nsPrintingPromptService::Init()
+{
+ nsresult rv;
+ mWatcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
+ return rv;
+}
+
+//-----------------------------------------------------------
+HWND
+nsPrintingPromptService::GetHWNDForDOMWindow(mozIDOMWindowProxy *aWindow)
+{
+ nsCOMPtr<nsIWebBrowserChrome> chrome;
+
+ // We might be embedded so check this path first
+ if (mWatcher) {
+ nsCOMPtr<mozIDOMWindowProxy> fosterParent;
+ if (!aWindow)
+ { // it will be a dependent window. try to find a foster parent.
+ mWatcher->GetActiveWindow(getter_AddRefs(fosterParent));
+ aWindow = fosterParent;
+ }
+ mWatcher->GetChromeForWindow(aWindow, getter_AddRefs(chrome));
+ }
+
+ if (chrome) {
+ nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome));
+ if (site)
+ {
+ HWND w;
+ site->GetSiteWindow(reinterpret_cast<void **>(&w));
+ return w;
+ }
+ }
+
+ // Now we might be the Browser so check this path
+ nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
+
+ nsCOMPtr<nsIDocShellTreeItem> treeItem =
+ do_QueryInterface(window->GetDocShell());
+ if (!treeItem) return nullptr;
+
+ nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+ treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
+ if (!treeOwner) return nullptr;
+
+ nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome(do_GetInterface(treeOwner));
+ if (!webBrowserChrome) return nullptr;
+
+ nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(webBrowserChrome));
+ if (!baseWin) return nullptr;
+
+ nsCOMPtr<nsIWidget> widget;
+ baseWin->GetMainWidget(getter_AddRefs(widget));
+ if (!widget) return nullptr;
+
+ return (HWND)widget->GetNativeData(NS_NATIVE_TMP_WINDOW);
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// nsIPrintingPromptService
+
+//-----------------------------------------------------------
+NS_IMETHODIMP
+nsPrintingPromptService::ShowPrintDialog(mozIDOMWindowProxy *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings)
+{
+ NS_ENSURE_ARG(parent);
+
+ HWND hWnd = GetHWNDForDOMWindow(parent);
+ NS_ASSERTION(hWnd, "Couldn't get native window for PRint Dialog!");
+
+ return NativeShowPrintDialog(hWnd, webBrowserPrint, printSettings);
+}
+
+
+NS_IMETHODIMP
+nsPrintingPromptService::ShowProgress(mozIDOMWindowProxy* parent,
+ nsIWebBrowserPrint* webBrowserPrint, // ok to be null
+ nsIPrintSettings* printSettings, // ok to be null
+ nsIObserver* openDialogObserver, // ok to be null
+ bool isForPrinting,
+ nsIWebProgressListener** webProgressListener,
+ nsIPrintProgressParams** printProgressParams,
+ bool* notifyOnOpen)
+{
+ NS_ENSURE_ARG(webProgressListener);
+ NS_ENSURE_ARG(printProgressParams);
+ NS_ENSURE_ARG(notifyOnOpen);
+
+ *notifyOnOpen = false;
+ if (mPrintProgress) {
+ *webProgressListener = nullptr;
+ *printProgressParams = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ nsPrintProgress* prtProgress = new nsPrintProgress();
+ mPrintProgress = prtProgress;
+ mWebProgressListener = prtProgress;
+
+ nsCOMPtr<nsIPrintProgressParams> prtProgressParams = new nsPrintProgressParams();
+
+ nsCOMPtr<mozIDOMWindowProxy> parentWindow = parent;
+
+ if (mWatcher && !parentWindow) {
+ mWatcher->GetActiveWindow(getter_AddRefs(parentWindow));
+ }
+
+ if (parentWindow) {
+ mPrintProgress->OpenProgressDialog(parentWindow,
+ isForPrinting ? kPrintProgressDialogURL : kPrtPrvProgressDialogURL,
+ prtProgressParams, openDialogObserver, notifyOnOpen);
+ }
+
+ prtProgressParams.forget(printProgressParams);
+ NS_ADDREF(*webProgressListener = this);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent, nsIPrintSettings *printSettings, nsIObserver *aObs)
+{
+ NS_ENSURE_ARG(printSettings);
+
+ ParamBlock block;
+ nsresult rv = block.Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ block->SetInt(0, 0);
+ rv = DoDialog(parent, block, printSettings, kPageSetupDialogURL);
+
+ // if aWebBrowserPrint is not null then we are printing
+ // so we want to pass back NS_ERROR_ABORT on cancel
+ if (NS_SUCCEEDED(rv))
+ {
+ int32_t status;
+ block->GetInt(0, &status);
+ return status == 0?NS_ERROR_ABORT:NS_OK;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent, const char16_t *printerName, nsIPrintSettings *printSettings)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//-----------------------------------------------------------
+// Helper to Fly XP Dialog
+nsresult
+nsPrintingPromptService::DoDialog(mozIDOMWindowProxy *aParent,
+ nsIDialogParamBlock *aParamBlock,
+ nsIPrintSettings* aPS,
+ const char *aChromeURL)
+{
+ NS_ENSURE_ARG(aParamBlock);
+ NS_ENSURE_ARG(aPS);
+ NS_ENSURE_ARG(aChromeURL);
+
+ if (!mWatcher)
+ return NS_ERROR_FAILURE;
+
+ // get a parent, if at all possible
+ // (though we'd rather this didn't fail, it's OK if it does. so there's
+ // no failure or null check.)
+ nsCOMPtr<mozIDOMWindowProxy> activeParent; // retain ownership for method lifetime
+ if (!aParent)
+ {
+ mWatcher->GetActiveWindow(getter_AddRefs(activeParent));
+ aParent = activeParent;
+ }
+
+ // create a nsIMutableArray of the parameters
+ // being passed to the window
+ nsCOMPtr<nsIMutableArray> array = nsArray::Create();
+
+ nsCOMPtr<nsISupports> psSupports(do_QueryInterface(aPS));
+ NS_ASSERTION(psSupports, "PrintSettings must be a supports");
+ array->AppendElement(psSupports, /*weak =*/ false);
+
+ nsCOMPtr<nsISupports> blkSupps(do_QueryInterface(aParamBlock));
+ NS_ASSERTION(blkSupps, "IOBlk must be a supports");
+ array->AppendElement(blkSupps, /*weak =*/ false);
+
+ nsCOMPtr<mozIDOMWindowProxy> dialog;
+ nsresult rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",
+ "centerscreen,chrome,modal,titlebar", array,
+ getter_AddRefs(dialog));
+
+ return rv;
+}
+
+//////////////////////////////////////////////////////////////////////
+// nsIWebProgressListener
+//////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
+{
+ if ((aStateFlags & STATE_STOP) && mWebProgressListener)
+ {
+ mWebProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
+ if (mPrintProgress)
+ {
+ mPrintProgress->CloseProgressDialog(true);
+ }
+ mPrintProgress = nullptr;
+ mWebProgressListener = nullptr;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
+{
+ if (mWebProgressListener)
+ {
+ return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
+{
+ if (mWebProgressListener)
+ {
+ return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
+{
+ if (mWebProgressListener)
+ {
+ return mWebProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
+{
+ if (mWebProgressListener)
+ {
+ return mWebProgressListener->OnSecurityChange(aWebProgress, aRequest, state);
+ }
+ return NS_ERROR_FAILURE;
+}
+
+
diff --git a/embedding/components/printingui/win/nsPrintingPromptService.h b/embedding/components/printingui/win/nsPrintingPromptService.h
new file mode 100644
index 000000000..76bc7a804
--- /dev/null
+++ b/embedding/components/printingui/win/nsPrintingPromptService.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __nsPrintingPromptService_h
+#define __nsPrintingPromptService_h
+
+#include <windows.h>
+
+// {E042570C-62DE-4bb6-A6E0-798E3C07B4DF}
+#define NS_PRINTINGPROMPTSERVICE_CID \
+ {0xe042570c, 0x62de, 0x4bb6, { 0xa6, 0xe0, 0x79, 0x8e, 0x3c, 0x7, 0xb4, 0xdf}}
+#define NS_PRINTINGPROMPTSERVICE_CONTRACTID \
+ "@mozilla.org/embedcomp/printingprompt-service;1"
+
+#include "nsCOMPtr.h"
+#include "nsIPrintingPromptService.h"
+#include "nsPIPromptService.h"
+#include "nsIWindowWatcher.h"
+
+// Printing Progress Includes
+#include "nsPrintProgress.h"
+#include "nsPrintProgressParams.h"
+#include "nsIWebProgressListener.h"
+
+class nsIDOMWindow;
+class nsIDialogParamBlock;
+
+class nsPrintingPromptService: public nsIPrintingPromptService,
+ public nsIWebProgressListener
+{
+ virtual ~nsPrintingPromptService();
+
+public:
+ nsPrintingPromptService();
+
+ nsresult Init();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPRINTINGPROMPTSERVICE
+ NS_DECL_NSIWEBPROGRESSLISTENER
+
+private:
+ HWND GetHWNDForDOMWindow(mozIDOMWindowProxy *parent);
+ nsresult DoDialog(mozIDOMWindowProxy *aParent,
+ nsIDialogParamBlock *aParamBlock,
+ nsIPrintSettings* aPS,
+ const char *aChromeURL);
+
+ nsCOMPtr<nsIWindowWatcher> mWatcher;
+ nsCOMPtr<nsIPrintProgress> mPrintProgress;
+ nsCOMPtr<nsIWebProgressListener> mWebProgressListener;
+
+};
+
+#endif
+