summaryrefslogtreecommitdiffstats
path: root/widget/nsPrinterCUPS.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--widget/nsPrinterCUPS.h181
1 files changed, 181 insertions, 0 deletions
diff --git a/widget/nsPrinterCUPS.h b/widget/nsPrinterCUPS.h
new file mode 100644
index 0000000000..3ecf1cb982
--- /dev/null
+++ b/widget/nsPrinterCUPS.h
@@ -0,0 +1,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___ */