Bug 1942006 - Upstream a variety of Servo-specific code from Servo's downstream fork...
[gecko.git] / widget / nsPrinterBase.cpp
blob0af3bcf9dc0e03776f914b69f0024deaf424f275
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsPrinterBase.h"
7 #include "nsPaperMargin.h"
8 #include <utility>
9 #include "nsPaper.h"
10 #include "nsIPrintSettings.h"
11 #include "nsPrintSettingsService.h"
12 #include "PrintBackgroundTask.h"
13 #include "mozilla/EnumeratedArrayCycleCollection.h"
14 #include "mozilla/dom/Promise.h"
16 using namespace mozilla;
17 using mozilla::dom::Promise;
18 using mozilla::gfx::MarginDouble;
20 // The maximum error when considering a paper size equal, in points.
21 // There is some variance in the actual sizes returned by printer drivers and
22 // print servers for paper sizes. This is a best-guess based on initial
23 // telemetry which should catch most near-miss dimensions. This should let us
24 // get consistent paper size names even when the size isn't quite exactly the
25 // correct size.
26 static constexpr double kPaperSizePointsEpsilon = 4.0;
28 // Basic implementation of nsIPrinterInfo
29 class nsPrinterInfo : public nsIPrinterInfo {
30 public:
31 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
32 NS_DECL_CYCLE_COLLECTION_CLASS(nsPrinterInfo)
33 NS_DECL_NSIPRINTERINFO
34 nsPrinterInfo() = delete;
35 nsPrinterInfo(nsPrinterBase& aPrinter,
36 const nsPrinterBase::PrinterInfo& aPrinterInfo)
37 : mDefaultSettings(
38 CreatePlatformPrintSettings(aPrinterInfo.mDefaultSettings)) {
39 mPaperList.SetCapacity(aPrinterInfo.mPaperList.Length());
40 for (const PaperInfo& info : aPrinterInfo.mPaperList) {
41 mPaperList.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
44 // Update the printer's default settings with the global settings.
45 nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
46 do_GetService("@mozilla.org/gfx/printsettings-service;1");
47 if (printSettingsSvc) {
48 // Passing false as the second parameter means we don't get the printer
49 // specific settings.
50 printSettingsSvc->InitPrintSettingsFromPrefs(
51 mDefaultSettings, false, nsIPrintSettings::kInitSaveAll);
55 private:
56 virtual ~nsPrinterInfo() = default;
58 nsTArray<RefPtr<nsIPaper>> mPaperList;
59 RefPtr<nsIPrintSettings> mDefaultSettings;
62 NS_IMETHODIMP
63 nsPrinterInfo::GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) {
64 aPaperList = mPaperList.Clone();
65 return NS_OK;
68 NS_IMETHODIMP
69 nsPrinterInfo::GetDefaultSettings(nsIPrintSettings** aDefaultSettings) {
70 NS_ENSURE_ARG_POINTER(aDefaultSettings);
71 MOZ_ASSERT(mDefaultSettings);
72 RefPtr<nsIPrintSettings> settings = mDefaultSettings;
73 settings.forget(aDefaultSettings);
74 return NS_OK;
77 NS_IMPL_CYCLE_COLLECTION(nsPrinterInfo, mPaperList, mDefaultSettings)
79 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterInfo)
80 NS_INTERFACE_MAP_ENTRY(nsIPrinterInfo)
81 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrinterInfo)
82 NS_INTERFACE_MAP_END
84 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterInfo)
85 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterInfo)
87 namespace mozilla {
89 template <>
90 void ResolveOrReject(Promise& aPromise, nsPrinterBase&,
91 const MarginDouble& aResult) {
92 auto margin = MakeRefPtr<nsPaperMargin>(aResult);
93 aPromise.MaybeResolve(margin);
96 template <>
97 void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
98 const nsTArray<PaperInfo>& aResult) {
99 nsTArray<RefPtr<nsPaper>> result;
100 result.SetCapacity(aResult.Length());
101 for (const PaperInfo& info : aResult) {
102 result.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
104 aPromise.MaybeResolve(result);
107 template <>
108 void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
109 const PrintSettingsInitializer& aResult) {
110 aPromise.MaybeResolve(
111 RefPtr<nsIPrintSettings>(CreatePlatformPrintSettings(aResult)));
114 template <>
115 void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
116 const nsPrinterBase::PrinterInfo& aResult) {
117 aPromise.MaybeResolve(MakeRefPtr<nsPrinterInfo>(aPrinter, aResult));
120 } // namespace mozilla
122 template <typename T, typename... Args>
123 nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
124 JSContext* aCx, Promise** aResultPromise, AsyncAttribute aAttribute,
125 BackgroundTask<T, Args...> aBackgroundTask, Args... aArgs) {
126 MOZ_ASSERT(NS_IsMainThread());
128 return mozilla::AsyncPromiseAttributeGetter(
129 *this, mAsyncAttributePromises[aAttribute], aCx, aResultPromise,
130 aBackgroundTask, std::forward<Args>(aArgs)...);
133 NS_IMETHODIMP nsPrinterBase::CopyFromWithValidation(
134 nsIPrintSettings* aSettingsToCopyFrom, JSContext* aCx,
135 Promise** aResultPromise) {
136 MOZ_ASSERT(NS_IsMainThread());
137 MOZ_ASSERT(aResultPromise);
139 ErrorResult errorResult;
140 RefPtr<dom::Promise> promise =
141 dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), errorResult);
142 if (MOZ_UNLIKELY(errorResult.Failed())) {
143 return errorResult.StealNSResult();
146 nsCOMPtr<nsIPrintSettings> settings;
147 MOZ_ALWAYS_SUCCEEDS(aSettingsToCopyFrom->Clone(getter_AddRefs(settings)));
148 nsString printerName;
149 MOZ_ALWAYS_SUCCEEDS(GetName(printerName));
150 MOZ_ALWAYS_SUCCEEDS(settings->SetPrinterName(printerName));
151 promise->MaybeResolve(settings);
152 promise.forget(aResultPromise);
154 return NS_OK;
157 NS_IMETHODIMP nsPrinterBase::GetSupportsDuplex(JSContext* aCx,
158 Promise** aResultPromise) {
159 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
160 AsyncAttribute::SupportsDuplex,
161 &nsPrinterBase::SupportsDuplex);
164 NS_IMETHODIMP nsPrinterBase::GetSupportsColor(JSContext* aCx,
165 Promise** aResultPromise) {
166 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
167 AsyncAttribute::SupportsColor,
168 &nsPrinterBase::SupportsColor);
171 NS_IMETHODIMP nsPrinterBase::GetSupportsMonochrome(JSContext* aCx,
172 Promise** aResultPromise) {
173 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
174 AsyncAttribute::SupportsMonochrome,
175 &nsPrinterBase::SupportsMonochrome);
178 NS_IMETHODIMP nsPrinterBase::GetSupportsCollation(JSContext* aCx,
179 Promise** aResultPromise) {
180 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
181 AsyncAttribute::SupportsCollation,
182 &nsPrinterBase::SupportsCollation);
185 NS_IMETHODIMP nsPrinterBase::GetPrinterInfo(JSContext* aCx,
186 Promise** aResultPromise) {
187 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
188 AsyncAttribute::PrinterInfo,
189 &nsPrinterBase::CreatePrinterInfo);
192 void nsPrinterBase::QueryMarginsForPaper(Promise& aPromise,
193 const nsString& aPaperId) {
194 return SpawnPrintBackgroundTask(*this, aPromise,
195 &nsPrinterBase::GetMarginsForPaper, aPaperId);
198 NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises)
200 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase)
201 NS_INTERFACE_MAP_ENTRY(nsIPrinter)
202 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrinter)
203 NS_INTERFACE_MAP_END
205 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterBase)
206 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterBase)
208 nsPrinterBase::nsPrinterBase(const CommonPaperInfoArray* aPaperInfoArray)
209 : mCommonPaperInfo(aPaperInfoArray) {
210 MOZ_DIAGNOSTIC_ASSERT(aPaperInfoArray, "Localized paper info was null");
212 nsPrinterBase::~nsPrinterBase() = default;
214 const PaperInfo* nsPrinterBase::FindCommonPaperSize(
215 const gfx::SizeDouble& aSize) const {
216 for (const PaperInfo& paper : *mCommonPaperInfo) {
217 if (std::abs(paper.mSize.width - aSize.width) <= kPaperSizePointsEpsilon &&
218 std::abs(paper.mSize.height - aSize.height) <=
219 kPaperSizePointsEpsilon) {
220 return &paper;
223 return nullptr;