Convert nsIPrinter.supportsDuplex to a Promise
Categories
(Core :: Printing: Setup, enhancement, P2)
Tracking
()
Tracking | Status | |
---|---|---|
firefox81 | --- | fixed |
People
(Reporter: jwatt, Assigned: emilio)
References
(Blocks 1 open bug)
Details
(Whiteboard: [print2020_v81])
Attachments
(1 file, 1 obsolete file)
(deleted),
text/x-phabricator-request
|
Details |
Reporter | ||
Comment 1•4 years ago
|
||
Reporter | ||
Comment 2•4 years ago
|
||
Some example code of a couple of approaches I've tried. Both require switching nsPrinterCUPS
from using NS_DECL_ISUPPORTS
to using NS_DECL_THREADSAFE_ISUPPORTS
.
NS_IMETHODIMP
nsPrinterCUPS::GetSupportsDuplex(JSContext* aCx, Promise** aResult) {
MOZ_ASSERT(aResult);
if (mDuplexPromise) {
*aResult = do_AddRef(mDuplexPromise).take();
return NS_OK;
}
*aResult = nullptr;
if (!XRE_IsParentProcess()) {
return NS_ERROR_FAILURE;
}
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
if (NS_WARN_IF(!global)) {
return NS_ERROR_FAILURE;
}
ErrorResult er;
mDuplexPromise = Promise::Create(global, er);
if (NS_WARN_IF(er.Failed())) {
return er.StealNSResult();
}
/**
* APPROACH 1:
* ___________
*/
RefPtr<nsPrinterCUPS> self = this;
NS_DispatchBackgroundTask(
NS_NewRunnableFunction("GetPrinterSupportsDuplexBgThread", [self]() {
bool supportsDuplex = self->mShim.mCupsCheckDestSupported(
CUPS_HTTP_DEFAULT, self->mPrinter, self->mPrinterInfo, CUPS_SIDES,
CUPS_SIDES_TWO_SIDED_PORTRAIT);
NS_DispatchToMainThread(NS_NewRunnableFunction(
"GetPrinterSupportsDuplexMainThread", [self, supportsDuplex]() {
self->mDuplexPromise->MaybeResolve(supportsDuplex);
}));
}));
/**
* APPROACH 2:
* ___________
*/
// A MozPromise to be resolved off-main thread:
auto bgPromise = MakeRefPtr<GenericPromise::Private>(__func__);
// Do the blocking call to query the printer on a background thread:
// RefPtr<nsPrinterCUPS> self = this;
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
"GetPrinterSupportsDuplexBgTask", [self, bgPromise]() {
bool supportsDuplex = self->mShim.mCupsCheckDestSupported(
CUPS_HTTP_DEFAULT, self->mPrinter, self->mPrinterInfo, CUPS_SIDES,
CUPS_SIDES_TWO_SIDED_PORTRAIT);
bgPromise->Resolve(supportsDuplex, __func__);
}));
// Resolve the JS Promise on the main thread after the MozPromise resolves:
auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<GenericPromise>>(global);
RefPtr<Promise> outer = mDuplexPromise;
bgPromise
->Then(
global->EventTargetFor(TaskCategory::Other), __func__,
[holder, outer](bool aResult) {
holder->Complete();
outer->MaybeResolve(aResult);
},
[holder, outer](nsresult aRv) {
holder->Complete();
outer->MaybeReject(aRv);
})
->Track(*holder);
*aResult = do_AddRef(mDuplexPromise).take();
return NS_OK;
}
Assignee | ||
Comment 3•4 years ago
|
||
I think approach 1 should work without changing it if you use self = std::move(self)
on the second closure (so you don't change the refcount off the main thread). We also have some helpers for this kind of stuff like nsMainThreadPtrHolder
and such.
Assignee | ||
Comment 4•4 years ago
|
||
While at it, properly CC the printer classes, as they're going to hold
promises and it's very easy to introduce leaks otherwise.
Reporter | ||
Comment 5•4 years ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #3)
I think approach 1 should work without changing it if you use
self = std::move(self)
on the second closure (so you don't change the refcount off the main thread).
Unfortunately that did not work when I tried it. See:
Comment 7•4 years ago
|
||
bugherder |
Updated•4 years ago
|
Reporter | ||
Updated•4 years ago
|
Description
•