Bug 1882593 [wpt PR 44836] - Add test for unknown, invalid ancillary chunk which...
[gecko.git] / widget / nsClipboardProxy.cpp
blob41f285461b99bb263b41897826bc5c3c2c706904
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"
9 #endif
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/dom/WindowGlobalChild.h"
16 #include "mozilla/Unused.h"
17 #include "nsArrayUtils.h"
18 #include "nsBaseClipboard.h"
19 #include "nsISupportsPrimitives.h"
20 #include "nsCOMPtr.h"
21 #include "nsComponentManagerUtils.h"
22 #include "nsXULAppAPI.h"
23 #include "nsContentUtils.h"
24 #include "PermissionMessageUtils.h"
26 using namespace mozilla;
27 using namespace mozilla::dom;
29 NS_IMPL_ISUPPORTS(nsClipboardProxy, nsIClipboard, nsIClipboardProxy)
31 nsClipboardProxy::nsClipboardProxy() : mClipboardCaps(false, false, false) {}
33 NS_IMETHODIMP
34 nsClipboardProxy::SetData(nsITransferable* aTransferable,
35 nsIClipboardOwner* anOwner, int32_t aWhichClipboard) {
36 #if defined(ACCESSIBILITY) && defined(XP_WIN)
37 a11y::Compatibility::SuppressA11yForClipboardCopy();
38 #endif
40 ContentChild* child = ContentChild::GetSingleton();
41 IPCTransferable ipcTransferable;
42 nsContentUtils::TransferableToIPCTransferable(aTransferable, &ipcTransferable,
43 false, nullptr);
44 child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard);
45 return NS_OK;
48 NS_IMETHODIMP nsClipboardProxy::AsyncSetData(
49 int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback,
50 nsIAsyncSetClipboardData** _retval) {
51 RefPtr<ClipboardWriteRequestChild> request =
52 MakeRefPtr<ClipboardWriteRequestChild>(aCallback);
53 ContentChild::GetSingleton()->SendPClipboardWriteRequestConstructor(
54 request, aWhichClipboard);
55 request.forget(_retval);
56 return NS_OK;
59 NS_IMETHODIMP
60 nsClipboardProxy::GetData(nsITransferable* aTransferable,
61 int32_t aWhichClipboard,
62 mozilla::dom::WindowContext* aWindowContext) {
63 MOZ_DIAGNOSTIC_ASSERT(aWindowContext && aWindowContext->IsInProcess(),
64 "content clipboard reads must be associated with an "
65 "in-process WindowContext");
66 if (aWindowContext->IsDiscarded()) {
67 return NS_ERROR_NOT_AVAILABLE;
69 nsTArray<nsCString> types;
70 aTransferable->FlavorsTransferableCanImport(types);
72 IPCTransferableData transferable;
73 ContentChild::GetSingleton()->SendGetClipboard(types, aWhichClipboard,
74 aWindowContext, &transferable);
75 return nsContentUtils::IPCTransferableDataToTransferable(
76 transferable, false /* aAddDataFlavor */, aTransferable,
77 false /* aFilterUnknownFlavors */);
80 namespace {
82 class AsyncGetClipboardDataProxy final : public nsIAsyncGetClipboardData {
83 public:
84 explicit AsyncGetClipboardDataProxy(ClipboardReadRequestChild* aActor)
85 : mActor(aActor) {
86 MOZ_ASSERT(mActor);
89 NS_DECL_ISUPPORTS
90 NS_DECL_NSIASYNCGETCLIPBOARDDATA
92 private:
93 virtual ~AsyncGetClipboardDataProxy() {
94 MOZ_ASSERT(mActor);
95 if (mActor->CanSend()) {
96 PClipboardReadRequestChild::Send__delete__(mActor);
100 RefPtr<ClipboardReadRequestChild> mActor;
103 NS_IMPL_ISUPPORTS(AsyncGetClipboardDataProxy, nsIAsyncGetClipboardData)
105 NS_IMETHODIMP AsyncGetClipboardDataProxy::GetValid(bool* aOutResult) {
106 MOZ_ASSERT(mActor);
107 *aOutResult = mActor->CanSend();
108 return NS_OK;
111 NS_IMETHODIMP AsyncGetClipboardDataProxy::GetFlavorList(
112 nsTArray<nsCString>& aFlavorList) {
113 MOZ_ASSERT(mActor);
114 aFlavorList.AppendElements(mActor->FlavorList());
115 return NS_OK;
118 NS_IMETHODIMP AsyncGetClipboardDataProxy::GetData(
119 nsITransferable* aTransferable,
120 nsIAsyncClipboardRequestCallback* aCallback) {
121 if (!aTransferable || !aCallback) {
122 return NS_ERROR_INVALID_ARG;
125 // Get a list of flavors this transferable can import
126 nsTArray<nsCString> flavors;
127 nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
128 if (NS_FAILED(rv)) {
129 return rv;
132 MOZ_ASSERT(mActor);
133 // If the requested flavor is not in the list, throw an error.
134 for (const auto& flavor : flavors) {
135 if (!mActor->FlavorList().Contains(flavor)) {
136 return NS_ERROR_FAILURE;
140 if (!mActor->CanSend()) {
141 return aCallback->OnComplete(NS_ERROR_FAILURE);
144 mActor->SendGetData(flavors)->Then(
145 GetMainThreadSerialEventTarget(), __func__,
146 /* resolve */
147 [self = RefPtr{this}, callback = nsCOMPtr{aCallback},
148 transferable = nsCOMPtr{aTransferable}](
149 const IPCTransferableDataOrError& aIpcTransferableDataOrError) {
150 if (aIpcTransferableDataOrError.type() ==
151 IPCTransferableDataOrError::Tnsresult) {
152 MOZ_ASSERT(NS_FAILED(aIpcTransferableDataOrError.get_nsresult()));
153 callback->OnComplete(aIpcTransferableDataOrError.get_nsresult());
154 return;
157 nsresult rv = nsContentUtils::IPCTransferableDataToTransferable(
158 aIpcTransferableDataOrError.get_IPCTransferableData(),
159 false /* aAddDataFlavor */, transferable,
160 false /* aFilterUnknownFlavors */);
161 if (NS_FAILED(rv)) {
162 callback->OnComplete(rv);
163 return;
166 callback->OnComplete(NS_OK);
168 /* reject */
169 [callback =
170 nsCOMPtr{aCallback}](mozilla::ipc::ResponseRejectReason aReason) {
171 callback->OnComplete(NS_ERROR_FAILURE);
174 return NS_OK;
177 } // namespace
179 NS_IMETHODIMP nsClipboardProxy::AsyncGetData(
180 const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard,
181 mozilla::dom::WindowContext* aRequestingWindowContext,
182 nsIPrincipal* aRequestingPrincipal,
183 nsIAsyncClipboardGetCallback* aCallback) {
184 if (!aCallback || !aRequestingPrincipal || aFlavorList.IsEmpty()) {
185 return NS_ERROR_INVALID_ARG;
188 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
189 MOZ_CLIPBOARD_LOG("%s: clipboard %d is not supported.", __FUNCTION__,
190 aWhichClipboard);
191 return NS_ERROR_FAILURE;
194 ContentChild::GetSingleton()
195 ->SendGetClipboardAsync(aFlavorList, aWhichClipboard,
196 aRequestingWindowContext,
197 WrapNotNull(aRequestingPrincipal))
198 ->Then(
199 GetMainThreadSerialEventTarget(), __func__,
200 /* resolve */
201 [callback = nsCOMPtr{aCallback}](const PClipboardReadRequestOrError&
202 aClipboardReadRequestOrError) {
203 if (aClipboardReadRequestOrError.type() ==
204 PClipboardReadRequestOrError::Tnsresult) {
205 MOZ_ASSERT(
206 NS_FAILED(aClipboardReadRequestOrError.get_nsresult()));
207 callback->OnError(aClipboardReadRequestOrError.get_nsresult());
208 return;
211 auto asyncGetClipboardData = MakeRefPtr<AsyncGetClipboardDataProxy>(
212 static_cast<ClipboardReadRequestChild*>(
213 aClipboardReadRequestOrError.get_PClipboardReadRequest()
214 .AsChild()
215 .get()));
217 callback->OnSuccess(asyncGetClipboardData);
219 /* reject */
220 [callback = nsCOMPtr{aCallback}](
221 mozilla::ipc::ResponseRejectReason aReason) {
222 callback->OnError(NS_ERROR_FAILURE);
224 return NS_OK;
227 NS_IMETHODIMP
228 nsClipboardProxy::EmptyClipboard(int32_t aWhichClipboard) {
229 ContentChild::GetSingleton()->SendEmptyClipboard(aWhichClipboard);
230 return NS_OK;
233 NS_IMETHODIMP
234 nsClipboardProxy::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
235 int32_t aWhichClipboard,
236 bool* aHasType) {
237 *aHasType = false;
239 ContentChild::GetSingleton()->SendClipboardHasType(aFlavorList,
240 aWhichClipboard, aHasType);
242 return NS_OK;
245 NS_IMETHODIMP
246 nsClipboardProxy::IsClipboardTypeSupported(int32_t aWhichClipboard,
247 bool* aIsSupported) {
248 switch (aWhichClipboard) {
249 case kGlobalClipboard:
250 // We always support the global clipboard.
251 *aIsSupported = true;
252 return NS_OK;
253 case kSelectionClipboard:
254 *aIsSupported = mClipboardCaps.supportsSelectionClipboard();
255 return NS_OK;
256 case kFindClipboard:
257 *aIsSupported = mClipboardCaps.supportsFindClipboard();
258 return NS_OK;
259 case kSelectionCache:
260 *aIsSupported = mClipboardCaps.supportsSelectionCache();
261 return NS_OK;
264 *aIsSupported = false;
265 return NS_OK;
268 void nsClipboardProxy::SetCapabilities(
269 const ClipboardCapabilities& aClipboardCaps) {
270 mClipboardCaps = aClipboardCaps;