1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ClipboardReadRequestParent.h"
8 #include "mozilla/dom/ContentParent.h"
9 #include "mozilla/net/CookieJarSettings.h"
10 #include "nsComponentManagerUtils.h"
11 #include "nsIClipboard.h"
12 #include "nsITransferable.h"
13 #include "nsThreadManager.h"
14 #include "nsWidgetsCID.h"
16 using mozilla::dom::ContentParent
;
17 using mozilla::ipc::IPCResult
;
23 class ClipboardGetDataCallback final
: public nsIAsyncClipboardRequestCallback
{
25 explicit ClipboardGetDataCallback(std::function
<void(nsresult
)>&& aCallback
)
26 : mCallback(std::move(aCallback
)) {}
28 // This object will never be held by a cycle-collected object, so it doesn't
29 // need to be cycle-collected despite holding alive cycle-collected objects.
32 // nsIAsyncClipboardRequestCallback
33 NS_IMETHOD
OnComplete(nsresult aResult
) override
{
39 ~ClipboardGetDataCallback() = default;
41 std::function
<void(nsresult
)> mCallback
;
44 NS_IMPL_ISUPPORTS(ClipboardGetDataCallback
, nsIAsyncClipboardRequestCallback
)
46 static Result
<nsCOMPtr
<nsITransferable
>, nsresult
> CreateTransferable(
47 const nsTArray
<nsCString
>& aTypes
) {
49 nsCOMPtr
<nsITransferable
> trans
=
50 do_CreateInstance("@mozilla.org/widget/transferable;1", &rv
);
55 MOZ_TRY(trans
->Init(nullptr));
56 // The private flag is only used to prevent the data from being cached to the
57 // disk. The flag is not exported to the IPCDataTransfer object.
58 // The flag is set because we are not sure whether the clipboard data is used
59 // in a private browsing context. The transferable is only used in this scope,
60 // so the cache would not reduce memory consumption anyway.
61 trans
->SetIsPrivateData(true);
62 // Fill out flavors for transferable
63 for (uint32_t t
= 0; t
< aTypes
.Length(); t
++) {
64 MOZ_TRY(trans
->AddDataFlavor(aTypes
[t
].get()));
67 return std::move(trans
);
72 IPCResult
ClipboardReadRequestParent::RecvGetData(
73 const nsTArray
<nsCString
>& aFlavors
, GetDataResolver
&& aResolver
) {
75 if (NS_FAILED(mClipboardDataSnapshot
->GetValid(&valid
)) || !valid
) {
76 Unused
<< PClipboardReadRequestParent::Send__delete__(this);
77 aResolver(NS_ERROR_NOT_AVAILABLE
);
81 // Create transferable
82 auto result
= CreateTransferable(aFlavors
);
84 aResolver(result
.unwrapErr());
88 nsCOMPtr
<nsITransferable
> trans
= result
.unwrap();
89 RefPtr
<ClipboardGetDataCallback
> callback
=
90 MakeRefPtr
<ClipboardGetDataCallback
>([self
= RefPtr
{this},
91 resolver
= std::move(aResolver
),
93 manager
= mManager
](nsresult aRv
) {
96 if (NS_FAILED(self
->mClipboardDataSnapshot
->GetValid(&valid
)) ||
98 Unused
<< PClipboardReadRequestParent::Send__delete__(self
);
104 dom::IPCTransferableData ipcTransferableData
;
105 nsContentUtils::TransferableToIPCTransferableData(
106 trans
, &ipcTransferableData
, false /* aInSyncMessage */, manager
);
107 resolver(std::move(ipcTransferableData
));
109 nsresult rv
= mClipboardDataSnapshot
->GetData(trans
, callback
);
111 callback
->OnComplete(rv
);
116 IPCResult
ClipboardReadRequestParent::RecvGetDataSync(
117 const nsTArray
<nsCString
>& aFlavors
,
118 dom::IPCTransferableDataOrError
* aTransferableDataOrError
) {
119 auto destroySoon
= [&] {
120 // Delete this actor, but don't do it in the middle of this sync IPC call
121 // Make sure nothing else gets processed before this deletion, so use
122 // DispatchDirectTaskToCurrentThread()
123 RefPtr
<nsIRunnable
> task
= NS_NewRunnableFunction(
124 "ClipboardReadRequestParent_SyncError", [self
= RefPtr
{this}]() {
125 Unused
<< PClipboardReadRequestParent::Send__delete__(self
);
127 nsThreadManager::get().DispatchDirectTaskToCurrentThread(task
);
131 if (NS_FAILED(mClipboardDataSnapshot
->GetValid(&valid
)) || !valid
) {
133 *aTransferableDataOrError
= NS_ERROR_NOT_AVAILABLE
;
137 // Create transferable
138 auto result
= CreateTransferable(aFlavors
);
139 if (result
.isErr()) {
140 *aTransferableDataOrError
= result
.unwrapErr();
144 nsCOMPtr
<nsITransferable
> trans
= result
.unwrap();
145 nsresult rv
= mClipboardDataSnapshot
->GetDataSync(trans
);
147 *aTransferableDataOrError
= rv
;
148 if (NS_FAILED(mClipboardDataSnapshot
->GetValid(&valid
)) || !valid
) {
153 dom::IPCTransferableData ipcTransferableData
;
154 nsContentUtils::TransferableToIPCTransferableData(
155 trans
, &ipcTransferableData
, true /* aInSyncMessage */, mManager
);
156 *aTransferableDataOrError
= std::move(ipcTransferableData
);
160 } // namespace mozilla