Bug 1869647 - Mark hasStorageAccess.sub.https.window.html as intermittent after wpt...
[gecko.git] / widget / nsDeviceContextSpecProxy.cpp
blobeed6e9b9995d694332eddec246ee06ea2c2e02df
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/. */
7 #include "nsDeviceContextSpecProxy.h"
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 "nsIPrintSettings.h"
20 #include "private/pprio.h"
22 using mozilla::Unused;
24 using namespace mozilla;
25 using namespace mozilla::gfx;
27 NS_IMPL_ISUPPORTS(nsDeviceContextSpecProxy, nsIDeviceContextSpec)
29 nsDeviceContextSpecProxy::nsDeviceContextSpecProxy(
30 RemotePrintJobChild* aRemotePrintJob)
31 : mRemotePrintJob(aRemotePrintJob) {}
32 nsDeviceContextSpecProxy::~nsDeviceContextSpecProxy() = default;
34 NS_IMETHODIMP
35 nsDeviceContextSpecProxy::Init(nsIPrintSettings* aPrintSettings,
36 bool aIsPrintPreview) {
37 mPrintSettings = aPrintSettings;
39 if (aIsPrintPreview) {
40 return NS_OK;
43 if (!mRemotePrintJob) {
44 NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
45 return NS_ERROR_FAILURE;
48 return NS_OK;
51 already_AddRefed<PrintTarget> nsDeviceContextSpecProxy::MakePrintTarget() {
52 double width, height;
53 mPrintSettings->GetEffectiveSheetSize(&width, &height);
54 if (width <= 0 || height <= 0) {
55 return nullptr;
58 // convert twips to points
59 width /= TWIPS_PER_POINT_FLOAT;
60 height /= TWIPS_PER_POINT_FLOAT;
62 RefPtr<gfxASurface> surface =
63 gfxPlatform::GetPlatform()->CreateOffscreenSurface(
64 mozilla::gfx::IntSize::Ceil(width, height),
65 mozilla::gfx::SurfaceFormat::A8R8G8B8_UINT32);
66 if (!surface) {
67 return nullptr;
70 // The type of PrintTarget that we return here shouldn't really matter since
71 // our implementation of GetDrawEventRecorder returns an object, which means
72 // the DrawTarget returned by the PrintTarget will be a
73 // DrawTargetWrapAndRecord. The recording will be serialized and sent over to
74 // the parent process where PrintTranslator::TranslateRecording will call
75 // MakePrintTarget (indirectly via PrintTranslator::CreateDrawTarget) on
76 // whatever type of nsIDeviceContextSpecProxy is created for the platform that
77 // we are running on. It is that DrawTarget that the recording will be
78 // replayed on to print.
79 // XXX(jwatt): The above isn't quite true. We do want to use a
80 // PrintTargetRecording here, but we can't until bug 1280324 is figured out
81 // and fixed otherwise we will cause bug 1280181 to happen again.
82 RefPtr<PrintTarget> target = PrintTargetThebes::CreateOrNull(surface);
84 return target.forget();
87 NS_IMETHODIMP
88 nsDeviceContextSpecProxy::GetDrawEventRecorder(
89 mozilla::gfx::DrawEventRecorder** aDrawEventRecorder) {
90 MOZ_ASSERT(aDrawEventRecorder);
91 RefPtr<mozilla::gfx::DrawEventRecorder> result = mRecorder;
92 result.forget(aDrawEventRecorder);
93 return NS_OK;
96 NS_IMETHODIMP
97 nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
98 const nsAString& aPrintToFileName,
99 int32_t aStartPage, int32_t aEndPage) {
100 if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
101 mRemotePrintJob = nullptr;
102 return NS_ERROR_NOT_AVAILABLE;
105 mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc();
106 nsresult rv =
107 mRemotePrintJob->InitializePrint(nsString(aTitle), aStartPage, aEndPage);
108 if (NS_FAILED(rv)) {
109 // The parent process will send a 'delete' message to tell this process to
110 // delete our RemotePrintJobChild. As soon as we return to the event loop
111 // and evaluate that message we will crash if we try to access
112 // mRemotePrintJob. We must not try to use it again.
113 mRemotePrintJob = nullptr;
115 return rv;
118 RefPtr<mozilla::gfx::PrintEndDocumentPromise>
119 nsDeviceContextSpecProxy::EndDocument() {
120 if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
121 mRemotePrintJob = nullptr;
122 return mozilla::gfx::PrintEndDocumentPromise::CreateAndReject(
123 NS_ERROR_NOT_AVAILABLE, __func__);
126 Unused << mRemotePrintJob->SendFinalizePrint();
128 return mozilla::gfx::PrintEndDocumentPromise::CreateAndResolve(true,
129 __func__);
132 NS_IMETHODIMP
133 nsDeviceContextSpecProxy::BeginPage(const IntSize& aSizeInPoints) {
134 if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
135 mRemotePrintJob = nullptr;
136 return NS_ERROR_NOT_AVAILABLE;
139 mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD());
140 mCurrentPageSizeInPoints = aSizeInPoints;
142 return NS_OK;
145 NS_IMETHODIMP
146 nsDeviceContextSpecProxy::EndPage() {
147 if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
148 mRemotePrintJob = nullptr;
149 return NS_ERROR_NOT_AVAILABLE;
152 // Send the page recording to the parent.
153 mRecorder->Close();
154 mRemotePrintJob->ProcessPage(mCurrentPageSizeInPoints,
155 std::move(mRecorder->TakeDependentSurfaces()));
157 return NS_OK;