Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsPrintingProxy.h"
8 :
9 : #include "mozilla/ClearOnShutdown.h"
10 : #include "mozilla/dom/ContentChild.h"
11 : #include "mozilla/dom/TabChild.h"
12 : #include "mozilla/layout/RemotePrintJobChild.h"
13 : #include "mozilla/Unused.h"
14 : #include "nsIDocShell.h"
15 : #include "nsIDocShellTreeOwner.h"
16 : #include "nsIPrintingPromptService.h"
17 : #include "nsIPrintSession.h"
18 : #include "nsPIDOMWindow.h"
19 : #include "nsPrintOptionsImpl.h"
20 : #include "nsServiceManagerUtils.h"
21 : #include "PrintDataUtils.h"
22 : #include "PrintProgressDialogChild.h"
23 : #include "PrintSettingsDialogChild.h"
24 :
25 : using namespace mozilla;
26 : using namespace mozilla::dom;
27 : using namespace mozilla::embedding;
28 : using namespace mozilla::layout;
29 :
30 3 : static StaticRefPtr<nsPrintingProxy> sPrintingProxyInstance;
31 :
32 6 : NS_IMPL_ISUPPORTS(nsPrintingProxy, nsIPrintingPromptService)
33 :
34 2 : nsPrintingProxy::nsPrintingProxy()
35 : {
36 2 : }
37 :
38 0 : nsPrintingProxy::~nsPrintingProxy()
39 : {
40 0 : }
41 :
42 : /* static */
43 : already_AddRefed<nsPrintingProxy>
44 2 : nsPrintingProxy::GetInstance()
45 : {
46 2 : if (!sPrintingProxyInstance) {
47 2 : sPrintingProxyInstance = new nsPrintingProxy();
48 2 : if (!sPrintingProxyInstance) {
49 0 : return nullptr;
50 : }
51 2 : nsresult rv = sPrintingProxyInstance->Init();
52 2 : if (NS_FAILED(rv)) {
53 0 : sPrintingProxyInstance = nullptr;
54 0 : return nullptr;
55 : }
56 2 : ClearOnShutdown(&sPrintingProxyInstance);
57 : }
58 :
59 4 : RefPtr<nsPrintingProxy> inst = sPrintingProxyInstance.get();
60 2 : return inst.forget();
61 : }
62 :
63 : nsresult
64 2 : nsPrintingProxy::Init()
65 : {
66 2 : ContentChild::GetSingleton()->SetEventTargetForActor(this,
67 4 : SystemGroup::EventTargetFor(mozilla::TaskCategory::Other));
68 2 : MOZ_ASSERT(this->GetActorEventTarget());
69 :
70 2 : mozilla::Unused << ContentChild::GetSingleton()->SendPPrintingConstructor(this);
71 2 : return NS_OK;
72 : }
73 :
74 : NS_IMETHODIMP
75 0 : nsPrintingProxy::ShowPrintDialog(mozIDOMWindowProxy *parent,
76 : nsIWebBrowserPrint *webBrowserPrint,
77 : nsIPrintSettings *printSettings)
78 : {
79 0 : NS_ENSURE_ARG(webBrowserPrint);
80 0 : NS_ENSURE_ARG(printSettings);
81 :
82 : // If parent is null we are just being called to retrieve the print settings
83 : // from the printer in the parent for print preview.
84 0 : TabChild* pBrowser = nullptr;
85 0 : if (parent) {
86 : // Get the TabChild for this nsIDOMWindow, which we can then pass up to
87 : // the parent.
88 0 : nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(parent);
89 0 : NS_ENSURE_STATE(pwin);
90 0 : nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
91 0 : NS_ENSURE_STATE(docShell);
92 :
93 0 : nsCOMPtr<nsITabChild> tabchild = docShell->GetTabChild();
94 0 : NS_ENSURE_STATE(tabchild);
95 :
96 0 : pBrowser = static_cast<TabChild*>(tabchild.get());
97 : }
98 :
99 : // Next, serialize the nsIWebBrowserPrint and nsIPrintSettings we were given.
100 0 : nsresult rv = NS_OK;
101 : nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
102 0 : do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
103 0 : NS_ENSURE_SUCCESS(rv, rv);
104 :
105 0 : PrintData inSettings;
106 0 : rv = printSettingsSvc->SerializeToPrintData(printSettings, webBrowserPrint,
107 0 : &inSettings);
108 0 : NS_ENSURE_SUCCESS(rv, rv);
109 :
110 : // Now, the waiting game. The parent process should be showing
111 : // the printing dialog soon. In the meantime, we need to spin a
112 : // nested event loop while we wait for the results of the dialog
113 : // to be returned to us.
114 :
115 0 : RefPtr<PrintSettingsDialogChild> dialog = new PrintSettingsDialogChild();
116 0 : SendPPrintSettingsDialogConstructor(dialog);
117 :
118 0 : mozilla::Unused << SendShowPrintDialog(dialog, pBrowser, inSettings);
119 :
120 0 : SpinEventLoopUntil([&, dialog]() { return dialog->returned(); });
121 :
122 0 : rv = dialog->result();
123 0 : NS_ENSURE_SUCCESS(rv, rv);
124 :
125 0 : rv = printSettingsSvc->DeserializeToPrintSettings(dialog->data(),
126 0 : printSettings);
127 0 : return NS_OK;
128 : }
129 :
130 : NS_IMETHODIMP
131 0 : nsPrintingProxy::ShowProgress(mozIDOMWindowProxy* parent,
132 : nsIWebBrowserPrint* webBrowserPrint, // ok to be null
133 : nsIPrintSettings* printSettings, // ok to be null
134 : nsIObserver* openDialogObserver, // ok to be null
135 : bool isForPrinting,
136 : nsIWebProgressListener** webProgressListener,
137 : nsIPrintProgressParams** printProgressParams,
138 : bool* notifyOnOpen)
139 : {
140 0 : NS_ENSURE_ARG(parent);
141 0 : NS_ENSURE_ARG(webProgressListener);
142 0 : NS_ENSURE_ARG(printProgressParams);
143 0 : NS_ENSURE_ARG(notifyOnOpen);
144 :
145 : // Get the TabChild for this nsIDOMWindow, which we can then pass up to
146 : // the parent.
147 0 : nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(parent);
148 0 : NS_ENSURE_STATE(pwin);
149 0 : nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
150 0 : NS_ENSURE_STATE(docShell);
151 0 : nsCOMPtr<nsITabChild> tabchild = docShell->GetTabChild();
152 0 : TabChild* pBrowser = static_cast<TabChild*>(tabchild.get());
153 :
154 : RefPtr<PrintProgressDialogChild> dialogChild =
155 0 : new PrintProgressDialogChild(openDialogObserver);
156 :
157 0 : SendPPrintProgressDialogConstructor(dialogChild);
158 :
159 : // Get the RemotePrintJob if we have one available.
160 0 : RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
161 0 : if (printSettings) {
162 0 : nsCOMPtr<nsIPrintSession> printSession;
163 0 : nsresult rv = printSettings->GetPrintSession(getter_AddRefs(printSession));
164 0 : if (NS_SUCCEEDED(rv) && printSession) {
165 0 : printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
166 : }
167 : }
168 :
169 : // NOTE: We set notifyOnOpen to true unconditionally. If the parent process
170 : // would get `false` for notifyOnOpen, then it will synthesize a notification
171 : // which will be sent asynchronously down to the child.
172 0 : *notifyOnOpen = true;
173 0 : mozilla::Unused << SendShowProgress(pBrowser, dialogChild, remotePrintJob,
174 0 : isForPrinting);
175 :
176 : // If we have a RemotePrintJob that will be being used as a more general
177 : // forwarder for print progress listeners. Once we always have one we can
178 : // remove the interface from PrintProgressDialogChild.
179 0 : if (!remotePrintJob) {
180 0 : NS_ADDREF(*webProgressListener = dialogChild);
181 : }
182 0 : NS_ADDREF(*printProgressParams = dialogChild);
183 :
184 0 : return NS_OK;
185 : }
186 :
187 : NS_IMETHODIMP
188 0 : nsPrintingProxy::ShowPageSetup(mozIDOMWindowProxy *parent,
189 : nsIPrintSettings *printSettings,
190 : nsIObserver *aObs)
191 : {
192 0 : return NS_ERROR_NOT_IMPLEMENTED;
193 : }
194 :
195 : NS_IMETHODIMP
196 0 : nsPrintingProxy::ShowPrinterProperties(mozIDOMWindowProxy *parent,
197 : const char16_t *printerName,
198 : nsIPrintSettings *printSettings)
199 : {
200 0 : return NS_ERROR_NOT_IMPLEMENTED;
201 : }
202 :
203 : nsresult
204 0 : nsPrintingProxy::SavePrintSettings(nsIPrintSettings* aPS,
205 : bool aUsePrinterNamePrefix,
206 : uint32_t aFlags)
207 : {
208 : nsresult rv;
209 : nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
210 0 : do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
211 0 : NS_ENSURE_SUCCESS(rv, rv);
212 :
213 0 : PrintData settings;
214 0 : rv = printSettingsSvc->SerializeToPrintData(aPS, nullptr, &settings);
215 0 : NS_ENSURE_SUCCESS(rv, rv);
216 :
217 0 : Unused << SendSavePrintSettings(settings, aUsePrinterNamePrefix, aFlags,
218 : &rv);
219 0 : return rv;
220 : }
221 :
222 : PPrintProgressDialogChild*
223 0 : nsPrintingProxy::AllocPPrintProgressDialogChild()
224 : {
225 : // The parent process will never initiate the PPrintProgressDialog
226 : // protocol connection, so no need to provide an allocator here.
227 0 : NS_NOTREACHED("Allocator for PPrintProgressDialogChild should not be "
228 : "called on nsPrintingProxy.");
229 0 : return nullptr;
230 : }
231 :
232 : bool
233 0 : nsPrintingProxy::DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor)
234 : {
235 : // The PrintProgressDialogChild implements refcounting, and
236 : // will take itself out.
237 0 : return true;
238 : }
239 :
240 : PPrintSettingsDialogChild*
241 0 : nsPrintingProxy::AllocPPrintSettingsDialogChild()
242 : {
243 : // The parent process will never initiate the PPrintSettingsDialog
244 : // protocol connection, so no need to provide an allocator here.
245 0 : NS_NOTREACHED("Allocator for PPrintSettingsDialogChild should not be "
246 : "called on nsPrintingProxy.");
247 0 : return nullptr;
248 : }
249 :
250 : bool
251 0 : nsPrintingProxy::DeallocPPrintSettingsDialogChild(PPrintSettingsDialogChild* aActor)
252 : {
253 : // The PrintSettingsDialogChild implements refcounting, and
254 : // will take itself out.
255 0 : return true;
256 : }
257 :
258 : PRemotePrintJobChild*
259 0 : nsPrintingProxy::AllocPRemotePrintJobChild()
260 : {
261 0 : RefPtr<RemotePrintJobChild> remotePrintJob = new RemotePrintJobChild();
262 0 : return remotePrintJob.forget().take();
263 : }
264 :
265 : bool
266 0 : nsPrintingProxy::DeallocPRemotePrintJobChild(PRemotePrintJobChild* aDoomed)
267 : {
268 0 : RemotePrintJobChild* remotePrintJob = static_cast<RemotePrintJobChild*>(aDoomed);
269 0 : NS_RELEASE(remotePrintJob);
270 0 : return true;
271 9 : }
|