diff --git a/widget/android/nsClipboard.cpp b/widget/android/nsClipboard.cpp index 6008b5264f1d..47f484e14b6e 100644 --- a/widget/android/nsClipboard.cpp +++ b/widget/android/nsClipboard.cpp @@ -114,6 +114,16 @@ nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard) { return NS_ERROR_FAILURE; } +RefPtr nsClipboard::AsyncGetData(nsITransferable* aTransferable, + int32_t aWhichClipboard) { + nsresult rv = GetData(aTransferable, aWhichClipboard); + if (NS_FAILED(rv)) { + return GenericPromise::CreateAndReject(rv, __func__); + } + + return GenericPromise::CreateAndResolve(true, __func__); +} + NS_IMETHODIMP nsClipboard::EmptyClipboard(int32_t aWhichClipboard) { if (aWhichClipboard != kGlobalClipboard) return NS_ERROR_NOT_IMPLEMENTED; diff --git a/widget/gtk/nsClipboard.cpp b/widget/gtk/nsClipboard.cpp index 48a827fc64d3..72625f9354f8 100644 --- a/widget/gtk/nsClipboard.cpp +++ b/widget/gtk/nsClipboard.cpp @@ -585,6 +585,17 @@ nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard) { return NS_OK; } +RefPtr nsClipboard::AsyncGetData(nsITransferable* aTransferable, + int32_t aWhichClipboard) { + // XXX we should read the clipboard data asynchronously instead, bug 1778201. + nsresult rv = GetData(aTransferable, aWhichClipboard); + if (NS_FAILED(rv)) { + return GenericPromise::CreateAndReject(rv, __func__); + } + + return GenericPromise::CreateAndResolve(true, __func__); +} + NS_IMETHODIMP nsClipboard::EmptyClipboard(int32_t aWhichClipboard) { LOGCLIP("nsClipboard::EmptyClipboard (%s)\n", diff --git a/widget/headless/HeadlessClipboard.cpp b/widget/headless/HeadlessClipboard.cpp index 0d8c7fe572d0..4abf0fb4a70f 100644 --- a/widget/headless/HeadlessClipboard.cpp +++ b/widget/headless/HeadlessClipboard.cpp @@ -108,5 +108,15 @@ HeadlessClipboard::SupportsFindClipboard(bool* _retval) { return NS_OK; } +RefPtr HeadlessClipboard::AsyncGetData( + nsITransferable* aTransferable, int32_t aWhichClipboard) { + nsresult rv = GetData(aTransferable, aWhichClipboard); + if (NS_FAILED(rv)) { + return GenericPromise::CreateAndReject(rv, __func__); + } + + return GenericPromise::CreateAndResolve(true, __func__); +} + } // namespace widget } // namespace mozilla diff --git a/widget/nsBaseClipboard.cpp b/widget/nsBaseClipboard.cpp index 0898aa082a4f..58085db0c11c 100644 --- a/widget/nsBaseClipboard.cpp +++ b/widget/nsBaseClipboard.cpp @@ -12,6 +12,7 @@ #include "nsError.h" #include "nsXPCOM.h" +using mozilla::GenericPromise; using mozilla::LogLevel; nsBaseClipboard::nsBaseClipboard() @@ -92,6 +93,16 @@ NS_IMETHODIMP nsBaseClipboard::GetData(nsITransferable* aTransferable, return NS_ERROR_FAILURE; } +RefPtr nsBaseClipboard::AsyncGetData( + nsITransferable* aTransferable, int32_t aWhichClipboard) { + nsresult rv = GetData(aTransferable, aWhichClipboard); + if (NS_FAILED(rv)) { + return GenericPromise::CreateAndReject(rv, __func__); + } + + return GenericPromise::CreateAndResolve(true, __func__); +} + NS_IMETHODIMP nsBaseClipboard::EmptyClipboard(int32_t aWhichClipboard) { CLIPBOARD_LOG("%s: clipboard=%i", __FUNCTION__, aWhichClipboard); diff --git a/widget/nsClipboardProxy.cpp b/widget/nsClipboardProxy.cpp index 13c5be6109d5..183069cae00a 100644 --- a/widget/nsClipboardProxy.cpp +++ b/widget/nsClipboardProxy.cpp @@ -87,3 +87,42 @@ void nsClipboardProxy::SetCapabilities( const ClipboardCapabilities& aClipboardCaps) { mClipboardCaps = aClipboardCaps; } + +RefPtr nsClipboardProxy::AsyncGetData( + nsITransferable* aTransferable, int32_t aWhichClipboard) { + if (!aTransferable) { + return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } + + // Get a list of flavors this transferable can import + nsTArray flavors; + nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors); + if (NS_FAILED(rv)) { + return GenericPromise::CreateAndReject(rv, __func__); + } + + nsCOMPtr transferable(aTransferable); + auto promise = MakeRefPtr(__func__); + ContentChild::GetSingleton() + ->SendGetClipboardAsync(flavors, aWhichClipboard) + ->Then( + GetMainThreadSerialEventTarget(), __func__, + /* resolve */ + [promise, transferable](const IPCDataTransfer& ipcDataTransfer) { + nsresult rv = nsContentUtils::IPCTransferableToTransferable( + ipcDataTransfer, false /* aAddDataFlavor */, transferable, + ContentChild::GetSingleton()); + if (NS_FAILED(rv)) { + promise->Reject(rv, __func__); + return; + } + + promise->Resolve(true, __func__); + }, + /* reject */ + [promise](mozilla::ipc::ResponseRejectReason aReason) { + promise->Reject(NS_ERROR_FAILURE, __func__); + }); + + return promise.forget(); +} diff --git a/widget/nsIClipboard.idl b/widget/nsIClipboard.idl index 1b89a073c41d..b216959c0d46 100644 --- a/widget/nsIClipboard.idl +++ b/widget/nsIClipboard.idl @@ -9,9 +9,15 @@ #include "nsITransferable.idl" #include "nsIClipboardOwner.idl" +%{C++ +#include "mozilla/MozPromise.h" +%} + interface nsIArray; -[scriptable, uuid(ceaa0047-647f-4b8e-ad1c-aff9fa62aa51)] +native AsyncGetDataPromise(RefPtr); + +[scriptable, builtinclass, uuid(ceaa0047-647f-4b8e-ad1c-aff9fa62aa51)] interface nsIClipboard : nsISupports { const long kSelectionClipboard = 0; @@ -84,9 +90,17 @@ interface nsIClipboard : nsISupports * @result NS_OK if successful. */ boolean supportsFindClipboard ( ) ; + + /** + * Filters the flavors aTransferable can import (see + * `nsITransferable::flavorsTransferableCanImport`) and gets the data for the + * first flavor. That data is set for aTransferable. + * + * @param aTransferable The transferable + * @param aWhichClipboard Specifies the clipboard to which this operation applies. + * @return MozPromise The returned promise will resolve when the data is ready or reject + * if any error occurs. + */ + [noscript, notxpcom, nostdcall] + AsyncGetDataPromise asyncGetData(in nsITransferable aTransferable, in long aWhichClipboard); }; - - -%{ C++ - -%}