Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/widget/nsDeviceContextSpecProxy.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 "nsDeviceContextSpecProxy.h"
8
9
#include "gfxASurface.h"
10
#include "gfxPlatform.h"
11
#include "mozilla/gfx/DrawEventRecorder.h"
12
#include "mozilla/gfx/PrintTargetThebes.h"
13
#include "mozilla/layout/RemotePrintJobChild.h"
14
#include "mozilla/RefPtr.h"
15
#include "mozilla/Unused.h"
16
#include "nsComponentManagerUtils.h"
17
#include "nsAppDirectoryServiceDefs.h"
18
#include "nsDirectoryServiceUtils.h"
19
#include "nsIPrintSession.h"
20
#include "nsIPrintSettings.h"
21
#include "nsIUUIDGenerator.h"
22
#include "private/pprio.h"
23
24
using mozilla::Unused;
25
26
using namespace mozilla;
27
using namespace mozilla::gfx;
28
29
NS_IMPL_ISUPPORTS(nsDeviceContextSpecProxy, nsIDeviceContextSpec)
30
31
NS_IMETHODIMP
32
nsDeviceContextSpecProxy::Init(nsIWidget* aWidget,
33
                               nsIPrintSettings* aPrintSettings,
34
                               bool aIsPrintPreview)
35
0
{
36
0
  nsresult rv;
37
0
  mRealDeviceContextSpec =
38
0
    do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv);
39
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
40
0
    return rv;
41
0
  }
42
0
43
0
  mRealDeviceContextSpec->Init(nullptr, aPrintSettings, aIsPrintPreview);
44
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
45
0
    mRealDeviceContextSpec = nullptr;
46
0
    return rv;
47
0
  }
48
0
49
0
  mPrintSettings = aPrintSettings;
50
0
51
0
  if (aIsPrintPreview) {
52
0
    return NS_OK;
53
0
  }
54
0
55
0
  // nsIPrintSettings only has a weak reference to nsIPrintSession, so we hold
56
0
  // it to make sure it's available for the lifetime of the print.
57
0
  rv = mPrintSettings->GetPrintSession(getter_AddRefs(mPrintSession));
58
0
  if (NS_FAILED(rv) || !mPrintSession) {
59
0
    NS_WARNING("We can't print via the parent without an nsIPrintSession.");
60
0
    return NS_ERROR_FAILURE;
61
0
  }
62
0
63
0
  rv = mPrintSession->GetRemotePrintJob(getter_AddRefs(mRemotePrintJob));
64
0
  if (NS_FAILED(rv) || !mRemotePrintJob) {
65
0
    NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
66
0
    return NS_ERROR_FAILURE;
67
0
  }
68
0
69
0
  return NS_OK;
