Bug 1662946 - Fix Paper List Retrieval For Older Versions of Ubuntu r=emilio

- Rename EnsurePrinterInfo to TryEnsurePrinterInfo to reflect the fact that it can fail to populate the printer info.
- Add argument to TryEnsurePrinterInfo to accept a connection other than the default.
- Allow TryEnsurePrinterInfo to try once with the default connection and once with an established connection.
- Use an established connection to retrieve the paper list information.

Differential Revision: https://phabricator.services.mozilla.com/D91193
This commit is contained in:
Erik Nordin 2020-09-24 22:01:43 +00:00
parent 2d346ebd7e
commit 572414569d
2 changed files with 56 additions and 29 deletions

View File

@ -91,7 +91,7 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings() const {
nsString printerName; nsString printerName;
GetPrinterName(printerName); GetPrinterName(printerName);
auto printerInfoLock = mPrinterInfoMutex.Lock(); auto printerInfoLock = mPrinterInfoMutex.Lock();
EnsurePrinterInfo(*printerInfoLock); TryEnsurePrinterInfo(*printerInfoLock);
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo; cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
cups_size_t media; cups_size_t media;
@ -171,7 +171,7 @@ const char* nsPrinterCUPS::LocalizeMediaName(http_t& aConnection,
// The returned string is owned by mPrinterInfo. // The returned string is owned by mPrinterInfo.
// https://www.cups.org/doc/cupspm.html#cupsLocalizeDestMedia // https://www.cups.org/doc/cupspm.html#cupsLocalizeDestMedia
auto printerInfoLock = mPrinterInfoMutex.Lock(); auto printerInfoLock = mPrinterInfoMutex.Lock();
EnsurePrinterInfo(*printerInfoLock); TryEnsurePrinterInfo(*printerInfoLock);
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo; cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
return mShim.cupsLocalizeDestMedia(&aConnection, mPrinter, printerInfo, return mShim.cupsLocalizeDestMedia(&aConnection, mPrinter, printerInfo,
CUPS_MEDIA_FLAGS_DEFAULT, &aMedia); CUPS_MEDIA_FLAGS_DEFAULT, &aMedia);
@ -219,7 +219,7 @@ bool nsPrinterCUPS::SupportsCollation() const {
bool nsPrinterCUPS::Supports(const char* aOption, const char* aValue) const { bool nsPrinterCUPS::Supports(const char* aOption, const char* aValue) const {
auto printerInfoLock = mPrinterInfoMutex.Lock(); auto printerInfoLock = mPrinterInfoMutex.Lock();
EnsurePrinterInfo(*printerInfoLock); TryEnsurePrinterInfo(*printerInfoLock);
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo; cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
return mShim.cupsCheckDestSupported(CUPS_HTTP_DEFAULT, mPrinter, printerInfo, return mShim.cupsCheckDestSupported(CUPS_HTTP_DEFAULT, mPrinter, printerInfo,
aOption, aValue); aOption, aValue);
@ -229,7 +229,7 @@ bool nsPrinterCUPS::IsCUPSVersionAtLeast(uint64_t aCUPSMajor,
uint64_t aCUPSMinor, uint64_t aCUPSMinor,
uint64_t aCUPSPatch) const { uint64_t aCUPSPatch) const {
auto printerInfoLock = mPrinterInfoMutex.Lock(); auto printerInfoLock = mPrinterInfoMutex.Lock();
EnsurePrinterInfo(*printerInfoLock); TryEnsurePrinterInfo(*printerInfoLock);
// Compare major version. // Compare major version.
if (printerInfoLock->mCUPSMajor > aCUPSMajor) { if (printerInfoLock->mCUPSMajor > aCUPSMajor) {
return true; return true;
@ -251,16 +251,6 @@ bool nsPrinterCUPS::IsCUPSVersionAtLeast(uint64_t aCUPSMajor,
} }
nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const { nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
auto printerInfoLock = mPrinterInfoMutex.Lock();
EnsurePrinterInfo(*printerInfoLock);
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
if (!printerInfo) {
return {};
}
const int paperCount = mShim.cupsGetDestMediaCount(
CUPS_HTTP_DEFAULT, mPrinter, printerInfo, CUPS_MEDIA_FLAGS_DEFAULT);
// blocking call // blocking call
http_t* connection = mShim.cupsConnectDest(mPrinter, CUPS_DEST_FLAGS_NONE, http_t* connection = mShim.cupsConnectDest(mPrinter, CUPS_DEST_FLAGS_NONE,
/* timeout(ms) */ 5000, /* timeout(ms) */ 5000,
@ -271,41 +261,68 @@ nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
/* user_data */ nullptr); /* user_data */ nullptr);
if (!connection) { if (!connection) {
connection = CUPS_HTTP_DEFAULT;
}
auto printerInfoLock = mPrinterInfoMutex.Lock();
TryEnsurePrinterInfo(*printerInfoLock, connection);
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
if (!printerInfo) {
if (connection) {
mShim.httpClose(connection);
}
return {}; return {};
} }
const int paperCount = mShim.cupsGetDestMediaCount(
connection, mPrinter, printerInfo, CUPS_MEDIA_FLAGS_DEFAULT);
nsTArray<PaperInfo> paperList; nsTArray<PaperInfo> paperList;
for (int i = 0; i < paperCount; ++i) { for (int i = 0; i < paperCount; ++i) {
cups_size_t media; cups_size_t media;
int getInfoSucceded = int getInfoSucceeded = mShim.cupsGetDestMediaByIndex(
mShim.cupsGetDestMediaByIndex(CUPS_HTTP_DEFAULT, mPrinter, printerInfo, connection, mPrinter, printerInfo, i, CUPS_MEDIA_FLAGS_DEFAULT, &media);
i, CUPS_MEDIA_FLAGS_DEFAULT, &media);
if (!getInfoSucceded) { if (!getInfoSucceeded) {
continue; continue;
} }
paperList.AppendElement( const char* mediaName =
MakePaperInfo(LocalizeMediaName(*connection, media), media)); connection ? LocalizeMediaName(*connection, media) : media.media;
paperList.AppendElement(MakePaperInfo(mediaName, media));
}
if (connection) {
mShim.httpClose(connection);
} }
mShim.httpClose(connection);
return paperList; return paperList;
} }
void nsPrinterCUPS::EnsurePrinterInfo( void nsPrinterCUPS::TryEnsurePrinterInfo(CUPSPrinterInfo& aInOutPrinterInfo,
CUPSPrinterInfo& aInOutPrinterInfo) const { http_t* const aConnection) const {
if (aInOutPrinterInfo.mWasInited) { if (aInOutPrinterInfo.mPrinterInfo) {
return; return;
} }
aInOutPrinterInfo.mWasInited = true; if (aConnection == CUPS_HTTP_DEFAULT) {
if (aInOutPrinterInfo.mTriedInitWithDefault) {
return;
}
aInOutPrinterInfo.mTriedInitWithDefault = true;
} else {
if (aInOutPrinterInfo.mTriedInitWithConnection) {
return;
}
aInOutPrinterInfo.mTriedInitWithConnection = true;
}
// 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.
aInOutPrinterInfo.mPrinterInfo = aInOutPrinterInfo.mPrinterInfo =
mShim.cupsCopyDestInfo(CUPS_HTTP_DEFAULT, mPrinter); mShim.cupsCopyDestInfo(aConnection, 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.

View File

@ -50,8 +50,10 @@ class nsPrinterCUPS final : public nsPrinterBase {
uint64_t mCUPSMinor = 0; uint64_t mCUPSMinor = 0;
uint64_t mCUPSPatch = 0; uint64_t mCUPSPatch = 0;
// Tracks whether we have attempted to fetch mPrinterInfo yet. // Whether we have attempted to fetch mPrinterInfo with CUPS_HTTP_DEFAULT.
bool mWasInited = false; bool mTriedInitWithDefault = false;
// Whether we have attempted to fetch mPrinterInfo with a connection.
bool mTriedInitWithConnection = false;
CUPSPrinterInfo() = default; CUPSPrinterInfo() = default;
CUPSPrinterInfo(const CUPSPrinterInfo&) = delete; CUPSPrinterInfo(const CUPSPrinterInfo&) = delete;
CUPSPrinterInfo(CUPSPrinterInfo&&) = delete; CUPSPrinterInfo(CUPSPrinterInfo&&) = delete;
@ -78,7 +80,15 @@ 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;
void EnsurePrinterInfo(CUPSPrinterInfo& aInOutPrinterInfo) 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).
*/
void TryEnsurePrinterInfo(
CUPSPrinterInfo& aInOutPrinterInfo,
http_t* const aConnection = CUPS_HTTP_DEFAULT) const;
const nsCUPSShim& mShim; const nsCUPSShim& mShim;
nsString mDisplayName; nsString mDisplayName;