diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
commit | 8dd16259287f58f9273002717ec4d27e97127719 (patch) | |
tree | 3863e62a53829a84037444beab3abd4ed9dfc7d0 /widget/windows/filedialog/WinFileDialogParent.cpp | |
parent | Releasing progress-linux version 126.0.1-1~progress7.99u1. (diff) | |
download | firefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz firefox-8dd16259287f58f9273002717ec4d27e97127719.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'widget/windows/filedialog/WinFileDialogParent.cpp')
-rw-r--r-- | widget/windows/filedialog/WinFileDialogParent.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
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 <typename T, typename Ex, size_t N> +static auto ConvertToFDPromise( + const char (&aMethod)[N], // __func__ + Ex&& extractor, + RefPtr<MozPromise<T, mozilla::ipc::ResponseRejectReason, true>> + aSrcPromise) { + // The extractor must produce a `mozilla::Result<..., Error>` from `T`. + using SrcResultInfo = detail::DestructureResult<std::invoke_result_t<Ex, T>>; + using ResolveT = typename SrcResultInfo::OkT; + static_assert(std::is_same_v<typename SrcResultInfo::ErrorT, Error>, + "expected T to be a Result<..., Error>"); + + using SrcPromiseT = MozPromise<T, mozilla::ipc::ResponseRejectReason, true>; + using DstPromiseT = MozPromise<ResolveT, Error, true>; + + RefPtr<DstPromiseT> ret = aSrcPromise->Then( + mozilla::GetCurrentSerialEventTarget(), aMethod, + + [extractor, aMethod](T&& val) { + mozilla::Result<ResolveT, Error> 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 <typename Input, typename Output> +struct Extractor { + template <typename Input::Type tag_, Output const& (Input::*getter_)() const> + static auto get() { + return [](Input&& res) -> Result<Output, Error> { + 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::ShowFileDialogPromise> +WinFileDialogParent::ShowFileDialogImpl(HWND parent, const FileDialogType& type, + mozilla::Span<Command const> commands) { + auto inner_promise = PWinFileDialogParent::SendShowFileDialog( + reinterpret_cast<WindowsHandle>(parent), type, std::move(commands)); + + return ConvertToFDPromise( + __func__, + Extractor<FileResult, Maybe<Results>>::get< + FileResult::TMaybeResults, &FileResult::get_MaybeResults>(), + std::move(inner_promise)); +} + +[[nodiscard]] RefPtr<WinFileDialogParent::ShowFolderDialogPromise> +WinFileDialogParent::ShowFolderDialogImpl( + HWND parent, mozilla::Span<Command const> commands) { + auto inner_promise = PWinFileDialogParent::SendShowFolderDialog( + reinterpret_cast<WindowsHandle>(parent), std::move(commands)); + + return ConvertToFDPromise( + __func__, + Extractor<FolderResult, Maybe<nsString>>::get< + FolderResult::TMaybensString, &FolderResult::get_MaybensString>(), + std::move(inner_promise)); +} + void WinFileDialogParent::ProcessingError(Result aCode, const char* aReason) { detail::LogProcessingError(sLogFileDialog, this, aCode, aReason); } |