1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsClipboardProxy.h"
7 #if defined(ACCESSIBILITY) && defined(XP_WIN)
8 # include "mozilla/a11y/Compatibility.h"
10 #include "mozilla/ClipboardReadRequestChild.h"
11 #include "mozilla/ClipboardWriteRequestChild.h"
12 #include "mozilla/dom/ContentChild.h"
13 #include "mozilla/net/CookieJarSettings.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/Unused.h"
16 #include "nsArrayUtils.h"
17 #include "nsBaseClipboard.h"
18 #include "nsISupportsPrimitives.h"
20 #include "nsComponentManagerUtils.h"
21 #include "nsXULAppAPI.h"
22 #include "nsContentUtils.h"
23 #include "PermissionMessageUtils.h"
25 using namespace mozilla
;
26 using namespace mozilla::dom
;
28 NS_IMPL_ISUPPORTS(nsClipboardProxy
, nsIClipboard
, nsIClipboardProxy
)
30 nsClipboardProxy::nsClipboardProxy() : mClipboardCaps(false, false, false) {}
33 nsClipboardProxy::SetData(nsITransferable
* aTransferable
,
34 nsIClipboardOwner
* anOwner
, int32_t aWhichClipboard
) {
35 #if defined(ACCESSIBILITY) && defined(XP_WIN)
36 a11y::Compatibility::SuppressA11yForClipboardCopy();
39 ContentChild
* child
= ContentChild::GetSingleton();
40 IPCTransferable ipcTransferable
;
41 nsContentUtils::TransferableToIPCTransferable(aTransferable
, &ipcTransferable
,
43 child
->SendSetClipboard(std::move(ipcTransferable
), aWhichClipboard
);
47 NS_IMETHODIMP
nsClipboardProxy::AsyncSetData(
48 int32_t aWhichClipboard
, nsIAsyncClipboardRequestCallback
* aCallback
,
49 nsIAsyncSetClipboardData
** _retval
) {
50 RefPtr
<ClipboardWriteRequestChild
> request
=
51 MakeRefPtr
<ClipboardWriteRequestChild
>(aCallback
);
52 ContentChild::GetSingleton()->SendPClipboardWriteRequestConstructor(
53 request
, aWhichClipboard
);
54 request
.forget(_retval
);
59 nsClipboardProxy::GetData(nsITransferable
* aTransferable
,
60 int32_t aWhichClipboard
) {
61 nsTArray
<nsCString
> types
;
62 aTransferable
->FlavorsTransferableCanImport(types
);
64 IPCTransferableData transferable
;
65 ContentChild::GetSingleton()->SendGetClipboard(types
, aWhichClipboard
,
67 return nsContentUtils::IPCTransferableDataToTransferable(
68 transferable
, false /* aAddDataFlavor */, aTransferable
,
69 false /* aFilterUnknownFlavors */);
74 class AsyncGetClipboardDataProxy final
: public nsIAsyncGetClipboardData
{
76 explicit AsyncGetClipboardDataProxy(ClipboardReadRequestChild
* aActor
)
82 NS_DECL_NSIASYNCGETCLIPBOARDDATA
85 virtual ~AsyncGetClipboardDataProxy() {
87 if (mActor
->CanSend()) {
88 PClipboardReadRequestChild::Send__delete__(mActor
);
92 RefPtr
<ClipboardReadRequestChild
> mActor
;
95 NS_IMPL_ISUPPORTS(AsyncGetClipboardDataProxy
, nsIAsyncGetClipboardData
)
97 NS_IMETHODIMP
AsyncGetClipboardDataProxy::GetValid(bool* aOutResult
) {
99 *aOutResult
= mActor
->CanSend();
103 NS_IMETHODIMP
AsyncGetClipboardDataProxy::GetFlavorList(
104 nsTArray
<nsCString
>& aFlavorList
) {
106 aFlavorList
.AppendElements(mActor
->FlavorList());
110 NS_IMETHODIMP
AsyncGetClipboardDataProxy::GetData(
111 nsITransferable
* aTransferable
,
112 nsIAsyncClipboardRequestCallback
* aCallback
) {
113 if (!aTransferable
|| !aCallback
) {
114 return NS_ERROR_INVALID_ARG
;
117 // Get a list of flavors this transferable can import
118 nsTArray
<nsCString
> flavors
;
119 nsresult rv
= aTransferable
->FlavorsTransferableCanImport(flavors
);
125 // If the requested flavor is not in the list, throw an error.
126 for (const auto& flavor
: flavors
) {
127 if (!mActor
->FlavorList().Contains(flavor
)) {
128 return NS_ERROR_FAILURE
;
132 if (!mActor
->CanSend()) {
133 return aCallback
->OnComplete(NS_ERROR_FAILURE
);
136 mActor
->SendGetData(flavors
)->Then(
137 GetMainThreadSerialEventTarget(), __func__
,
139 [self
= RefPtr
{this}, callback
= nsCOMPtr
{aCallback
},
140 transferable
= nsCOMPtr
{aTransferable
}](
141 const IPCTransferableDataOrError
& aIpcTransferableDataOrError
) {
142 if (aIpcTransferableDataOrError
.type() ==
143 IPCTransferableDataOrError::Tnsresult
) {
144 MOZ_ASSERT(NS_FAILED(aIpcTransferableDataOrError
.get_nsresult()));
145 callback
->OnComplete(aIpcTransferableDataOrError
.get_nsresult());
149 nsresult rv
= nsContentUtils::IPCTransferableDataToTransferable(
150 aIpcTransferableDataOrError
.get_IPCTransferableData(),
151 false /* aAddDataFlavor */, transferable
,
152 false /* aFilterUnknownFlavors */);
154 callback
->OnComplete(rv
);
158 callback
->OnComplete(NS_OK
);
162 nsCOMPtr
{aCallback
}](mozilla::ipc::ResponseRejectReason aReason
) {
163 callback
->OnComplete(NS_ERROR_FAILURE
);
171 NS_IMETHODIMP
nsClipboardProxy::AsyncGetData(
172 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
173 mozilla::dom::WindowContext
* aRequestingWindowContext
,
174 nsIPrincipal
* aRequestingPrincipal
,
175 nsIAsyncClipboardGetCallback
* aCallback
) {
176 if (!aCallback
|| !aRequestingPrincipal
|| aFlavorList
.IsEmpty()) {
177 return NS_ERROR_INVALID_ARG
;
180 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard
)) {
181 MOZ_CLIPBOARD_LOG("%s: clipboard %d is not supported.", __FUNCTION__
,
183 return NS_ERROR_FAILURE
;
186 ContentChild::GetSingleton()
187 ->SendGetClipboardAsync(aFlavorList
, aWhichClipboard
,
188 aRequestingWindowContext
,
189 WrapNotNull(aRequestingPrincipal
))
191 GetMainThreadSerialEventTarget(), __func__
,
193 [callback
= nsCOMPtr
{aCallback
}](const PClipboardReadRequestOrError
&
194 aClipboardReadRequestOrError
) {
195 if (aClipboardReadRequestOrError
.type() ==
196 PClipboardReadRequestOrError::Tnsresult
) {
198 NS_FAILED(aClipboardReadRequestOrError
.get_nsresult()));
199 callback
->OnError(aClipboardReadRequestOrError
.get_nsresult());
203 auto asyncGetClipboardData
= MakeRefPtr
<AsyncGetClipboardDataProxy
>(
204 static_cast<ClipboardReadRequestChild
*>(
205 aClipboardReadRequestOrError
.get_PClipboardReadRequest()
209 callback
->OnSuccess(asyncGetClipboardData
);
212 [callback
= nsCOMPtr
{aCallback
}](
213 mozilla::ipc::ResponseRejectReason aReason
) {
214 callback
->OnError(NS_ERROR_FAILURE
);
220 nsClipboardProxy::EmptyClipboard(int32_t aWhichClipboard
) {
221 ContentChild::GetSingleton()->SendEmptyClipboard(aWhichClipboard
);
226 nsClipboardProxy::HasDataMatchingFlavors(const nsTArray
<nsCString
>& aFlavorList
,
227 int32_t aWhichClipboard
,
231 ContentChild::GetSingleton()->SendClipboardHasType(aFlavorList
,
232 aWhichClipboard
, aHasType
);
238 nsClipboardProxy::IsClipboardTypeSupported(int32_t aWhichClipboard
,
239 bool* aIsSupported
) {
240 switch (aWhichClipboard
) {
241 case kGlobalClipboard
:
242 // We always support the global clipboard.
243 *aIsSupported
= true;
245 case kSelectionClipboard
:
246 *aIsSupported
= mClipboardCaps
.supportsSelectionClipboard();
249 *aIsSupported
= mClipboardCaps
.supportsFindClipboard();
251 case kSelectionCache
:
252 *aIsSupported
= mClipboardCaps
.supportsSelectionCache();
256 *aIsSupported
= false;
260 void nsClipboardProxy::SetCapabilities(
261 const ClipboardCapabilities
& aClipboardCaps
) {
262 mClipboardCaps
= aClipboardCaps
;