Bug 1869043 assert that graph set access is main thread only r=padenot
[gecko.git] / widget / nsPrinterBase.cpp
blob7e01b9e12f676456b43cbe2b9c90b7799aaa390b
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/dom/Promise.h"
15 using namespace mozilla;
16 using mozilla::dom::Promise;
17 using mozilla::gfx::MarginDouble;
19 // The maximum error when considering a paper size equal, in points.
20 // There is some variance in the actual sizes returned by printer drivers and
21 // print servers for paper sizes. This is a best-guess based on initial
22 // telemetry which should catch most near-miss dimensions. This should let us
23 // get consistent paper size names even when the size isn't quite exactly the
24 // correct size.
25 static constexpr double kPaperSizePointsEpsilon = 4.0;
27 // Basic implementation of nsIPrinterInfo
28 class nsPrinterInfo : public nsIPrinterInfo {
29 public:
30 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
31 NS_DECL_CYCLE_COLLECTION_CLASS(nsPrinterInfo)
32 NS_DECL_NSIPRINTERINFO
33 nsPrinterInfo() = delete;
34 nsPrinterInfo(nsPrinterBase& aPrinter,
35 const nsPrinterBase::PrinterInfo& aPrinterInfo)
36 : mDefaultSettings(
37 CreatePlatformPrintSettings(aPrinterInfo.mDefaultSettings)) {
38 mPaperList.SetCapacity(aPrinterInfo.mPaperList.Length());
39 for (const PaperInfo& info : aPrinterInfo.mPaperList) {
40 mPaperList.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
43 // Update the printer's default settings with the global settings.
44 nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
45 do_GetService("@mozilla.org/gfx/printsettings-service;1");
46 if (printSettingsSvc) {
47 // Passing false as the second parameter means we don't get the printer
48 // specific settings.
49 printSettingsSvc->InitPrintSettingsFromPrefs(
50 mDefaultSettings, false, nsIPrintSettings::kInitSaveAll);
54 private:
55 virtual ~nsPrinterInfo() = default;
57 nsTArray<RefPtr<nsIPaper>> mPaperList;
58 RefPtr<nsIPrintSettings> mDefaultSettings;
61 NS_IMETHODIMP
62 nsPrinterInfo::GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) {
63 aPaperList = mPaperList.Clone();
64 return NS_OK;
67 NS_IMETHODIMP
68 nsPrinterInfo::GetDefaultSettings(nsIPrintSettings** aDefaultSettings) {
69 NS_ENSURE_ARG_POINTER(aDefaultSettings);
70 MOZ_ASSERT(mDefaultSettings);
71 RefPtr<nsIPrintSettings> settings = mDefaultSettings;
72 settings.forget(aDefaultSettings);
73 return NS_OK;
76 NS_IMPL_CYCLE_COLLECTION(nsPrinterInfo, mPaperList, mDefaultSettings)
78 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterInfo)
79 NS_INTERFACE_MAP_ENTRY(nsIPrinterInfo)
80 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrinterInfo)
81 NS_INTERFACE_MAP_END
83 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterInfo)
84 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterInfo)
86 template <typename Index, Index Size, typename Value>
87 inline void ImplCycleCollectionTraverse(
88 nsCycleCollectionTraversalCallback& aCallback,
89 EnumeratedArray<Index, Size, Value>& aArray, const char* aName,
90 uint32_t aFlags = 0) {
91 aFlags |= CycleCollectionEdgeNameArrayFlag;
92 for (Value& element : aArray) {
93 ImplCycleCollectionTraverse(aCallback, element, aName, aFlags);
97 template <typename Index, Index Size, typename Value>
98 inline void ImplCycleCollectionUnlink(
99 EnumeratedArray<Index, Size, Value>& aArray) {
100 for (Value& element : aArray) {
101 ImplCycleCollectionUnlink(element);
105 namespace mozilla {
107 template <>
108 void ResolveOrReject(Promise& aPromise, nsPrinterBase&,
109 const MarginDouble& aResult) {
110 auto margin = MakeRefPtr<nsPaperMargin>(aResult);
111 aPromise.MaybeResolve(margin);
114 template <>
115 void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
116 const nsTArray<PaperInfo>& aResult) {
117 nsTArray<RefPtr<nsPaper>> result;
118 result.SetCapacity(aResult.Length());
119 for (const PaperInfo& info : aResult) {
120 result.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
122 aPromise.MaybeResolve(result);
125 template <>
126 void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
127 const PrintSettingsInitializer& aResult) {
128 aPromise.MaybeResolve(
129 RefPtr<nsIPrintSettings>(CreatePlatformPrintSettings(aResult)));
132 template <>
133 void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
134 const nsPrinterBase::PrinterInfo& aResult) {
135 aPromise.MaybeResolve(MakeRefPtr<nsPrinterInfo>(aPrinter, aResult));
138 } // namespace mozilla
140 template <typename T, typename... Args>
141 nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
142 JSContext* aCx, Promise** aResultPromise, AsyncAttribute aAttribute,
143 BackgroundTask<T, Args...> aBackgroundTask, Args... aArgs) {
144 MOZ_ASSERT(NS_IsMainThread());
146 static constexpr EnumeratedArray<AsyncAttribute, AsyncAttribute::Last,
147 nsLiteralCString>
148 attributeKeys{"SupportsDuplex"_ns, "SupportsColor"_ns,
149 "SupportsMonochrome"_ns, "SupportsCollation"_ns,
150 "PrinterInfo"_ns};
151 return mozilla::AsyncPromiseAttributeGetter(
152 *this, mAsyncAttributePromises[aAttribute], aCx, aResultPromise,
153 attributeKeys[aAttribute], aBackgroundTask, std::forward<Args>(aArgs)...);
156 NS_IMETHODIMP nsPrinterBase::CopyFromWithValidation(
157 nsIPrintSettings* aSettingsToCopyFrom, JSContext* aCx,
158 Promise** aResultPromise) {
159 MOZ_ASSERT(NS_IsMainThread());
160 MOZ_ASSERT(aResultPromise);
162 ErrorResult errorResult;
163 RefPtr<dom::Promise> promise =
164 dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), errorResult);
165 if (MOZ_UNLIKELY(errorResult.Failed())) {
166 return errorResult.StealNSResult();
169 nsCOMPtr<nsIPrintSettings> settings;
170 MOZ_ALWAYS_SUCCEEDS(aSettingsToCopyFrom->Clone(getter_AddRefs(settings)));
171 nsString printerName;
172 MOZ_ALWAYS_SUCCEEDS(GetName(printerName));
173 MOZ_ALWAYS_SUCCEEDS(settings->SetPrinterName(printerName));
174 promise->MaybeResolve(settings);
175 promise.forget(aResultPromise);
177 return NS_OK;
180 NS_IMETHODIMP nsPrinterBase::GetSupportsDuplex(JSContext* aCx,
181 Promise** aResultPromise) {
182 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
183 AsyncAttribute::SupportsDuplex,
184 &nsPrinterBase::SupportsDuplex);
187 NS_IMETHODIMP nsPrinterBase::GetSupportsColor(JSContext* aCx,
188 Promise** aResultPromise) {
189 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
190 AsyncAttribute::SupportsColor,
191 &nsPrinterBase::SupportsColor);
194 NS_IMETHODIMP nsPrinterBase::GetSupportsMonochrome(JSContext* aCx,
195 Promise** aResultPromise) {
196 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
197 AsyncAttribute::SupportsMonochrome,
198 &nsPrinterBase::SupportsMonochrome);
201 NS_IMETHODIMP nsPrinterBase::GetSupportsCollation(JSContext* aCx,
202 Promise** aResultPromise) {
203 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
204 AsyncAttribute::SupportsCollation,
205 &nsPrinterBase::SupportsCollation);
208 NS_IMETHODIMP nsPrinterBase::GetPrinterInfo(JSContext* aCx,
209 Promise** aResultPromise) {
210 return AsyncPromiseAttributeGetter(aCx, aResultPromise,
211 AsyncAttribute::PrinterInfo,
212 &nsPrinterBase::CreatePrinterInfo);
215 void nsPrinterBase::QueryMarginsForPaper(Promise& aPromise,
216 const nsString& aPaperId) {
217 return SpawnPrintBackgroundTask(*this, aPromise, "MarginsForPaper"_ns,
218 &nsPrinterBase::GetMarginsForPaper, aPaperId);
221 NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises)
223 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase)
224 NS_INTERFACE_MAP_ENTRY(nsIPrinter)
225 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrinter)
226 NS_INTERFACE_MAP_END
228 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterBase)
229 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterBase)
231 nsPrinterBase::nsPrinterBase(const CommonPaperInfoArray* aPaperInfoArray)
232 : mCommonPaperInfo(aPaperInfoArray) {
233 MOZ_DIAGNOSTIC_ASSERT(aPaperInfoArray, "Localized paper info was null");
235 nsPrinterBase::~nsPrinterBase() = default;
237 const PaperInfo* nsPrinterBase::FindCommonPaperSize(
238 const gfx::SizeDouble& aSize) const {
239 for (const PaperInfo& paper : *mCommonPaperInfo) {
240 if (std::abs(paper.mSize.width - aSize.width) <= kPaperSizePointsEpsilon &&
241 std::abs(paper.mSize.height - aSize.height) <=
242 kPaperSizePointsEpsilon) {
243 return &paper;
246 return nullptr;