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 "nsPrinterListBase.h"
7 #include "PrintBackgroundTask.h"
8 #include "mozilla/ErrorResult.h"
9 #include "mozilla/intl/Localization.h"
10 #include "xpcpublic.h"
12 using mozilla::ErrorResult
;
13 using mozilla::intl::Localization
;
14 using PrinterInfo
= nsPrinterListBase::PrinterInfo
;
16 nsPrinterListBase::nsPrinterListBase() = default;
17 nsPrinterListBase::~nsPrinterListBase() = default;
19 NS_IMPL_CYCLE_COLLECTION(nsPrinterListBase
, mPrintersPromise
)
21 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterListBase
)
22 NS_INTERFACE_MAP_ENTRY(nsIPrinterList
)
23 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPrinterList
)
26 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterListBase
)
27 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterListBase
)
32 void ResolveOrReject(dom::Promise
& aPromise
, nsPrinterListBase
& aList
,
33 const nsTArray
<PrinterInfo
>& aInfo
) {
34 nsTArray
<RefPtr
<nsIPrinter
>> printers
;
35 printers
.SetCapacity(aInfo
.Length());
36 for (auto& info
: aInfo
) {
37 printers
.AppendElement(aList
.CreatePrinter(info
));
39 aPromise
.MaybeResolve(printers
);
43 void ResolveOrReject(dom::Promise
& aPromise
, nsPrinterListBase
& aList
,
44 const Maybe
<PrinterInfo
>& aInfo
) {
46 aPromise
.MaybeResolve(aList
.CreatePrinter(aInfo
.value()));
48 aPromise
.MaybeRejectWithNotFoundError("Printer not found");
52 } // namespace mozilla
54 NS_IMETHODIMP
nsPrinterListBase::GetPrinters(JSContext
* aCx
,
56 EnsureCommonPaperInfo(aCx
);
57 return mozilla::AsyncPromiseAttributeGetter(*this, mPrintersPromise
, aCx
,
58 aResult
, "Printers"_ns
,
59 &nsPrinterListBase::Printers
);
62 NS_IMETHODIMP
nsPrinterListBase::GetPrinterByName(const nsAString
& aPrinterName
,
65 EnsureCommonPaperInfo(aCx
);
66 return PrintBackgroundTaskPromise(*this, aCx
, aResult
, "PrinterByName"_ns
,
67 &nsPrinterListBase::PrinterByName
,
68 nsString
{aPrinterName
});
71 NS_IMETHODIMP
nsPrinterListBase::GetPrinterBySystemName(
72 const nsAString
& aPrinterName
, JSContext
* aCx
, Promise
** aResult
) {
73 EnsureCommonPaperInfo(aCx
);
74 return PrintBackgroundTaskPromise(
75 *this, aCx
, aResult
, "PrinterBySystemName"_ns
,
76 &nsPrinterListBase::PrinterBySystemName
, nsString
{aPrinterName
});
79 NS_IMETHODIMP
nsPrinterListBase::GetNamedOrDefaultPrinter(
80 const nsAString
& aPrinterName
, JSContext
* aCx
, Promise
** aResult
) {
81 EnsureCommonPaperInfo(aCx
);
82 return PrintBackgroundTaskPromise(
83 *this, aCx
, aResult
, "NamedOrDefaultPrinter"_ns
,
84 &nsPrinterListBase::NamedOrDefaultPrinter
, nsString
{aPrinterName
});
87 Maybe
<PrinterInfo
> nsPrinterListBase::NamedOrDefaultPrinter(
88 nsString aName
) const {
89 if (Maybe
<PrinterInfo
> value
= PrinterByName(std::move(aName
))) {
93 // Since the name had to be passed by-value, we can re-use it to fetch the
94 // default printer name, potentially avoiding an extra string allocation.
95 if (NS_SUCCEEDED(SystemDefaultPrinterName(aName
))) {
96 return PrinterByName(std::move(aName
));
102 NS_IMETHODIMP
nsPrinterListBase::GetFallbackPaperList(JSContext
* aCx
,
105 nsCOMPtr
<nsIGlobalObject
> global
= xpc::CurrentNativeGlobal(aCx
);
106 RefPtr
<Promise
> promise
= Promise::Create(global
, rv
);
107 if (MOZ_UNLIKELY(rv
.Failed())) {
109 return rv
.StealNSResult();
112 EnsureCommonPaperInfo(aCx
);
113 nsTArray
<RefPtr
<nsPaper
>> papers
;
114 papers
.SetCapacity(nsPaper::kNumCommonPaperSizes
);
115 for (const auto& info
: *mCommonPaperInfo
) {
116 papers
.AppendElement(MakeRefPtr
<nsPaper
>(info
));
119 promise
->MaybeResolve(papers
);
120 promise
.forget(aResult
);
124 void nsPrinterListBase::EnsureCommonPaperInfo(JSContext
* aCx
) {
125 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
126 if (mCommonPaperInfo
) {
129 RefPtr
<CommonPaperInfoArray
> localizedPaperInfo
=
130 MakeRefPtr
<CommonPaperInfoArray
>();
131 CommonPaperInfoArray
& paperArray
= *localizedPaperInfo
;
132 // Apply localization to the names while constructing the PaperInfo, if
133 // available (otherwise leave them as the internal keys, which are at least
134 // somewhat recognizable).
135 IgnoredErrorResult rv
;
136 nsCOMPtr
<nsIGlobalObject
> global
= xpc::CurrentNativeGlobal(aCx
);
137 RefPtr
<Localization
> l10n
= Localization::Create(global
, true, {});
138 l10n
->AddResourceId(u
"toolkit/printing/printUI.ftl"_ns
);
140 for (auto i
: IntegerRange(nsPaper::kNumCommonPaperSizes
)) {
141 const CommonPaperSize
& size
= nsPaper::kCommonPaperSizes
[i
];
142 PaperInfo
& info
= paperArray
[i
];
144 nsAutoCString key
{"printui-paper-"};
145 key
.Append(size
.mLocalizableNameKey
);
147 l10n
->FormatValueSync(aCx
, key
, {}, name
, rv
);
149 // Fill out the info with our PWG size and the localized name.
150 info
.mId
= size
.mPWGName
;
152 (rv
.Failed() || name
.IsEmpty())
153 ? static_cast<const nsCString
&>(size
.mLocalizableNameKey
)
156 info
.mSize
= size
.mSize
;
157 info
.mUnwriteableMargin
= Some(MarginDouble
{});
159 mCommonPaperInfo
= std::move(localizedPaperInfo
);