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 "nsIDialogParamBlock.h"
12 #include "nsIDocShellTreeOwner.h"
13 #include "nsIDocShellTreeItem.h"
14 #include "nsIDocShell.h"
15 #include "nsIEmbeddingSiteWindow.h"
16 #include "nsIInterfaceRequestorUtils.h"
17 #include "nsIPrintSettings.h"
18 #include "nsIWebBrowserChrome.h"
19 #include "nsIWidget.h"
20 #include "nsPrintDialogUtil.h"
21 #include "nsIPrintSettings.h"
22 #include "nsIWebBrowserChrome.h"
23 #include "nsQueryObject.h"
24 
25 static const char* kPageSetupDialogURL =
26     "chrome://global/content/printPageSetup.xul";
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,nsIWebBrowserPrint * aWebBrowserPrint)65 nsPrintDialogServiceWin::Show(nsPIDOMWindowOuter* aParent,
66                               nsIPrintSettings* aSettings,
67                               nsIWebBrowserPrint* aWebBrowserPrint) {
68   NS_ENSURE_ARG(aParent);
69   HWND hWnd = GetHWNDForDOMWindow(aParent);
70   NS_ASSERTION(hWnd, "Couldn't get native window for PRint Dialog!");
71 
72   return NativeShowPrintDialog(hWnd, aWebBrowserPrint, aSettings);
73 }
74 
75 NS_IMETHODIMP
ShowPageSetup(nsPIDOMWindowOuter * aParent,nsIPrintSettings * aNSSettings)76 nsPrintDialogServiceWin::ShowPageSetup(nsPIDOMWindowOuter* aParent,
77                                        nsIPrintSettings* aNSSettings) {
78   NS_ENSURE_ARG(aParent);
79   NS_ENSURE_ARG(aNSSettings);
80 
81   ParamBlock block;
82   nsresult rv = block.Init();
83   if (NS_FAILED(rv)) return rv;
84 
85   block->SetInt(0, 0);
86   rv = DoDialog(aParent, block, aNSSettings, kPageSetupDialogURL);
87 
88   // if aWebBrowserPrint is not null then we are printing
89   // so we want to pass back NS_ERROR_ABORT on cancel
90   if (NS_SUCCEEDED(rv)) {
91     int32_t status;
92     block->GetInt(0, &status);
93     return status == 0 ? NS_ERROR_ABORT : NS_OK;
94   }
95 
96   return rv;
97 }
98 
DoDialog(mozIDOMWindowProxy * aParent,nsIDialogParamBlock * aParamBlock,nsIPrintSettings * aPS,const char * aChromeURL)99 nsresult nsPrintDialogServiceWin::DoDialog(mozIDOMWindowProxy* aParent,
100                                            nsIDialogParamBlock* aParamBlock,
101                                            nsIPrintSettings* aPS,
102                                            const char* aChromeURL) {
103   NS_ENSURE_ARG(aParamBlock);
104   NS_ENSURE_ARG(aPS);
105   NS_ENSURE_ARG(aChromeURL);
106 
107   if (!mWatcher) return NS_ERROR_FAILURE;
108 
109   // get a parent, if at all possible
110   // (though we'd rather this didn't fail, it's OK if it does. so there's
111   // no failure or null check.)
112   // retain ownership for method lifetime
113   nsCOMPtr<mozIDOMWindowProxy> activeParent;
114   if (!aParent) {
115     mWatcher->GetActiveWindow(getter_AddRefs(activeParent));
116     aParent = activeParent;
117   }
118 
119   // create a nsIMutableArray of the parameters
120   // being passed to the window
121   nsCOMPtr<nsIMutableArray> array = nsArray::Create();
122 
123   nsCOMPtr<nsISupports> psSupports(do_QueryInterface(aPS));
124   NS_ASSERTION(psSupports, "PrintSettings must be a supports");
125   array->AppendElement(psSupports);
126 
127   nsCOMPtr<nsISupports> blkSupps(do_QueryInterface(aParamBlock));
128   NS_ASSERTION(blkSupps, "IOBlk must be a supports");
129   array->AppendElement(blkSupps);
130 
131   nsCOMPtr<mozIDOMWindowProxy> dialog;
132   nsresult rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",
133                                      "centerscreen,chrome,modal,titlebar",
134                                      array, getter_AddRefs(dialog));
135 
136   return rv;
137 }
138 
GetHWNDForDOMWindow(mozIDOMWindowProxy * aWindow)139 HWND nsPrintDialogServiceWin::GetHWNDForDOMWindow(mozIDOMWindowProxy* aWindow) {
140   nsCOMPtr<nsIWebBrowserChrome> chrome;
141 
142   // We might be embedded so check this path first
143   if (mWatcher) {
144     nsCOMPtr<mozIDOMWindowProxy> fosterParent;
145     // it will be a dependent window. try to find a foster parent.
146     if (!aWindow) {
147       mWatcher->GetActiveWindow(getter_AddRefs(fosterParent));
148       aWindow = fosterParent;
149     }
150     mWatcher->GetChromeForWindow(aWindow, getter_AddRefs(chrome));
151   }
152 
153   if (chrome) {
154     nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome));
155     if (site) {
156       HWND w;
157       site->GetSiteWindow(reinterpret_cast<void**>(&w));
158       return w;
159     }
160   }
161 
162   // Now we might be the Browser so check this path
163   nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
164 
165   nsCOMPtr<nsIDocShellTreeItem> treeItem =
166       do_QueryInterface(window->GetDocShell());
167   if (!treeItem) return nullptr;
168 
169   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
170   treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
171   if (!treeOwner) return nullptr;
172 
173   nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome(do_GetInterface(treeOwner));
174   if (!webBrowserChrome) return nullptr;
175 
176   nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(webBrowserChrome));
177   if (!baseWin) return nullptr;
178 
179   nsCOMPtr<nsIWidget> widget;
180   baseWin->GetMainWidget(getter_AddRefs(widget));
181   if (!widget) return nullptr;
182 
183   return (HWND)widget->GetNativeData(NS_NATIVE_TMP_WINDOW);
184 }
185