mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
02b2360a11
This puts all CUPS data into one structure, refactors the locking of this data, and and simplifies logic for determining the connection to use in TryEnsurePrinterInfo. Differential Revision: https://phabricator.services.mozilla.com/D174925
182 lines
7.2 KiB
C++
182 lines
7.2 KiB
C++
/* -*- 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___ */
|