Bug 1454293 [wpt PR 10484] - null is not the correct origin for createDocument()...
[gecko.git] / widget / nsDeviceContextSpecProxy.cpp
blob012bc0d2c22e8ab0a709767e77de33eb528d5de5
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 "nsIPrintSession.h"
20 #include "nsIPrintSettings.h"
21 #include "nsIUUIDGenerator.h"
22 #include "private/pprio.h"
24 using mozilla::Unused;
26 using namespace mozilla;
27 using namespace mozilla::gfx;
29 NS_IMPL_ISUPPORTS(nsDeviceContextSpecProxy, nsIDeviceContextSpec)
31 NS_IMETHODIMP
32 nsDeviceContextSpecProxy::Init(nsIWidget* aWidget,
33 nsIPrintSettings* aPrintSettings,
34 bool aIsPrintPreview)
36 nsresult rv;
37 mRealDeviceContextSpec =
38 do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv);
39 if (NS_WARN_IF(NS_FAILED(rv))) {
40 return rv;
43 mRealDeviceContextSpec->Init(nullptr, aPrintSettings, aIsPrintPreview);
44 if (NS_WARN_IF(NS_FAILED(rv))) {
45 mRealDeviceContextSpec = nullptr;
46 return rv;
49 mPrintSettings = aPrintSettings;
51 if (aIsPrintPreview) {
52 return NS_OK;
55 // nsIPrintSettings only has a weak reference to nsIPrintSession, so we hold
56 // it to make sure it's available for the lifetime of the print.
57 rv = mPrintSettings->GetPrintSession(getter_AddRefs(mPrintSession));
58 if (NS_FAILED(rv) || !mPrintSession) {
59 NS_WARNING("We can't print via the parent without an nsIPrintSession.");
60 return NS_ERROR_FAILURE;
63 rv = mPrintSession->GetRemotePrintJob(getter_AddRefs(mRemotePrintJob));
64 if (NS_FAILED(rv) || !mRemotePrintJob) {
65 NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
66 return NS_ERROR_FAILURE;
69 return NS_OK;
72 already_AddRefed<PrintTarget>
73 nsDeviceContextSpecProxy::MakePrintTarget()
75 MOZ_ASSERT(mRealDeviceContextSpec);
77 double width, height;
78 nsresult rv = mPrintSettings->GetEffectivePageSize(&width, &height);
79 if (NS_WARN_IF(NS_FAILED(rv)) || width <= 0 || height <= 0) {
80 return nullptr;
83 // convert twips to points
84 width /= TWIPS_PER_POINT_FLOAT;
85 height /= TWIPS_PER_POINT_FLOAT;
87 RefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
88 CreateOffscreenSurface(mozilla::gfx::IntSize::Truncate(width, height),
89 mozilla::gfx::SurfaceFormat::A8R8G8B8_UINT32);
90 if (!surface) {
91 return nullptr;
94 // The type of PrintTarget that we return here shouldn't really matter since
95 // our implementation of GetDrawEventRecorder returns an object, which means
96 // the DrawTarget returned by the PrintTarget will be a DrawTargetWrapAndRecord.
97 // The recording will be serialized and sent over to the parent process where
98 // PrintTranslator::TranslateRecording will call MakePrintTarget (indirectly
99 // via PrintTranslator::CreateDrawTarget) on whatever type of
100 // nsIDeviceContextSpecProxy is created for the platform that we are running
101 // on. It is that DrawTarget that the recording will be replayed on to
102 // print.
103 // XXX(jwatt): The above isn't quite true. We do want to use a
104 // PrintTargetRecording here, but we can't until bug 1280324 is figured out
105 // and fixed otherwise we will cause bug 1280181 to happen again.
106 RefPtr<PrintTarget> target = PrintTargetThebes::CreateOrNull(surface);
108 return target.forget();
111 NS_IMETHODIMP
112 nsDeviceContextSpecProxy::GetDrawEventRecorder(mozilla::gfx::DrawEventRecorder** aDrawEventRecorder)
114 MOZ_ASSERT(aDrawEventRecorder);
115 RefPtr<mozilla::gfx::DrawEventRecorder> result = mRecorder;
116 result.forget(aDrawEventRecorder);
117 return NS_OK;
120 float
121 nsDeviceContextSpecProxy::GetDPI()
123 MOZ_ASSERT(mRealDeviceContextSpec);
125 return mRealDeviceContextSpec->GetDPI();
128 float
129 nsDeviceContextSpecProxy::GetPrintingScale()
131 MOZ_ASSERT(mRealDeviceContextSpec);
133 return mRealDeviceContextSpec->GetPrintingScale();
136 NS_IMETHODIMP
137 nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
138 const nsAString& aPrintToFileName,
139 int32_t aStartPage, int32_t aEndPage)
141 mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc();
142 nsresult rv = mRemotePrintJob->InitializePrint(nsString(aTitle),
143 nsString(aPrintToFileName),
144 aStartPage, aEndPage);
145 if (NS_FAILED(rv)) {
146 // The parent process will send a 'delete' message to tell this process to
147 // delete our RemotePrintJobChild. As soon as we return to the event loop
148 // and evaluate that message we will crash if we try to access
149 // mRemotePrintJob. We must not try to use it again.
150 mRemotePrintJob = nullptr;
152 return rv;
155 NS_IMETHODIMP
156 nsDeviceContextSpecProxy::EndDocument()
158 if (mRemotePrintJob) {
159 Unused << mRemotePrintJob->SendFinalizePrint();
161 return NS_OK;
164 NS_IMETHODIMP
165 nsDeviceContextSpecProxy::AbortDocument()
167 if (mRemotePrintJob) {
168 Unused << mRemotePrintJob->SendAbortPrint(NS_OK);
170 return NS_OK;
173 NS_IMETHODIMP
174 nsDeviceContextSpecProxy::BeginPage()
176 mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD());
178 return NS_OK;
181 NS_IMETHODIMP
182 nsDeviceContextSpecProxy::EndPage()
184 // Send the page recording to the parent.
185 mRecorder->Close();
186 mRemotePrintJob->ProcessPage();
188 return NS_OK;