From 59203c63bb777a3bacec32fb8830fba33540e809 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:29 +0200 Subject: Adding upstream version 127.0. Signed-off-by: Daniel Baumann --- widget/windows/filedialog/WinFileDialogParent.cpp | 80 +++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'widget/windows/filedialog/WinFileDialogParent.cpp') diff --git a/widget/windows/filedialog/WinFileDialogParent.cpp b/widget/windows/filedialog/WinFileDialogParent.cpp index 2c256a1506..329c72cc94 100644 --- a/widget/windows/filedialog/WinFileDialogParent.cpp +++ b/widget/windows/filedialog/WinFileDialogParent.cpp @@ -54,6 +54,86 @@ PWinFileDialogParent::nsresult WinFileDialogParent::BindToUtilityProcess( return NS_OK; } +// Convert the raw IPC promise-type to a filedialog::Promise. +template +static auto ConvertToFDPromise( + const char (&aMethod)[N], // __func__ + Ex&& extractor, + RefPtr> + aSrcPromise) { + // The extractor must produce a `mozilla::Result<..., Error>` from `T`. + using SrcResultInfo = detail::DestructureResult>; + using ResolveT = typename SrcResultInfo::OkT; + static_assert(std::is_same_v, + "expected T to be a Result<..., Error>"); + + using SrcPromiseT = MozPromise; + using DstPromiseT = MozPromise; + + RefPtr ret = aSrcPromise->Then( + mozilla::GetCurrentSerialEventTarget(), aMethod, + + [extractor, aMethod](T&& val) { + mozilla::Result result = extractor(std::move(val)); + if (result.isOk()) { + return DstPromiseT::CreateAndResolve(result.unwrap(), aMethod); + } + return DstPromiseT::CreateAndReject(result.unwrapErr(), aMethod); + }, + [aMethod](typename mozilla::ipc::ResponseRejectReason&& val) { + return DstPromiseT::CreateAndReject( + MOZ_FD_ERROR(IPCError, "IPC", (uint32_t)val), aMethod); + }); + + return ret; +} + +template +struct Extractor { + template + static auto get() { + return [](Input&& res) -> Result { + if (res.type() == tag_) { + return (res.*getter_)(); + } + if (res.type() == Input::TRemoteError) { + RemoteError err = res.get_RemoteError(); + return Err(Error{.kind = Error::RemoteError, + .where = Error::Location::Deserialize(err.where()), + .why = err.why()}); + } + MOZ_ASSERT_UNREACHABLE("internal IPC failure?"); + return Err(MOZ_FD_ERROR(IPCError, "internal IPC failure?", E_FAIL)); + }; + } +}; + +[[nodiscard]] RefPtr +WinFileDialogParent::ShowFileDialogImpl(HWND parent, const FileDialogType& type, + mozilla::Span commands) { + auto inner_promise = PWinFileDialogParent::SendShowFileDialog( + reinterpret_cast(parent), type, std::move(commands)); + + return ConvertToFDPromise( + __func__, + Extractor>::get< + FileResult::TMaybeResults, &FileResult::get_MaybeResults>(), + std::move(inner_promise)); +} + +[[nodiscard]] RefPtr +WinFileDialogParent::ShowFolderDialogImpl( + HWND parent, mozilla::Span commands) { + auto inner_promise = PWinFileDialogParent::SendShowFolderDialog( + reinterpret_cast(parent), std::move(commands)); + + return ConvertToFDPromise( + __func__, + Extractor>::get< + FolderResult::TMaybensString, &FolderResult::get_MaybensString>(), + std::move(inner_promise)); +} + void WinFileDialogParent::ProcessingError(Result aCode, const char* aReason) { detail::LogProcessingError(sLogFileDialog, this, aCode, aReason); } -- cgit v1.2.3