Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/printingui/ipc/nsPrintingProxy.cpp
Line
Count
Source (jump to first uncovered line)
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 "nsPrintSettingsService.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
static StaticRefPtr<nsPrintingProxy> sPrintingProxyInstance;
31
32
NS_IMPL_ISUPPORTS(nsPrintingProxy, nsIPrintingPromptService)
33
34
nsPrintingProxy::nsPrintingProxy()
35
0
{
36
0
}
37
38
nsPrintingProxy::~nsPrintingProxy()
39
0
{
40
0
}
41
42
/* static */
43
already_AddRefed<nsPrintingProxy>
44
nsPrintingProxy::GetInstance()
45
0
{
46
0
  if (!sPrintingProxyInstance) {
47
0
    sPrintingProxyInstance = new nsPrintingProxy();
48
0
    if (!sPrintingProxyInstance) {
49
0
      return nullptr;
50
0
    }
51
0
    nsresult rv = sPrintingProxyInstance->Init();
52
0
    if (NS_FAILED(rv)) {
53
0
      sPrintingProxyInstance = nullptr;
54
0
      return nullptr;
55
0
    }
56
0
    ClearOnShutdown(&sPrintingProxyInstance);
57
0
  }
58
0
59
0
  RefPtr<nsPrintingProxy> inst = sPrintingProxyInstance.get();
60
0
  return inst.forget();
61
0
}
62
63
nsresult
64
nsPrintingProxy::Init()
65
0
{
66
0
  // Don't create a printing proxy in middleman processes, to avoid conflicts
67
0
  // with the one created in the child recording process.
68
0
  if (recordreplay::IsMiddleman()) {
69
0
    return NS_ERROR_FAILURE;
70
0
  }
71
0
  mozilla::Unused << ContentChild::GetSingleton()->SendPPrintingConstructor(this);
72
0
  return NS_OK;
73
0
}
74
75
NS_IMETHODIMP
76
nsPrintingProxy::ShowPrintDialog(mozIDOMWindowProxy *parent,
77
                                 nsIWebBrowserPrint *webBrowserPrint,
78
                                 nsIPrintSettings *printSettings)
79
0
{
80
0
  NS_ENSURE_ARG(webBrowserPrint);
81
0
  NS_ENSURE_ARG(printSettings);
82
0
83
0
  // If parent is null we are just being called to retrieve the print settings
84
0
  // from the printer in the parent for print preview.
85
0
  TabChild* pBrowser = nullptr;
86
0
  if (parent) {
87
0
    // Get the TabChild for this nsIDOMWindow, which we can then pass up to
88
0
    // the parent.
89
0
    nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(parent);
90
0
    NS_ENSURE_STATE(pwin);
91
0
    nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
92
0
    NS_ENSURE_STATE(docShell);
93
0
94
0
    nsCOMPtr<nsITabChild> tabchild = docShell->GetTabChild();
95
0
    NS_ENSURE_STATE(tabchild);
96
0
97
0
    pBrowser = static_cast<TabChild*>(tabchild.get());
98
0
  }
99
0
100
0
  // Next, serialize the nsIWebBrowserPrint and nsIPrintSettings we were given.
101
0
  nsresult rv = NS_OK;
102
0
  nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
103
0
    do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
104
0
  NS_ENSURE_SUCCESS(rv, rv);
105
0
106
0
  PrintData inSettings;
107
0
  rv = printSettingsSvc->SerializeToPrintData(printSettings, webBrowserPrint,
108
0
                                              &inSettings);
109
0
  NS_ENSURE_SUCCESS(rv, rv);
110
0
111
0
  // Now, the waiting game. The parent process should be showing
112
0
  // the printing dialog soon. In the meantime, we need to spin a
113
0
  // nested event loop while we wait for the results of the dialog
114
0
  // to be returned to us.
115
0
116
0
  RefPtr<PrintSettingsDialogChild> dialog = new PrintSettingsDialogChild();
117
0
  SendPPrintSettingsDialogConstructor(dialog);
118
0
119
0
  mozilla::Unused << SendShowPrintDialog(dialog, pBrowser, inSettings);
120
0
121
0
  SpinEventLoopUntil([&, dialog]() { return dialog->returned(); });
122
0
123
0
  rv = dialog->result();
124
0
  NS_ENSURE_SUCCESS(rv, rv);
125
0
126
0
  rv = printSettingsSvc->DeserializeToPrintSettings(dialog->data(),
127
0
                                                    printSettings);
128
0
  return NS_OK;
129
0
}
130
131
NS_IMETHODIMP
132
nsPrintingProxy::ShowProgress(mozIDOMWindowProxy*      parent,
133
                              nsIWebBrowserPrint*      webBrowserPrint,    // ok to be null
134
                              nsIPrintSettings*        printSettings,      // ok to be null
135
                              nsIObserver*             openDialogObserver, // ok to be null
136
                              bool                     isForPrinting,
137
                              nsIWebProgressListener** webProgressListener,
138
                              nsIPrintProgressParams** printProgressParams,
139
                              bool*                  notifyOnOpen)
