Bug 1892041 - Part 3: Update test exclusions. r=spidermonkey-reviewers,dminor
[gecko.git] / widget / nsClipboardProxy.cpp
blob4d0b72bf8e87a5dbe0de7dba1fcc39d29eb02662
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 mozilla::dom::WindowContext* aWindowContext) {
37 #if defined(ACCESSIBILITY) && defined(XP_WIN)
38 a11y::Compatibility::SuppressA11yForClipboardCopy();
39 #endif
41 ContentChild* child = ContentChild::GetSingleton();
42 IPCTransferable ipcTransferable;
43 nsContentUtils::TransferableToIPCTransferable(aTransferable, &ipcTransferable,
44 false, nullptr);
45 child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard,
46 aWindowContext);
47 return NS_OK;
50 NS_IMETHODIMP nsClipboardProxy::AsyncSetData(
51 int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext,
52 nsIAsyncClipboardRequestCallback* aCallback,
53 nsIAsyncSetClipboardData** _retval) {
54 RefPtr<ClipboardWriteRequestChild> request =
55 MakeRefPtr<ClipboardWriteRequestChild>(aCallback);
56 ContentChild::GetSingleton()->SendPClipboardWriteRequestConstructor(
57 request, aWhichClipboard, aSettingWindowContext);
58 request.forget(_retval);
59 return NS_OK;
62 NS_IMETHODIMP
63 nsClipboardProxy::GetData(nsITransferable* aTransferable,
64 int32_t aWhichClipboard,
65 mozilla::dom::WindowContext* aWindowContext) {
66 MOZ_DIAGNOSTIC_ASSERT(aWindowContext && aWindowContext->IsInProcess(),
67 "content clipboard reads must be associated with an "
68 "in-process WindowContext");
69 if (aWindowContext->IsDiscarded()) {
70 return NS_ERROR_NOT_AVAILABLE;
72 nsTArray<nsCString> types;
73 aTransferable->FlavorsTransferableCanImport(types);
75 IPCTransferableData transferable;
76 ContentChild::GetSingleton()->SendGetClipboard(types, aWhichClipboard,
77 aWindowContext, &transferable);
78 return nsContentUtils::IPCTransferableDataToTransferable(
79 transferable, false /* aAddDataFlavor */, aTransferable,
80 false /* aFilterUnknownFlavors */);
83 namespace {
85 class AsyncGetClipboardDataProxy final : public nsIAsyncGetClipboardData {
86 public:
87 explicit AsyncGetClipboardDataProxy(ClipboardReadRequestChild* aActor)
88 : mActor(aActor) {
89 MOZ_ASSERT(mActor);
92 NS_DECL_ISUPPORTS
93 NS_DECL_NSIASYNCGETCLIPBOARDDATA
95 private:
96 virtual ~AsyncGetClipboardDataProxy() {
97 MOZ_ASSERT(mActor);
98 if (mActor->CanSend()) {
99 PClipboardReadRequestChild::Send__delete__(mActor);
103 RefPtr<ClipboardReadRequestChild> mActor;
106 NS_IMPL_ISUPPORTS(AsyncGetClipboardDataProxy, nsIAsyncGetClipboardData)
108 NS_IMETHODIMP AsyncGetClipboardDataProxy::GetValid(bool* aOutResult) {
109 MOZ_ASSERT(mActor);
110 *aOutResult = mActor->CanSend();
111 return NS_OK;
114 NS_IMETHODIMP AsyncGetClipboardDataProxy::GetFlavorList(
115 nsTArray<nsCString>& aFlavorList) {
116 MOZ_ASSERT(mActor);
117 aFlavorList.AppendElements(mActor->FlavorList());
118 return NS_OK;
121 NS_IMETHODIMP AsyncGetClipboardDataProxy::GetData(
122 nsITransferable* aTransferable,
123 nsIAsyncClipboardRequestCallback* aCallback) {
124 if (!aTransferable || !aCallback) {
125 return NS_ERROR_INVALID_ARG;
128 // Get a list of flavors this transferable can import
129 nsTArray<nsCString> flavors;
130 nsresult rv = aTransferable->FlavorsTransferableCanImport(flavors);
131 if (NS_FAILED(rv)) {
132 return rv;
135 MOZ_ASSERT(mActor);
136 // If the requested flavor is not in the list, throw an error.
137 for (const auto& flavor : flavors) {
138 if (!mActor->FlavorList().Contains(flavor)) {
139 return NS_ERROR_FAILURE;
143 if (!mActor->CanSend()) {
144 return aCallback->OnComplete(NS_ERROR_FAILURE);
147 mActor->SendGetData(flavors)->Then(
148 GetMainThreadSerialEventTarget(), __func__,
149 /* resolve */
150 [self = RefPtr{this}, callback = nsCOMPtr{aCallback},
151 transferable = nsCOMPtr{aTransferable}](
152 const IPCTransferableDataOrError& aIpcTransferableDataOrError) {
153 if (aIpcTransferableDataOrError.type() ==
154 IPCTransferableDataOrError::Tnsresult) {
155 MOZ_ASSERT(NS_FAILED(aIpcTransferableDataOrError.get_nsresult()));
156 callback->OnComplete(aIpcTransferableDataOrError.get_nsresult());
157 return;
160 nsresult rv = nsContentUtils::IPCTransferableDataToTransferable(
161 aIpcTransferableDataOrError.get_IPCTransferableData(),
162 false /* aAddDataFlavor */, transferable,
163 false /* aFilterUnknownFlavors */);
164 if (NS_FAILED(rv)) {
165 callback->OnComplete(rv);
166 return;
169 callback->OnComplete(NS_OK);
171 /* reject */
172 [callback =
173 nsCOMPtr{aCallback}](mozilla::ipc::ResponseRejectReason aReason) {
174 callback->OnComplete(NS_ERROR_FAILURE);
177 return NS_OK;
180 static Result<RefPtr<AsyncGetClipboardDataProxy>, nsresult>
181 CreateAsyncGetClipboardDataProxy(
182 ClipboardReadRequestOrError&& aClipboardReadRequestOrError) {
183 if (aClipboardReadRequestOrError.type() ==
184 ClipboardReadRequestOrError::Tnsresult) {
185 MOZ_ASSERT(NS_FAILED(aClipboardReadRequestOrError.get_nsresult()));
186 return Err(aClipboardReadRequestOrError.get_nsresult());
189 ClipboardReadRequest& request =
190 aClipboardReadRequestOrError.get_ClipboardReadRequest();
191 auto requestChild = MakeRefPtr<ClipboardReadRequestChild>(
192 std::move(request.availableTypes()));
193 if (NS_WARN_IF(
194 !ContentChild::GetSingleton()->BindPClipboardReadRequestEndpoint(
195 std::move(request.childEndpoint()), requestChild))) {
196 return Err(NS_ERROR_FAILURE);
199 return MakeRefPtr<AsyncGetClipboardDataProxy>(requestChild);
202 } // namespace
204 NS_IMETHODIMP nsClipboardProxy::AsyncGetData(
205 const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard,
206 mozilla::dom::WindowContext* aRequestingWindowContext,
207 nsIPrincipal* aRequestingPrincipal,
208 nsIAsyncClipboardGetCallback* aCallback) {
209 if (!aCallback || !aRequestingPrincipal || aFlavorList.IsEmpty()) {
210 return NS_ERROR_INVALID_ARG;
213 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
214 MOZ_CLIPBOARD_LOG("%s: clipboard %d is not supported.", __FUNCTION__,
215 aWhichClipboard);
216 return NS_ERROR_FAILURE;
219 ContentChild::GetSingleton()
220 ->SendGetClipboardAsync(aFlavorList, aWhichClipboard,
221 aRequestingWindowContext,
222 WrapNotNull(aRequestingPrincipal))
223 ->Then(
224 GetMainThreadSerialEventTarget(), __func__,
225 /* resolve */
226 [callback = nsCOMPtr{aCallback}](
227 ClipboardReadRequestOrError&& aClipboardReadRequestOrError) {
228 auto result = CreateAsyncGetClipboardDataProxy(
229 std::move(aClipboardReadRequestOrError));
230 if (result.isErr()) {
231 callback->OnError(result.unwrapErr());
232 return;
235 callback->OnSuccess(result.inspect());
237 /* reject */
238 [callback = nsCOMPtr{aCallback}](
239 mozilla::ipc::ResponseRejectReason aReason) {
240 callback->OnError(NS_ERROR_FAILURE);
242 return NS_OK;
245 NS_IMETHODIMP nsClipboardProxy::GetDataSnapshotSync(
246 const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard,
247 mozilla::dom::WindowContext* aRequestingWindowContext,
248 nsIAsyncGetClipboardData** _retval) {
249 *_retval = nullptr;
251 if (aFlavorList.IsEmpty()) {
252 return NS_ERROR_INVALID_ARG;
255 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
256 MOZ_CLIPBOARD_LOG("%s: clipboard %d is not supported.", __FUNCTION__,
257 aWhichClipboard);
258 return NS_ERROR_FAILURE;
261 ContentChild* contentChild = ContentChild::GetSingleton();
262 ClipboardReadRequestOrError requestOrError;
263 contentChild->SendGetClipboardDataSnapshotSync(
264 aFlavorList, aWhichClipboard, aRequestingWindowContext, &requestOrError);
265 auto result = CreateAsyncGetClipboardDataProxy(std::move(requestOrError));
266 if (result.isErr()) {
267 return result.unwrapErr();
270 result.unwrap().forget(_retval);
271 return NS_OK;
274 NS_IMETHODIMP
275 nsClipboardProxy::EmptyClipboard(int32_t aWhichClipboard) {
276 ContentChild::GetSingleton()->SendEmptyClipboard(aWhichClipboard);
277 return NS_OK;
280 NS_IMETHODIMP
281 nsClipboardProxy::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
282 int32_t aWhichClipboard,
283 bool* aHasType) {
284 *aHasType = false;
286 ContentChild::GetSingleton()->SendClipboardHasType(aFlavorList,
287 aWhichClipboard, aHasType);
289 return NS_OK;
292 NS_IMETHODIMP
293 nsClipboardProxy::IsClipboardTypeSupported(int32_t aWhichClipboard,
294 bool* aIsSupported) {
295 switch (aWhichClipboard) {
296 case kGlobalClipboard:
297 // We always support the global clipboard.
298 *aIsSupported = true;
299 return NS_OK;
300 case kSelectionClipboard:
301 *aIsSupported = mClipboardCaps.supportsSelectionClipboard();
302 return NS_OK;
303 case kFindClipboard:
304 *aIsSupported = mClipboardCaps.supportsFindClipboard();
305 return NS_OK;
306 case kSelectionCache:
307 *aIsSupported = mClipboardCaps.supportsSelectionCache();
308 return NS_OK;
311 *aIsSupported = false;
312 return NS_OK;
315 void nsClipboardProxy::SetCapabilities(
316 const ClipboardCapabilities& aClipboardCaps) {
317 mClipboardCaps = aClipboardCaps;