70
0
}
71
72
already_AddRefed<PrintTarget>
73
nsDeviceContextSpecProxy::MakePrintTarget()
74
0
{
75
0
  MOZ_ASSERT(mRealDeviceContextSpec);
76
0
77
0
  double width, height;
78
0
  nsresult rv = mPrintSettings->GetEffectivePageSize(&width, &height);
79
0
  if (NS_WARN_IF(NS_FAILED(rv)) || width <= 0 || height <= 0) {
80
0
    return nullptr;
81
0
  }
82
0
83
0
  // convert twips to points
84
0
  width /= TWIPS_PER_POINT_FLOAT;
85
0
  height /= TWIPS_PER_POINT_FLOAT;
86
0
87
0
  RefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
88
0
    CreateOffscreenSurface(mozilla::gfx::IntSize::Truncate(width, height),
89
0
                           mozilla::gfx::SurfaceFormat::A8R8G8B8_UINT32);
90
0
  if (!surface) {
91
0
    return nullptr;
92
0
  }
93
0
94
0
  // The type of PrintTarget that we return here shouldn't really matter since
95
0
  // our implementation of GetDrawEventRecorder returns an object, which means
96
0
  // the DrawTarget returned by the PrintTarget will be a DrawTargetWrapAndRecord.
97
0
  // The recording will be serialized and sent over to the parent process where
98
0
  // PrintTranslator::TranslateRecording will call MakePrintTarget (indirectly
99
0
  // via PrintTranslator::CreateDrawTarget) on whatever type of
100
0
  // nsIDeviceContextSpecProxy is created for the platform that we are running
101
0
  // on.  It is that DrawTarget that the recording will be replayed on to
102
0
  // print.
103
0
  // XXX(jwatt): The above isn't quite true.  We do want to use a
104
0
  // PrintTargetRecording here, but we can't until bug 1280324 is figured out
105
0
  // and fixed otherwise we will cause bug 1280181 to happen again.
106
0
  RefPtr<PrintTarget> target = PrintTargetThebes::CreateOrNull(surface);
107
0
108
0
  return target.forget();
109
0
}
110
111
NS_IMETHODIMP
112
nsDeviceContextSpecProxy::GetDrawEventRecorder(mozilla::gfx::DrawEventRecorder** aDrawEventRecorder)
113
0
{
114
0
  MOZ_ASSERT(aDrawEventRecorder);
115
0
  RefPtr<mozilla::gfx::DrawEventRecorder> result = mRecorder;
116
0
  result.forget(aDrawEventRecorder);
117
0
  return NS_OK;
118
0
}
119
120
float
121
nsDeviceContextSpecProxy::GetDPI()
122
0
{
123
0
  MOZ_ASSERT(mRealDeviceContextSpec);
124
0
125
0
  return mRealDeviceContextSpec->GetDPI();
126
0
}
127
128
float
129
nsDeviceContextSpecProxy::GetPrintingScale()
130
0
{
131
0
  MOZ_ASSERT(mRealDeviceContextSpec);
132
0
133
0
  return mRealDeviceContextSpec->GetPrintingScale();
134
0
}
135
136
gfxPoint
137
nsDeviceContextSpecProxy::GetPrintingTranslate()
138
0
{
139
0
  MOZ_ASSERT(mRealDeviceContextSpec);
140
0
141
0
  return mRealDeviceContextSpec->GetPrintingTranslate();
142
0
}
143
144
NS_IMETHODIMP
145
nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
146
                                        const nsAString& aPrintToFileName,
147
                                        int32_t aStartPage, int32_t aEndPage)
148
0
{
149
0
  mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc();
150
0
  nsresult rv = mRemotePrintJob->InitializePrint(nsString(aTitle),
151
0
                                                 nsString(aPrintToFileName),
152
0
                                                 aStartPage, aEndPage);
153
0
  if (NS_FAILED(rv)) {
154
0
    // The parent process will send a 'delete' message to tell this process to
155
0
    // delete our RemotePrintJobChild.  As soon as we return to the event loop
156
0
    // and evaluate that message we will crash if we try to access
157
0
    // mRemotePrintJob.  We must not try to use it again.
158
0
    mRemotePrintJob = nullptr;
159
0
  }
160
0
  return rv;
161
0
}
162
163
NS_IMETHODIMP
164
nsDeviceContextSpecProxy::EndDocument()
165
0
{
166
0
  if (mRemotePrintJob) {
167
0
    Unused << mRemotePrintJob->SendFinalizePrint();
168
0
  }
169
0
  return NS_OK;
170
0
}
171
172
NS_IMETHODIMP
173
nsDeviceContextSpecProxy::AbortDocument()
174
0
{
175
0
  if (mRemotePrintJob) {
176
0
    Unused << mRemotePrintJob->SendAbortPrint(NS_OK);
177
0
  }
178
0
  return NS_OK;
179
0
}
180
181
NS_IMETHODIMP
182
nsDeviceContextSpecProxy::BeginPage()
183
0
{
184
0
  mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD());
185
0
186
0
  return NS_OK;
187
0
}
188
189
NS_IMETHODIMP
190
nsDeviceContextSpecProxy::EndPage()
191
0
{
192
0
  // Send the page recording to the parent.
193
0
  mRecorder->Close();
194
0
  mRemotePrintJob->ProcessPage();
195
0
196
0
  return NS_OK;
197
0
}