forked from mirrors/gecko-dev
Bug 1826872 Part 2 - Move CUPS printer dest into CUPSPrinterInfo for nsPrinterCUPS r=dholbert
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
This commit is contained in:
parent
60b538473f
commit
02b2360a11
2 changed files with 75 additions and 47 deletions
|
|
@ -87,9 +87,8 @@ nsPrinterCUPS::~nsPrinterCUPS() {
|
||||||
if (lock->mPrinterInfo) {
|
if (lock->mPrinterInfo) {
|
||||||
mShim.cupsFreeDestInfo(lock->mPrinterInfo);
|
mShim.cupsFreeDestInfo(lock->mPrinterInfo);
|
||||||
}
|
}
|
||||||
if (mPrinter) {
|
if (lock->mPrinter) {
|
||||||
mShim.cupsFreeDests(1, mPrinter);
|
mShim.cupsFreeDests(1, lock->mPrinter);
|
||||||
mPrinter = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,14 +100,16 @@ nsPrinterCUPS::GetName(nsAString& aName) {
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsPrinterCUPS::GetSystemName(nsAString& aName) {
|
nsPrinterCUPS::GetSystemName(nsAString& aName) {
|
||||||
CopyUTF8toUTF16(MakeStringSpan(mPrinter->name), aName);
|
PrinterInfoLock lock = mPrinterInfoMutex.Lock();
|
||||||
|
CopyUTF8toUTF16(MakeStringSpan(lock->mPrinter->name), aName);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsPrinterCUPS::GetPrinterName(nsAString& aName) const {
|
void nsPrinterCUPS::GetPrinterName(nsAString& aName) const {
|
||||||
if (mDisplayName.IsEmpty()) {
|
if (mDisplayName.IsEmpty()) {
|
||||||
aName.Truncate();
|
aName.Truncate();
|
||||||
CopyUTF8toUTF16(MakeStringSpan(mPrinter->name), aName);
|
PrinterInfoLock lock = mPrinterInfoMutex.Lock();
|
||||||
|
CopyUTF8toUTF16(MakeStringSpan(lock->mPrinter->name), aName);
|
||||||
} else {
|
} else {
|
||||||
aName = mDisplayName;
|
aName = mDisplayName;
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +123,8 @@ const char* nsPrinterCUPS::LocalizeMediaName(http_t& aConnection,
|
||||||
return aMedia.media;
|
return aMedia.media;
|
||||||
}
|
}
|
||||||
PrinterInfoLock lock = TryEnsurePrinterInfo();
|
PrinterInfoLock lock = TryEnsurePrinterInfo();
|
||||||
return mShim.cupsLocalizeDestMedia(&aConnection, mPrinter, lock->mPrinterInfo,
|
return mShim.cupsLocalizeDestMedia(&aConnection, lock->mPrinter,
|
||||||
|
lock->mPrinterInfo,
|
||||||
CUPS_MEDIA_FLAGS_DEFAULT, &aMedia);
|
CUPS_MEDIA_FLAGS_DEFAULT, &aMedia);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +153,8 @@ bool nsPrinterCUPS::SupportsColor() const {
|
||||||
|
|
||||||
bool nsPrinterCUPS::SupportsCollation() const {
|
bool nsPrinterCUPS::SupportsCollation() const {
|
||||||
// We can't depend on cupsGetIntegerOption existing.
|
// We can't depend on cupsGetIntegerOption existing.
|
||||||
const char* const value = FindCUPSOption("printer-type");
|
PrinterInfoLock lock = mPrinterInfoMutex.Lock();
|
||||||
|
const char* const value = FindCUPSOption(lock, "printer-type");
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +171,7 @@ nsPrinterBase::PrinterInfo nsPrinterCUPS::CreatePrinterInfo() const {
|
||||||
|
|
||||||
bool nsPrinterCUPS::Supports(const char* aOption, const char* aValue) const {
|
bool nsPrinterCUPS::Supports(const char* aOption, const char* aValue) const {
|
||||||
PrinterInfoLock lock = TryEnsurePrinterInfo();
|
PrinterInfoLock lock = TryEnsurePrinterInfo();
|
||||||
return mShim.cupsCheckDestSupported(CUPS_HTTP_DEFAULT, mPrinter,
|
return mShim.cupsCheckDestSupported(CUPS_HTTP_DEFAULT, lock->mPrinter,
|
||||||
lock->mPrinterInfo, aOption, aValue);
|
lock->mPrinterInfo, aOption, aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -235,13 +238,13 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings(
|
||||||
// and the IPP attribute appears to return more accurate defaults on Linux.
|
// and the IPP attribute appears to return more accurate defaults on Linux.
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
hasDefaultMedia = mShim.cupsGetDestMediaDefault(
|
hasDefaultMedia = mShim.cupsGetDestMediaDefault(
|
||||||
CUPS_HTTP_DEFAULT, mPrinter, lock->mPrinterInfo, CUPS_MEDIA_FLAGS_DEFAULT,
|
CUPS_HTTP_DEFAULT, lock->mPrinter, lock->mPrinterInfo,
|
||||||
&media);
|
CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
ipp_attribute_t* defaultMediaIPP =
|
ipp_attribute_t* defaultMediaIPP =
|
||||||
mShim.cupsFindDestDefault
|
mShim.cupsFindDestDefault
|
||||||
? mShim.cupsFindDestDefault(CUPS_HTTP_DEFAULT, mPrinter,
|
? mShim.cupsFindDestDefault(CUPS_HTTP_DEFAULT, lock->mPrinter,
|
||||||
lock->mPrinterInfo, "media")
|
lock->mPrinterInfo, "media")
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
|
@ -251,7 +254,7 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings(
|
||||||
|
|
||||||
hasDefaultMedia = defaultMediaName &&
|
hasDefaultMedia = defaultMediaName &&
|
||||||
mShim.cupsGetDestMediaByName(
|
mShim.cupsGetDestMediaByName(
|
||||||
CUPS_HTTP_DEFAULT, mPrinter, lock->mPrinterInfo,
|
CUPS_HTTP_DEFAULT, lock->mPrinter, lock->mPrinterInfo,
|
||||||
defaultMediaName, CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
defaultMediaName, CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -277,7 +280,7 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
http_t* const connection = aConnection.GetConnection(mPrinter);
|
http_t* const connection = aConnection.GetConnection(lock->mPrinter);
|
||||||
// XXX Do we actually have the guarantee that this is utf-8?
|
// XXX Do we actually have the guarantee that this is utf-8?
|
||||||
NS_ConvertUTF8toUTF16 localizedName{
|
NS_ConvertUTF8toUTF16 localizedName{
|
||||||
connection ? LocalizeMediaName(*connection, media) : ""};
|
connection ? LocalizeMediaName(*connection, media) : ""};
|
||||||
|
|
@ -291,8 +294,9 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings(
|
||||||
|
|
||||||
nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList(
|
nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList(
|
||||||
Connection& aConnection) const {
|
Connection& aConnection) const {
|
||||||
http_t* const connection = aConnection.GetConnection(mPrinter);
|
PrinterInfoLock lock = mPrinterInfoMutex.Lock();
|
||||||
PrinterInfoLock lock = TryEnsurePrinterInfo(connection);
|
http_t* const connection = aConnection.GetConnection(lock->mPrinter);
|
||||||
|
TryEnsurePrinterInfo(lock, connection);
|
||||||
|
|
||||||
if (!lock->mPrinterInfo) {
|
if (!lock->mPrinterInfo) {
|
||||||
return {};
|
return {};
|
||||||
|
|
@ -300,8 +304,8 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList(
|
||||||
|
|
||||||
const int paperCount = mShim.cupsGetDestMediaCount
|
const int paperCount = mShim.cupsGetDestMediaCount
|
||||||
? mShim.cupsGetDestMediaCount(
|
? mShim.cupsGetDestMediaCount(
|
||||||
connection, mPrinter, lock->mPrinterInfo,
|
connection, lock->mPrinter,
|
||||||
CUPS_MEDIA_FLAGS_DEFAULT)
|
lock->mPrinterInfo, CUPS_MEDIA_FLAGS_DEFAULT)
|
||||||
: 0;
|
: 0;
|
||||||
nsTArray<PaperInfo> paperList;
|
nsTArray<PaperInfo> paperList;
|
||||||
nsTHashtable<nsCharPtrHashKey> paperSet(std::max(paperCount, 0));
|
nsTHashtable<nsCharPtrHashKey> paperSet(std::max(paperCount, 0));
|
||||||
|
|
@ -309,9 +313,9 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList(
|
||||||
paperList.SetCapacity(paperCount);
|
paperList.SetCapacity(paperCount);
|
||||||
for (int i = 0; i < paperCount; ++i) {
|
for (int i = 0; i < paperCount; ++i) {
|
||||||
cups_size_t media;
|
cups_size_t media;
|
||||||
const int getInfoSucceeded =
|
const int getInfoSucceeded = mShim.cupsGetDestMediaByIndex(
|
||||||
mShim.cupsGetDestMediaByIndex(connection, mPrinter, lock->mPrinterInfo,
|
connection, lock->mPrinter, lock->mPrinterInfo, i,
|
||||||
i, CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||||
|
|
||||||
if (!getInfoSucceeded || !paperSet.EnsureInserted(media.media)) {
|
if (!getInfoSucceeded || !paperSet.EnsureInserted(media.media)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -334,22 +338,21 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList(
|
||||||
return paperList;
|
return paperList;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPrinterCUPS::PrinterInfoLock nsPrinterCUPS::TryEnsurePrinterInfo(
|
void nsPrinterCUPS::TryEnsurePrinterInfo(PrinterInfoLock& aLock,
|
||||||
http_t* const aConnection) const {
|
http_t* const aConnection) const {
|
||||||
PrinterInfoLock lock = mPrinterInfoMutex.Lock();
|
if (aLock->mPrinterInfo ||
|
||||||
if (lock->mPrinterInfo ||
|
(aConnection == CUPS_HTTP_DEFAULT ? aLock->mTriedInitWithDefault
|
||||||
(aConnection == CUPS_HTTP_DEFAULT ? lock->mTriedInitWithDefault
|
: aLock->mTriedInitWithConnection)) {
|
||||||
: lock->mTriedInitWithConnection)) {
|
return;
|
||||||
return lock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aConnection == CUPS_HTTP_DEFAULT) {
|
if (aConnection == CUPS_HTTP_DEFAULT) {
|
||||||
lock->mTriedInitWithDefault = true;
|
aLock->mTriedInitWithDefault = true;
|
||||||
} else {
|
} else {
|
||||||
lock->mTriedInitWithConnection = true;
|
aLock->mTriedInitWithConnection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(mPrinter);
|
MOZ_ASSERT(aLock->mPrinter);
|
||||||
|
|
||||||
// httpGetAddress was only added in CUPS 2.0, and some systems still use
|
// httpGetAddress was only added in CUPS 2.0, and some systems still use
|
||||||
// CUPS 1.7.
|
// CUPS 1.7.
|
||||||
|
|
@ -427,9 +430,10 @@ nsPrinterCUPS::PrinterInfoLock nsPrinterCUPS::TryEnsurePrinterInfo(
|
||||||
// Match the conditional at
|
// Match the conditional at
|
||||||
// https://github.com/apple/cups/blob/23c45db76a8520fd6c3b1d9164dbe312f1ab1481/cups/dest.c#L1144
|
// https://github.com/apple/cups/blob/23c45db76a8520fd6c3b1d9164dbe312f1ab1481/cups/dest.c#L1144
|
||||||
// but if device-uri is null do not call into CUPS.
|
// but if device-uri is null do not call into CUPS.
|
||||||
if ((cupsDestDeviceFlag || !FindCUPSOption("printer-uri-supported")) &&
|
if ((cupsDestDeviceFlag ||
|
||||||
!FindCUPSOption("device-uri")) {
|
!FindCUPSOption(aLock, "printer-uri-supported")) &&
|
||||||
return lock;
|
!FindCUPSOption(aLock, "device-uri")) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -438,13 +442,12 @@ nsPrinterCUPS::PrinterInfoLock nsPrinterCUPS::TryEnsurePrinterInfo(
|
||||||
// All CUPS calls that take the printer info do null-checks internally, so we
|
// All CUPS calls that take the printer info do null-checks internally, so we
|
||||||
// can fetch this info and only worry about the result of the later CUPS
|
// can fetch this info and only worry about the result of the later CUPS
|
||||||
// functions.
|
// functions.
|
||||||
lock->mPrinterInfo = mShim.cupsCopyDestInfo(aConnection, mPrinter);
|
aLock->mPrinterInfo = mShim.cupsCopyDestInfo(aConnection, aLock->mPrinter);
|
||||||
|
|
||||||
// Even if we failed to fetch printer info, it is still possible we can talk
|
// Even if we failed to fetch printer info, it is still possible we can talk
|
||||||
// to the print server and get its CUPS version.
|
// to the print server and get its CUPS version.
|
||||||
FetchCUPSVersionForPrinter(mShim, mPrinter, lock->mCUPSMajor,
|
FetchCUPSVersionForPrinter(mShim, aLock->mPrinter, aLock->mCUPSMajor,
|
||||||
lock->mCUPSMinor, lock->mCUPSPatch);
|
aLock->mCUPSMinor, aLock->mCUPSPatch);
|
||||||
return lock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsPrinterCUPS::ForEachExtraMonochromeSetting(
|
void nsPrinterCUPS::ForEachExtraMonochromeSetting(
|
||||||
|
|
|
||||||
|
|
@ -42,18 +42,17 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
||||||
: nsPrinterBase(aArray),
|
: nsPrinterBase(aArray),
|
||||||
mShim(aShim),
|
mShim(aShim),
|
||||||
mDisplayName(std::move(aDisplayName)),
|
mDisplayName(std::move(aDisplayName)),
|
||||||
mPrinter(aPrinter),
|
mPrinterInfoMutex(CUPSPrinterInfo{aPrinter},
|
||||||
mPrinterInfoMutex("nsPrinterCUPS::mPrinterInfoMutex") {}
|
"nsPrinterCUPS::mPrinterInfoMutex") {}
|
||||||
|
|
||||||
static void ForEachExtraMonochromeSetting(
|
static void ForEachExtraMonochromeSetting(
|
||||||
mozilla::FunctionRef<void(const nsACString&, const nsACString&)>);
|
mozilla::FunctionRef<void(const nsACString&, const nsACString&)>);
|
||||||
|
|
||||||
inline const char* FindCUPSOption(const char* name) const {
|
|
||||||
return mShim.cupsGetOption(name, mPrinter->num_options, mPrinter->options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CUPSPrinterInfo {
|
struct CUPSPrinterInfo {
|
||||||
|
explicit constexpr CUPSPrinterInfo(cups_dest_t* aPrinter)
|
||||||
|
: mPrinter(aPrinter) {}
|
||||||
|
cups_dest_t* mPrinter;
|
||||||
cups_dinfo_t* mPrinterInfo = nullptr;
|
cups_dinfo_t* mPrinterInfo = nullptr;
|
||||||
uint64_t mCUPSMajor = 0;
|
uint64_t mCUPSMajor = 0;
|
||||||
uint64_t mCUPSMinor = 0;
|
uint64_t mCUPSMinor = 0;
|
||||||
|
|
@ -63,9 +62,17 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
||||||
bool mTriedInitWithDefault = false;
|
bool mTriedInitWithDefault = false;
|
||||||
// Whether we have attempted to fetch mPrinterInfo with a connection.
|
// Whether we have attempted to fetch mPrinterInfo with a connection.
|
||||||
bool mTriedInitWithConnection = false;
|
bool mTriedInitWithConnection = false;
|
||||||
CUPSPrinterInfo() = default;
|
CUPSPrinterInfo() = delete;
|
||||||
CUPSPrinterInfo(const CUPSPrinterInfo&) = delete;
|
CUPSPrinterInfo(const CUPSPrinterInfo&) = delete;
|
||||||
CUPSPrinterInfo(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 =
|
using PrinterInfoMutex =
|
||||||
|
|
@ -91,6 +98,11 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
||||||
bool IsCUPSVersionAtLeast(uint64_t aCUPSMajor, uint64_t aCUPSMinor,
|
bool IsCUPSVersionAtLeast(uint64_t aCUPSMajor, uint64_t aCUPSMinor,
|
||||||
uint64_t aCUPSPatch) const;
|
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 {
|
class Connection {
|
||||||
public:
|
public:
|
||||||
http_t* GetConnection(cups_dest_t* aDest);
|
http_t* GetConnection(cups_dest_t* aDest);
|
||||||
|
|
@ -114,11 +126,24 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
||||||
* on older versions of Ubuntu (18 and below).
|
* on older versions of Ubuntu (18 and below).
|
||||||
*/
|
*/
|
||||||
PrinterInfoLock TryEnsurePrinterInfo(
|
PrinterInfoLock TryEnsurePrinterInfo(
|
||||||
http_t* const aConnection = CUPS_HTTP_DEFAULT) const;
|
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;
|
const nsCUPSShim& mShim;
|
||||||
nsString mDisplayName;
|
nsString mDisplayName;
|
||||||
cups_dest_t* mPrinter;
|
|
||||||
mutable PrinterInfoMutex mPrinterInfoMutex;
|
mutable PrinterInfoMutex mPrinterInfoMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue