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