1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "nsPrintDialogWin.h"
7 
8 #include "nsArray.h"
9 #include "nsCOMPtr.h"
10 #include "nsIBaseWindow.h"
11 #include "nsIBrowserChild.h"
12 #include "nsIDialogParamBlock.h"
13 #include "nsIDocShell.h"
14 #include "nsIEmbeddingSiteWindow.h"
15 #include "nsIInterfaceRequestorUtils.h"
16 #include "nsIPrintSettings.h"
17 #include "nsIWebBrowserChrome.h"
18 #include "nsIWidget.h"
19 #include "nsPrintDialogUtil.h"
20 #include "nsIPrintSettings.h"
21 #include "nsIWebBrowserChrome.h"
22 #include "nsPIDOMWindow.h"
23 #include "nsQueryObject.h"
24 
25 static const char* kPageSetupDialogURL =
26     "chrome://global/content/printPageSetup.xhtml";
27 
28 using namespace mozilla;
29 using namespace mozilla::widget;
30 
31 /**
32  * ParamBlock
33  */
34 
35 class ParamBlock {
36  public:
ParamBlock()37   ParamBlock() { mBlock = 0; }
~ParamBlock()38   ~ParamBlock() { NS_IF_RELEASE(mBlock); }
Init()39   nsresult Init() {
40     return CallCreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &mBlock);
41   }
operator ->() const42   nsIDialogParamBlock* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
43     return mBlock;
44   }
operator nsIDialogParamBlock*const()45   operator nsIDialogParamBlock* const() { return mBlock; }
46 
47  private:
48   nsIDialogParamBlock* mBlock;
49 };
50 
NS_IMPL_ISUPPORTS(nsPrintDialogServiceWin,nsIPrintDialogService)51 NS_IMPL_ISUPPORTS(nsPrintDialogServiceWin, nsIPrintDialogService)
52 
53 nsPrintDialogServiceWin::nsPrintDialogServiceWin() {}
54 
~nsPrintDialogServiceWin()55 nsPrintDialogServiceWin::~nsPrintDialogServiceWin() {}
56 
57 NS_IMETHODIMP
Init()58 nsPrintDialogServiceWin::Init() {
59   nsresult rv;
60   mWatcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
61   return rv;
62 }
63 
64 NS_IMETHODIMP
Show(nsPIDOMWindowOuter * aParent,nsIPrintSettings * aSettings)65 nsPrintDialogServiceWin::Show(nsPIDOMWindowOuter* aParent,
66                               nsIPrintSettings* aSettings) {
67   NS_ENSURE_ARG(aParent);
68   HWND hWnd = GetHWNDForDOMWindow(aParent);
69   NS_ASSERTION(hWnd, "Couldn't get native window for PRint Dialog!");
70 
71   return NativeShowPrintDialog(hWnd, aSettings);
72 }
73 
74 NS_IMETHODIMP
ShowPageSetup(nsPIDOMWindowOuter * aParent,nsIPrintSettings * aNSSettings)75 nsPrintDialogServiceWin::ShowPageSetup(nsPIDOMWindowOuter* aParent,
76                                        nsIPrintSettings* aNSSettings) {
77   NS_ENSURE_ARG(aParent);
78   NS_ENSURE_ARG(aNSSettings);
79 
80   ParamBlock block;
81   nsresult rv = block.Init();
82   if (NS_FAILED(rv)) return rv;
83 
84   block->SetInt(0, 0);
85   rv = DoDialog(aParent, block, aNSSettings, kPageSetupDialogURL);
86 
87   // if aWebBrowserPrint is not null then we are printing
88   // so we want to pass back NS_ERROR_ABORT on cancel
89   if (NS_SUCCEEDED(rv)) {
90     int32_t status;
91     block->GetInt(0, &status);
92     return status == 0 ? NS_ERROR_ABORT : NS_OK;
93   }
94 
95   // We don't call nsPrintSettingsService::SavePrintSettingsToPrefs here since
96   // it's called for us in printPageSetup.js.  Maybe we should move that call
97   // here for consistency with the other platforms though?
98 
99   return rv;
100 }
101 
DoDialog(mozIDOMWindowProxy * aParent,nsIDialogParamBlock * aParamBlock,nsIPrintSettings * aPS,const char * aChromeURL)102 nsresult nsPrintDialogServiceWin::DoDialog(mozIDOMWindowProxy* aParent,
103                                            nsIDialogParamBlock* aParamBlock,
104                                            nsIPrintSettings* aPS,
105                                            const char* aChromeURL) {
106   NS_ENSURE_ARG(aParamBlock);
107   NS_ENSURE_ARG(aPS);
108   NS_ENSURE_ARG(aChromeURL);
109 
110   if (!mWatcher) return NS_ERROR_FAILURE;
111 
112   // get a parent, if at all possible
113   // (though we'd rather this didn't fail, it's OK if it does. so there's
114   // no failure or null check.)
115   // retain ownership for method lifetime
116   nsCOMPtr<mozIDOMWindowProxy> activeParent;
117   if (!aParent) {
118     mWatcher->GetActiveWindow(getter_AddRefs(activeParent));
119     aParent = activeParent;
120   }
121 
122   // create a nsIMutableArray of the parameters
123   // being passed to the window
124   nsCOMPtr<nsIMutableArray> array = nsArray::Create();
125 
126   nsCOMPtr<nsISupports> psSupports(do_QueryInterface(aPS));
127   NS_ASSERTION(psSupports, "PrintSettings must be a supports");
128   array->AppendElement(psSupports);
129 
130   nsCOMPtr<nsISupports> blkSupps(do_QueryInterface(aParamBlock));
131   NS_ASSERTION(blkSupps, "IOBlk must be a supports");
132   array->AppendElement(blkSupps);
133 
134   nsCOMPtr<mozIDOMWindowProxy> dialog;
135   nsresult rv = mWatcher->OpenWindow(
136       aParent, nsDependentCString(aChromeURL), "_blank"_ns,
137       "centerscreen,chrome,modal,titlebar"_ns, array, getter_AddRefs(dialog));
138 
139   return rv;
140 }
141 
GetHWNDForDOMWindow(mozIDOMWindowProxy * aWindow)142 HWND nsPrintDialogServiceWin::GetHWNDForDOMWindow(mozIDOMWindowProxy* aWindow) {
143   nsCOMPtr<nsIWebBrowserChrome> chrome;
144 
145   // We might be embedded so check this path first
146   if (mWatcher) {
147     nsCOMPtr<mozIDOMWindowProxy> fosterParent;
148     // it will be a dependent window. try to find a foster parent.
149     if (!aWindow) {
150       mWatcher->GetActiveWindow(getter_AddRefs(fosterParent));
151       aWindow = fosterParent;
152     }
153     mWatcher->GetChromeForWindow(aWindow, getter_AddRefs(chrome));
154   }
155 
156   if (chrome) {
157     nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome));
158     if (site) {
159       HWND w;
160       site->GetSiteWindow(reinterpret_cast<void**>(&w));
161       return w;
162     }
163   }
164 
165   // Now we might be the Browser so check this path
166   nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
167 
168   nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome =
169       window->GetWebBrowserChrome();
170   if (!webBrowserChrome) return nullptr;
171 
172   nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(webBrowserChrome));
173   if (!baseWin) return nullptr;
174 
175   nsCOMPtr<nsIWidget> widget;
176   baseWin->GetMainWidget(getter_AddRefs(widget));
177   if (!widget) return nullptr;
178 
179   return (HWND)widget->GetNativeData(NS_NATIVE_TMP_WINDOW);
180 }
181