From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- widget/PrintBackgroundTask.h | 121 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 widget/PrintBackgroundTask.h (limited to 'widget/PrintBackgroundTask.h') diff --git a/widget/PrintBackgroundTask.h b/widget/PrintBackgroundTask.h new file mode 100644 index 0000000000..8b18c8a879 --- /dev/null +++ b/widget/PrintBackgroundTask.h @@ -0,0 +1,121 @@ +/* -*- 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/. */ + +#ifndef mozilla_PrintBackgroundTask_h_ +#define mozilla_PrintBackgroundTask_h_ + +#include "mozilla/dom/Promise.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/Telemetry.h" + +#include +#include + +// A helper to resolve a DOM Promise with the result of a const method, executed +// in another thread. +// +// Once in the main thread, the caller can turn the result of the method into a +// JSValue by specializing ResolveOrReject. +namespace mozilla { + +template +void ResolveOrReject(dom::Promise& aPromise, T&, Result& aResult) { + aPromise.MaybeResolve(std::forward(aResult)); +} + +template +using PrintBackgroundTask = Result (T::*)(Args...) const; + +template +void SpawnPrintBackgroundTask( + T& aReceiver, dom::Promise& aPromise, const nsCString& aTelemetryKey, + PrintBackgroundTask aBackgroundTask, Args... aArgs) { + auto promiseHolder = MakeRefPtr>( + "nsPrinterBase::SpawnBackgroundTaskPromise", &aPromise); + // We actually want to allow to access the printer data from the callback, so + // disable strict checking. They should of course only access immutable + // members. + auto holder = MakeRefPtr>( + "nsPrinterBase::SpawnBackgroundTaskPrinter", &aReceiver, + /* strict = */ false); + // See + // https://stackoverflow.com/questions/47496358/c-lambdas-how-to-capture-variadic-parameter-pack-from-the-upper-scope + // about the tuple shenanigans. It could be improved with C++20 + NS_DispatchBackgroundTask( + NS_NewRunnableFunction( + "SpawnPrintBackgroundTask", + [holder = std::move(holder), promiseHolder = std::move(promiseHolder), + aTelemetryKey, startRoundTrip = TimeStamp::Now(), + backgroundTask = aBackgroundTask, + aArgs = std::make_tuple(std::forward(aArgs)...)] { + auto start = TimeStamp::Now(); + Result result = std::apply( + [&](auto&&... args) { + return (holder->get()->*backgroundTask)(args...); + }, + std::move(aArgs)); + Telemetry::AccumulateTimeDelta( + Telemetry::PRINT_BACKGROUND_TASK_TIME_MS, aTelemetryKey, start); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "SpawnPrintBackgroundTaskResolution", + [holder = std::move(holder), + promiseHolder = std::move(promiseHolder), + telemetryKey = std::move(aTelemetryKey), startRoundTrip, + result = std::move(result)] { + Telemetry::AccumulateTimeDelta( + Telemetry::PRINT_BACKGROUND_TASK_ROUND_TRIP_TIME_MS, + telemetryKey, startRoundTrip); + ResolveOrReject(*promiseHolder->get(), *holder->get(), + result); + })); + }), + NS_DISPATCH_EVENT_MAY_BLOCK); +} + +// Gets a fresh promise into aResultPromise, that resolves whenever the print +// background task finishes. +template +nsresult PrintBackgroundTaskPromise( + T& aReceiver, JSContext* aCx, dom::Promise** aResultPromise, + const nsCString& aTelemetryKey, + PrintBackgroundTask aTask, Args... aArgs) { + ErrorResult rv; + RefPtr promise = + dom::Promise::Create(xpc::CurrentNativeGlobal(aCx), rv); + if (MOZ_UNLIKELY(rv.Failed())) { + return rv.StealNSResult(); + } + + SpawnPrintBackgroundTask(aReceiver, *promise, aTelemetryKey, aTask, + std::forward(aArgs)...); + + promise.forget(aResultPromise); + return NS_OK; +} + +// Resolves an async attribute via a background task, creating and storing a +// promise as needed in aPromiseSlot. +template +nsresult AsyncPromiseAttributeGetter( + T& aReceiver, RefPtr& aPromiseSlot, JSContext* aCx, + dom::Promise** aResultPromise, const nsCString& aTelemetryKey, + PrintBackgroundTask aTask, Args... aArgs) { + if (RefPtr existing = aPromiseSlot) { + existing.forget(aResultPromise); + return NS_OK; + } + + nsresult rv = + PrintBackgroundTaskPromise(aReceiver, aCx, aResultPromise, aTelemetryKey, + aTask, std::forward(aArgs)...); + NS_ENSURE_SUCCESS(rv, rv); + + aPromiseSlot = *aResultPromise; + return NS_OK; +} + +} // namespace mozilla + +#endif -- cgit v1.2.3