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"
10 #include "nsIPrintSettings.h"
11 #include "PrintBackgroundTask.h"
12 #include "mozilla/dom/Promise.h"
14 using namespace mozilla
;
15 using mozilla::dom::Promise
;
16 using mozilla::gfx::MarginDouble
;
18 // The maximum error when considering a paper size equal, in points.
19 // There is some variance in the actual sizes returned by printer drivers and
20 // print servers for paper sizes. This is a best-guess based on initial
21 // telemetry which should catch most near-miss dimensions. This should let us
22 // get consistent paper size names even when the size isn't quite exactly the
24 static constexpr double kPaperSizePointsEpsilon
= 4.0;
26 // Basic implementation of nsIPrinterInfo
27 class nsPrinterInfo
: public nsIPrinterInfo
{
29 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
30 NS_DECL_CYCLE_COLLECTION_CLASS(nsPrinterInfo
)
31 NS_DECL_NSIPRINTERINFO
32 nsPrinterInfo() = delete;
33 nsPrinterInfo(nsPrinterBase
& aPrinter
,
34 const nsPrinterBase::PrinterInfo
& aPrinterInfo
)
36 CreatePlatformPrintSettings(aPrinterInfo
.mDefaultSettings
)) {
37 mPaperList
.SetCapacity(aPrinterInfo
.mPaperList
.Length());
38 for (const PaperInfo
& info
: aPrinterInfo
.mPaperList
) {
39 mPaperList
.AppendElement(MakeRefPtr
<nsPaper
>(aPrinter
, info
));
44 virtual ~nsPrinterInfo() = default;
46 nsTArray
<RefPtr
<nsIPaper
>> mPaperList
;
47 RefPtr
<nsIPrintSettings
> mDefaultSettings
;
51 nsPrinterInfo::GetPaperList(nsTArray
<RefPtr
<nsIPaper
>>& aPaperList
) {
52 aPaperList
= mPaperList
.Clone();
57 nsPrinterInfo::GetDefaultSettings(nsIPrintSettings
** aDefaultSettings
) {
58 NS_ENSURE_ARG_POINTER(aDefaultSettings
);
59 MOZ_ASSERT(mDefaultSettings
);
60 RefPtr
<nsIPrintSettings
> settings
= mDefaultSettings
;
61 settings
.forget(aDefaultSettings
);
65 NS_IMPL_CYCLE_COLLECTION(nsPrinterInfo
, mPaperList
, mDefaultSettings
)
67 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterInfo
)
68 NS_INTERFACE_MAP_ENTRY(nsIPrinterInfo
)
69 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPrinterInfo
)
72 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterInfo
)
73 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterInfo
)
75 template <typename Index
, Index Size
, typename Value
>
76 inline void ImplCycleCollectionTraverse(
77 nsCycleCollectionTraversalCallback
& aCallback
,
78 EnumeratedArray
<Index
, Size
, Value
>& aArray
, const char* aName
,
79 uint32_t aFlags
= 0) {
80 aFlags
|= CycleCollectionEdgeNameArrayFlag
;
81 for (Value
& element
: aArray
) {
82 ImplCycleCollectionTraverse(aCallback
, element
, aName
, aFlags
);
86 template <typename Index
, Index Size
, typename Value
>
87 inline void ImplCycleCollectionUnlink(
88 EnumeratedArray
<Index
, Size
, Value
>& aArray
) {
89 for (Value
& element
: aArray
) {
90 ImplCycleCollectionUnlink(element
);
97 void ResolveOrReject(Promise
& aPromise
, nsPrinterBase
&,
98 const MarginDouble
& aResult
) {
99 auto margin
= MakeRefPtr
<nsPaperMargin
>(aResult
);
100 aPromise
.MaybeResolve(margin
);
104 void ResolveOrReject(Promise
& aPromise
, nsPrinterBase
& aPrinter
,
105 const nsTArray
<PaperInfo
>& aResult
) {
106 nsTArray
<RefPtr
<nsPaper
>> result
;
107 result
.SetCapacity(aResult
.Length());
108 for (const PaperInfo
& info
: aResult
) {
109 result
.AppendElement(MakeRefPtr
<nsPaper
>(aPrinter
, info
));
111 aPromise
.MaybeResolve(result
);
115 void ResolveOrReject(Promise
& aPromise
, nsPrinterBase
& aPrinter
,
116 const PrintSettingsInitializer
& aResult
) {
117 aPromise
.MaybeResolve(
118 RefPtr
<nsIPrintSettings
>(CreatePlatformPrintSettings(aResult
)));
122 void ResolveOrReject(Promise
& aPromise
, nsPrinterBase
& aPrinter
,
123 const nsPrinterBase::PrinterInfo
& aResult
) {
124 aPromise
.MaybeResolve(MakeRefPtr
<nsPrinterInfo
>(aPrinter
, aResult
));
127 } // namespace mozilla
129 template <typename T
, typename
... Args
>
130 nsresult
nsPrinterBase::AsyncPromiseAttributeGetter(
131 JSContext
* aCx
, Promise
** aResultPromise
, AsyncAttribute aAttribute
,
132 BackgroundTask
<T
, Args
...> aBackgroundTask
, Args
... aArgs
) {
133 MOZ_ASSERT(NS_IsMainThread());
135 static constexpr EnumeratedArray
<AsyncAttribute
, AsyncAttribute::Last
,
137 attributeKeys
{"SupportsDuplex"_ns
, "SupportsColor"_ns
,
138 "SupportsMonochrome"_ns
, "SupportsCollation"_ns
,
140 return mozilla::AsyncPromiseAttributeGetter(
141 *this, mAsyncAttributePromises
[aAttribute
], aCx
, aResultPromise
,
142 attributeKeys
[aAttribute
], aBackgroundTask
, std::forward
<Args
>(aArgs
)...);
145 NS_IMETHODIMP
nsPrinterBase::GetSupportsDuplex(JSContext
* aCx
,
146 Promise
** aResultPromise
) {
147 return AsyncPromiseAttributeGetter(aCx
, aResultPromise
,
148 AsyncAttribute::SupportsDuplex
,
149 &nsPrinterBase::SupportsDuplex
);
152 NS_IMETHODIMP
nsPrinterBase::GetSupportsColor(JSContext
* aCx
,
153 Promise
** aResultPromise
) {
154 return AsyncPromiseAttributeGetter(aCx
, aResultPromise
,
155 AsyncAttribute::SupportsColor
,
156 &nsPrinterBase::SupportsColor
);
159 NS_IMETHODIMP
nsPrinterBase::GetSupportsMonochrome(JSContext
* aCx
,
160 Promise
** aResultPromise
) {
161 return AsyncPromiseAttributeGetter(aCx
, aResultPromise
,
162 AsyncAttribute::SupportsMonochrome
,
163 &nsPrinterBase::SupportsMonochrome
);
166 NS_IMETHODIMP
nsPrinterBase::GetSupportsCollation(JSContext
* aCx
,
167 Promise
** aResultPromise
) {
168 return AsyncPromiseAttributeGetter(aCx
, aResultPromise
,
169 AsyncAttribute::SupportsCollation
,
170 &nsPrinterBase::SupportsCollation
);
173 NS_IMETHODIMP
nsPrinterBase::GetPrinterInfo(JSContext
* aCx
,
174 Promise
** aResultPromise
) {
175 return AsyncPromiseAttributeGetter(aCx
, aResultPromise
,
176 AsyncAttribute::PrinterInfo
,
177 &nsPrinterBase::CreatePrinterInfo
);
180 void nsPrinterBase::QueryMarginsForPaper(Promise
& aPromise
,
181 const nsString
& aPaperId
) {
182 return SpawnPrintBackgroundTask(*this, aPromise
, "MarginsForPaper"_ns
,
183 &nsPrinterBase::GetMarginsForPaper
, aPaperId
);
186 NS_IMPL_CYCLE_COLLECTION(nsPrinterBase
, mAsyncAttributePromises
)
188 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase
)
189 NS_INTERFACE_MAP_ENTRY(nsIPrinter
)
190 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPrinter
)
193 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterBase
)
194 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterBase
)
196 nsPrinterBase::nsPrinterBase(const CommonPaperInfoArray
* aPaperInfoArray
)
197 : mCommonPaperInfo(aPaperInfoArray
) {
198 MOZ_DIAGNOSTIC_ASSERT(aPaperInfoArray
, "Localized paper info was null");
200 nsPrinterBase::~nsPrinterBase() = default;
202 const PaperInfo
* nsPrinterBase::FindCommonPaperSize(
203 const gfx::SizeDouble
& aSize
) const {
204 for (const PaperInfo
& paper
: *mCommonPaperInfo
) {
205 if (std::abs(paper
.mSize
.width
- aSize
.width
) <= kPaperSizePointsEpsilon
&&
206 std::abs(paper
.mSize
.height
- aSize
.height
) <=
207 kPaperSizePointsEpsilon
) {