1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 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 #ifndef nsPrinterCUPS_h___
7 #define nsPrinterCUPS_h___
9 #include "nsPrinterBase.h"
10 #include "nsPrintSettingsImpl.h"
11 #include "nsCUPSShim.h"
14 #include "mozilla/DataMutex.h"
15 #include "mozilla/FunctionRef.h"
16 #include "mozilla/RecursiveMutex.h"
19 * @brief Interface to help implementing nsIPrinter using a CUPS printer.
21 class nsPrinterCUPS final
: public nsPrinterBase
{
23 NS_IMETHOD
GetName(nsAString
& aName
) override
;
24 NS_IMETHOD
GetSystemName(nsAString
& aName
) override
;
25 bool SupportsDuplex() const final
;
26 bool SupportsColor() const final
;
27 bool SupportsMonochrome() const final
;
28 bool SupportsCollation() const final
;
29 PrinterInfo
CreatePrinterInfo() const final
;
30 MarginDouble
GetMarginsForPaper(nsString aPaperId
) const final
{
31 MOZ_ASSERT_UNREACHABLE(
32 "The CUPS API requires us to always get the margin when fetching the "
33 "paper list so there should be no need to query it separately");
37 nsPrinterCUPS() = delete;
39 nsPrinterCUPS(const mozilla::CommonPaperInfoArray
* aArray
,
40 const nsCUPSShim
& aShim
, nsString aDisplayName
,
41 cups_dest_t
* aPrinter
)
42 : nsPrinterBase(aArray
),
44 mDisplayName(std::move(aDisplayName
)),
45 mPrinterInfoMutex(CUPSPrinterInfo
{aPrinter
},
46 "nsPrinterCUPS::mPrinterInfoMutex") {}
48 static void ForEachExtraMonochromeSetting(
49 mozilla::FunctionRef
<void(const nsACString
&, const nsACString
&)>);
52 struct CUPSPrinterInfo
{
53 explicit constexpr CUPSPrinterInfo(cups_dest_t
* aPrinter
)
54 : mPrinter(aPrinter
) {}
55 cups_dest_t
* mPrinter
;
56 cups_dinfo_t
* mPrinterInfo
= nullptr;
57 uint64_t mCUPSMajor
= 0;
58 uint64_t mCUPSMinor
= 0;
59 uint64_t mCUPSPatch
= 0;
61 // Whether we have attempted to fetch mPrinterInfo with CUPS_HTTP_DEFAULT.
62 bool mTriedInitWithDefault
= false;
63 // Whether we have attempted to fetch mPrinterInfo with a connection.
64 bool mTriedInitWithConnection
= false;
65 CUPSPrinterInfo() = delete;
66 CUPSPrinterInfo(const CUPSPrinterInfo
&) = delete;
67 CUPSPrinterInfo(CUPSPrinterInfo
&& aOther
)
68 : mPrinter(aOther
.mPrinter
),
69 mPrinterInfo(aOther
.mPrinterInfo
),
70 mCUPSMajor(aOther
.mCUPSMajor
),
71 mCUPSMinor(aOther
.mCUPSMinor
),
72 mCUPSPatch(aOther
.mCUPSPatch
) {
73 aOther
.mPrinter
= nullptr;
74 aOther
.mPrinterInfo
= nullptr;
78 using PrinterInfoMutex
=
79 mozilla::DataMutexBase
<CUPSPrinterInfo
, mozilla::RecursiveMutex
>;
81 using PrinterInfoLock
= PrinterInfoMutex::AutoLock
;
86 * Retrieves the localized name for a given media (paper).
87 * Returns nullptr if the name cannot be localized.
89 const char* LocalizeMediaName(http_t
& aConnection
, cups_size_t
& aMedia
) const;
91 void GetPrinterName(nsAString
& aName
) const;
93 // Little util for getting support flags using the direct CUPS names.
94 bool Supports(const char* aOption
, const char* aValue
) const;
96 // Returns support value if CUPS meets the minimum version, otherwise returns
98 bool IsCUPSVersionAtLeast(uint64_t aCUPSMajor
, uint64_t aCUPSMinor
,
99 uint64_t aCUPSPatch
) const;
101 const char* FindCUPSOption(PrinterInfoLock
& aLock
, const char* name
) const {
102 const cups_dest_t
* const printer
= aLock
->mPrinter
;
103 return mShim
.cupsGetOption(name
, printer
->num_options
, printer
->options
);
108 http_t
* GetConnection(cups_dest_t
* aDest
);
110 inline explicit Connection(const nsCUPSShim
& aShim
) : mShim(aShim
) {}
111 Connection() = delete;
115 const nsCUPSShim
& mShim
;
116 http_t
* mConnection
= CUPS_HTTP_DEFAULT
;
117 bool mWasInited
= false;
120 PrintSettingsInitializer
DefaultSettings(Connection
& aConnection
) const;
121 nsTArray
<mozilla::PaperInfo
> PaperList(Connection
& aConnection
) const;
123 * Attempts to populate the CUPSPrinterInfo object.
124 * This usually works with the CUPS default connection,
125 * but has been known to require an established connection
126 * on older versions of Ubuntu (18 and below).
128 PrinterInfoLock
TryEnsurePrinterInfo(
129 http_t
* const aConnection
= CUPS_HTTP_DEFAULT
) const {
130 PrinterInfoLock lock
= mPrinterInfoMutex
.Lock();
131 TryEnsurePrinterInfo(lock
, aConnection
);
136 * TryEnsurePrinterInfo that uses a caller-provided PrinterInfoLock.
138 * This can be used to avoid unnecessarily redundant locking of
139 * mPrinterInfoLock when getting a connection through
140 * Connection::GetConnection and then passing that into TryEnsurePrinterInfo.
142 void TryEnsurePrinterInfo(PrinterInfoLock
& aLock
,
143 http_t
* const aConnection
) const;
145 const nsCUPSShim
& mShim
;
146 nsString mDisplayName
;
147 mutable PrinterInfoMutex mPrinterInfoMutex
;
150 // There's no standard setting in Core Printing for monochrome. Or rather,
151 // there is (PMSetColorMode) but it does nothing. Similarly, the relevant gtk
152 // setting only works on Windows, yay.
154 // So on CUPS the right setting to use depends on the print driver. So we set /
155 // look for a variety of driver-specific keys that are known to work across
158 // We set all the known settings, because the alternative to that is parsing ppd
159 // files from the printer and find the relevant known choices that can apply,
160 // and that is a lot more complex, similarly sketchy (requires the same amount
161 // of driver-specific knowledge), and requires using deprecated CUPS APIs.
162 #define CUPS_EACH_MONOCHROME_PRINTER_SETTING(macro_) \
163 macro_("ColorModel", "Gray") /* Generic */ \
164 macro_("BRMonoColor", "Mono") /* Brother */ \
165 macro_("BRPrintQuality", "Black") /* Brother */ \
166 macro_("CNIJGrayScale", "1") /* Canon */ \
167 macro_("CNGrayscale", "True") /* Canon */ \
168 macro_("INK", "MONO") /* Epson */ \
169 macro_("HPColorMode", "GrayscalePrint") /* HP */ \
170 macro_("ColorMode", "Mono") /* Samsung */ \
171 macro_("PrintoutMode", "Normal.Gray") /* Foomatic */ \
172 macro_("ProcessColorModel", "Mono") /* Samsung */ \
173 macro_("ARCMode", "CMBW") /* Sharp */ \
174 macro_("XRXColor", "BW") /* Xerox */ \
175 macro_("XROutputColor", "PrintAsGrayscale") /* Xerox, bug 1676191#c32 */ \
176 macro_("SelectColor", "Grayscale") /* Konica Minolta */ \
177 macro_("OKControl", "Gray") /* Oki */ \
178 macro_("BLW", "TrueM") /* Lexmark */ \
179 macro_("EPRendering", "None") /* Epson */
181 #endif /* nsPrinterCUPS_h___ */