140
0
{
141
0
  NS_ENSURE_ARG(parent);
142
0
  NS_ENSURE_ARG(webProgressListener);
143
0
  NS_ENSURE_ARG(printProgressParams);
144
0
  NS_ENSURE_ARG(notifyOnOpen);
145
0
146
0
  // Get the TabChild for this nsIDOMWindow, which we can then pass up to
147
0
  // the parent.
148
0
  nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(parent);
149
0
  NS_ENSURE_STATE(pwin);
150
0
  nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
151
0
  NS_ENSURE_STATE(docShell);
152
0
  nsCOMPtr<nsITabChild> tabchild = docShell->GetTabChild();
153
0
  TabChild* pBrowser = static_cast<TabChild*>(tabchild.get());
154
0
155
0
  RefPtr<PrintProgressDialogChild> dialogChild =
156
0
    new PrintProgressDialogChild(openDialogObserver, printSettings);
157
0
158
0
  SendPPrintProgressDialogConstructor(dialogChild);
159
0
160
0
  // Get the RemotePrintJob if we have one available.
161
0
  RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
162
0
  if (printSettings) {
163
0
    nsCOMPtr<nsIPrintSession> printSession;
164
0
    nsresult rv = printSettings->GetPrintSession(getter_AddRefs(printSession));
165
0
    if (NS_SUCCEEDED(rv) && printSession) {
166
0
      printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
167
0
    }
168
0
  }
169
0
170
0
  // NOTE: We set notifyOnOpen to true unconditionally. If the parent process
171
0
  // would get `false` for notifyOnOpen, then it will synthesize a notification
172
0
  // which will be sent asynchronously down to the child.
173
0
  *notifyOnOpen = true;
174
0
  mozilla::Unused << SendShowProgress(pBrowser, dialogChild, remotePrintJob,
175
0
                                      isForPrinting);
176
0
177
0
  // If we have a RemotePrintJob that will be being used as a more general
178
0
  // forwarder for print progress listeners. Once we always have one we can
179
0
  // remove the interface from PrintProgressDialogChild.
180
0
  if (!remotePrintJob) {
181
0
    NS_ADDREF(*webProgressListener = dialogChild);
182
0
  }
183
0
  NS_ADDREF(*printProgressParams = dialogChild);
184
0
185
0
  return NS_OK;
186
0
}
187
188
NS_IMETHODIMP
189
nsPrintingProxy::ShowPageSetup(mozIDOMWindowProxy *parent,
190
                               nsIPrintSettings *printSettings)
191
0
{
192
0
  return NS_ERROR_NOT_IMPLEMENTED;
193
0
}
194
195
nsresult
196
nsPrintingProxy::SavePrintSettings(nsIPrintSettings* aPS,
197
                                   bool aUsePrinterNamePrefix,
198
                                   uint32_t aFlags)
199
0
{
200
0
  nsresult rv;
201
0
  nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
202
0
    do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
203
0
  NS_ENSURE_SUCCESS(rv, rv);
204
0
205
0
  PrintData settings;
206
0
  rv = printSettingsSvc->SerializeToPrintData(aPS, nullptr, &settings);
207
0
  NS_ENSURE_SUCCESS(rv, rv);
208
0
209
0
  Unused << SendSavePrintSettings(settings, aUsePrinterNamePrefix, aFlags,
210
0
                                  &rv);
211
0
  return rv;
212
0
}
213
214
PPrintProgressDialogChild*
215
nsPrintingProxy::AllocPPrintProgressDialogChild()
216
0
{
217
0
  // The parent process will never initiate the PPrintProgressDialog
218
0
  // protocol connection, so no need to provide an allocator here.
219
0
  MOZ_ASSERT_UNREACHABLE("Allocator for PPrintProgressDialogChild should not "
220
0
                         "be called on nsPrintingProxy.");
221
0
  return nullptr;
222
0
}
223
224
bool
225
nsPrintingProxy::DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor)
226
0
{
227
0
  // The PrintProgressDialogChild implements refcounting, and
228
0
  // will take itself out.
229
0
  return true;
230
0
}
231
232
PPrintSettingsDialogChild*
233
nsPrintingProxy::AllocPPrintSettingsDialogChild()
234
0
{
235
0
  // The parent process will never initiate the PPrintSettingsDialog
236
0
  // protocol connection, so no need to provide an allocator here.
237
0
  MOZ_ASSERT_UNREACHABLE("Allocator for PPrintSettingsDialogChild should not "
238
0
                         "be called on nsPrintingProxy.");
239
0
  return nullptr;
240
0
}
241
242
bool
243
nsPrintingProxy::DeallocPPrintSettingsDialogChild(PPrintSettingsDialogChild* aActor)
244
0
{
245
0
  // The PrintSettingsDialogChild implements refcounting, and
246
0
  // will take itself out.
247
0
  return true;
248
0
}
249
250
PRemotePrintJobChild*
251
nsPrintingProxy::AllocPRemotePrintJobChild()
252
0
{
253
0
  RefPtr<RemotePrintJobChild> remotePrintJob = new RemotePrintJobChild();
254
0
  return remotePrintJob.forget().take();
255
0
}
256
257
bool
258
nsPrintingProxy::DeallocPRemotePrintJobChild(PRemotePrintJobChild* aDoomed)
259
0
{
260
0
  RemotePrintJobChild* remotePrintJob = static_cast<RemotePrintJobChild*>(aDoomed);
261
0
  NS_RELEASE(remotePrintJob);
262
0
  return true;
263
0
}