gecko-dev/widget/nsPrinterBase.cpp
Emily McDonough 6635212e1a Bug 1663652 part 2 - Add combined printerInfo method to nsPrinterCUPS r=emilio
Since we no longer are using the PaperList or CreateDefaultSettings methods on
nsPrinterBase, and we can remove them from nsPrinterBase.

This should dramatically improve latency when the remote printer is not
available, or when the print server is slower. In the best-case scenario it may
increase the latency to displaying the print preview somewhat.

Differential Revision: https://phabricator.services.mozilla.com/D94482
2020-11-03 20:35:38 +00:00

213 lines
7.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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/. */
#include "nsPrinterBase.h"
#include "nsPaperMargin.h"
#include <utility>
#include "nsPaper.h"
#include "nsIPrintSettings.h"
#include "PrintBackgroundTask.h"
#include "mozilla/dom/Promise.h"
using namespace mozilla;
using mozilla::dom::Promise;
using mozilla::gfx::MarginDouble;
// The maximum error when considering a paper size equal, in points.
// There is some variance in the actual sizes returned by printer drivers and
// print servers for paper sizes. This is a best-guess based on initial
// telemetry which should catch most near-miss dimensions. This should let us
// get consistent paper size names even when the size isn't quite exactly the
// correct size.
static constexpr double kPaperSizePointsEpsilon = 4.0;
// Basic implementation of nsIPrinterInfo
class nsPrinterInfo : public nsIPrinterInfo {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsPrinterInfo)
NS_DECL_NSIPRINTERINFO
nsPrinterInfo() = delete;
nsPrinterInfo(nsPrinterBase& aPrinter,
const nsPrinterBase::PrinterInfo& aPrinterInfo)
: mDefaultSettings(
CreatePlatformPrintSettings(aPrinterInfo.mDefaultSettings)) {
mPaperList.SetCapacity(aPrinterInfo.mPaperList.Length());
for (const PaperInfo& info : aPrinterInfo.mPaperList) {
mPaperList.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
}
}
private:
virtual ~nsPrinterInfo() = default;
nsTArray<RefPtr<nsIPaper>> mPaperList;
RefPtr<nsIPrintSettings> mDefaultSettings;
};
NS_IMETHODIMP
nsPrinterInfo::GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) {
aPaperList = mPaperList.Clone();
return NS_OK;
}
NS_IMETHODIMP
nsPrinterInfo::GetDefaultSettings(nsIPrintSettings** aDefaultSettings) {
NS_ENSURE_ARG_POINTER(aDefaultSettings);
MOZ_ASSERT(mDefaultSettings);
RefPtr<nsIPrintSettings> settings = mDefaultSettings;
settings.forget(aDefaultSettings);
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION(nsPrinterInfo, mPaperList, mDefaultSettings)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterInfo)
NS_INTERFACE_MAP_ENTRY(nsIPrinterInfo)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrinterInfo)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterInfo)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterInfo)
template <typename Index, Index Size, typename Value>
inline void ImplCycleCollectionTraverse(
nsCycleCollectionTraversalCallback& aCallback,
EnumeratedArray<Index, Size, Value>& aArray, const char* aName,
uint32_t aFlags = 0) {
aFlags |= CycleCollectionEdgeNameArrayFlag;
for (Value& element : aArray) {
ImplCycleCollectionTraverse(aCallback, element, aName, aFlags);
}
}
template <typename Index, Index Size, typename Value>
inline void ImplCycleCollectionUnlink(
EnumeratedArray<Index, Size, Value>& aArray) {
for (Value& element : aArray) {
ImplCycleCollectionUnlink(element);
}
}
namespace mozilla {
template <>
void ResolveOrReject(Promise& aPromise, nsPrinterBase&,
const MarginDouble& aResult) {
auto margin = MakeRefPtr<nsPaperMargin>(aResult);
aPromise.MaybeResolve(margin);
}
template <>
void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
const nsTArray<PaperInfo>& aResult) {
nsTArray<RefPtr<nsPaper>> result;
result.SetCapacity(aResult.Length());
for (const PaperInfo& info : aResult) {
result.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
}
aPromise.MaybeResolve(result);
}
template <>
void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
const PrintSettingsInitializer& aResult) {
aPromise.MaybeResolve(
RefPtr<nsIPrintSettings>(CreatePlatformPrintSettings(aResult)));
}
template <>
void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
const nsPrinterBase::PrinterInfo& aResult) {
aPromise.MaybeResolve(MakeRefPtr<nsPrinterInfo>(aPrinter, aResult));
}
} // namespace mozilla
template <typename T, typename... Args>
nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
JSContext* aCx, Promise** aResultPromise, AsyncAttribute aAttribute,
BackgroundTask<T, Args...> aBackgroundTask, Args... aArgs) {
MOZ_ASSERT(NS_IsMainThread());
static constexpr EnumeratedArray<AsyncAttribute, AsyncAttribute::Last,
nsLiteralCString>
attributeKeys{"SupportsDuplex"_ns, "SupportsColor"_ns,
"SupportsMonochrome"_ns, "SupportsCollation"_ns,
"PrinterInfo"_ns};
return mozilla::AsyncPromiseAttributeGetter(
*this, mAsyncAttributePromises[aAttribute], aCx, aResultPromise,
attributeKeys[aAttribute], aBackgroundTask, std::forward<Args>(aArgs)...);
}
NS_IMETHODIMP nsPrinterBase::GetSupportsDuplex(JSContext* aCx,
Promise** aResultPromise) {
return AsyncPromiseAttributeGetter(aCx, aResultPromise,
AsyncAttribute::SupportsDuplex,
&nsPrinterBase::SupportsDuplex);
}
NS_IMETHODIMP nsPrinterBase::GetSupportsColor(JSContext* aCx,
Promise** aResultPromise) {
return AsyncPromiseAttributeGetter(aCx, aResultPromise,
AsyncAttribute::SupportsColor,
&nsPrinterBase::SupportsColor);
}
NS_IMETHODIMP nsPrinterBase::GetSupportsMonochrome(JSContext* aCx,
Promise** aResultPromise) {
return AsyncPromiseAttributeGetter(aCx, aResultPromise,
AsyncAttribute::SupportsMonochrome,
&nsPrinterBase::SupportsMonochrome);
}
NS_IMETHODIMP nsPrinterBase::GetSupportsCollation(JSContext* aCx,
Promise** aResultPromise) {
return AsyncPromiseAttributeGetter(aCx, aResultPromise,
AsyncAttribute::SupportsCollation,
&nsPrinterBase::SupportsCollation);
}
NS_IMETHODIMP nsPrinterBase::GetPrinterInfo(JSContext* aCx,
Promise** aResultPromise) {
return AsyncPromiseAttributeGetter(aCx, aResultPromise,
AsyncAttribute::PrinterInfo,
&nsPrinterBase::CreatePrinterInfo);
}
void nsPrinterBase::QueryMarginsForPaper(Promise& aPromise,
const nsString& aPaperId) {
return SpawnPrintBackgroundTask(*this, aPromise, "MarginsForPaper"_ns,
&nsPrinterBase::GetMarginsForPaper, aPaperId);
}
NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase)
NS_INTERFACE_MAP_ENTRY(nsIPrinter)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrinter)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterBase)
nsPrinterBase::nsPrinterBase(const CommonPaperInfoArray* aPaperInfoArray)
: mCommonPaperInfo(aPaperInfoArray) {
MOZ_DIAGNOSTIC_ASSERT(aPaperInfoArray, "Localized paper info was null");
}
nsPrinterBase::~nsPrinterBase() = default;
const PaperInfo* nsPrinterBase::FindCommonPaperSize(
const gfx::SizeDouble& aSize) const {
for (const PaperInfo& paper : *mCommonPaperInfo) {
if (std::abs(paper.mSize.width - aSize.width) <= kPaperSizePointsEpsilon &&
std::abs(paper.mSize.height - aSize.height) <=
kPaperSizePointsEpsilon) {
return &paper;
}
}
return nullptr;
}