Bug 1835710 - Cancel off-thread JIT compilation before changing nursery allocation...
[gecko.git] / widget / nsBaseClipboard.cpp
blob1af81819ada503b1df8d8f2891f98eca34ab77fa
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 "nsBaseClipboard.h"
8 #include "nsIClipboardOwner.h"
9 #include "nsError.h"
10 #include "nsXPCOM.h"
12 using mozilla::GenericPromise;
13 using mozilla::LogLevel;
14 using mozilla::UniquePtr;
15 using mozilla::dom::ClipboardCapabilities;
17 NS_IMPL_ISUPPORTS(ClipboardSetDataHelper::AsyncSetClipboardData,
18 nsIAsyncSetClipboardData)
20 ClipboardSetDataHelper::AsyncSetClipboardData::AsyncSetClipboardData(
21 int32_t aClipboardType, ClipboardSetDataHelper* aClipboard,
22 nsIAsyncSetClipboardDataCallback* aCallback)
23 : mClipboardType(aClipboardType),
24 mClipboard(aClipboard),
25 mCallback(aCallback) {
26 MOZ_ASSERT(mClipboard);
27 MOZ_ASSERT(mClipboard->IsClipboardTypeSupported(mClipboardType));
30 NS_IMETHODIMP
31 ClipboardSetDataHelper::AsyncSetClipboardData::SetData(
32 nsITransferable* aTransferable, nsIClipboardOwner* aOwner) {
33 if (!IsValid()) {
34 return NS_ERROR_FAILURE;
37 MOZ_ASSERT(mClipboard);
38 MOZ_ASSERT(mClipboard->IsClipboardTypeSupported(mClipboardType));
39 MOZ_DIAGNOSTIC_ASSERT(mClipboard->mPendingWriteRequests[mClipboardType] ==
40 this);
42 RefPtr<AsyncSetClipboardData> request =
43 std::move(mClipboard->mPendingWriteRequests[mClipboardType]);
44 nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType);
45 MaybeNotifyCallback(rv);
47 return rv;
50 NS_IMETHODIMP
51 ClipboardSetDataHelper::AsyncSetClipboardData::Abort(nsresult aReason) {
52 // Note: This may be called during destructor, so it should not attempt to
53 // take a reference to mClipboard.
55 if (!IsValid() || !NS_FAILED(aReason)) {
56 return NS_ERROR_FAILURE;
59 MaybeNotifyCallback(aReason);
60 return NS_OK;
63 void ClipboardSetDataHelper::AsyncSetClipboardData::MaybeNotifyCallback(
64 nsresult aResult) {
65 // Note: This may be called during destructor, so it should not attempt to
66 // take a reference to mClipboard.
68 MOZ_ASSERT(IsValid());
69 if (nsCOMPtr<nsIAsyncSetClipboardDataCallback> callback =
70 mCallback.forget()) {
71 callback->OnComplete(aResult);
73 // Once the callback is notified, setData should not be allowed, so invalidate
74 // this request.
75 mClipboard = nullptr;
78 NS_IMPL_ISUPPORTS(ClipboardSetDataHelper, nsIClipboard)
80 ClipboardSetDataHelper::~ClipboardSetDataHelper() {
81 for (auto& request : mPendingWriteRequests) {
82 if (request) {
83 request->Abort(NS_ERROR_ABORT);
84 request = nullptr;
89 void ClipboardSetDataHelper::RejectPendingAsyncSetDataRequestIfAny(
90 int32_t aClipboardType) {
91 MOZ_ASSERT(nsIClipboard::IsClipboardTypeSupported(aClipboardType));
92 auto& request = mPendingWriteRequests[aClipboardType];
93 if (request) {
94 request->Abort(NS_ERROR_ABORT);
95 request = nullptr;
99 NS_IMETHODIMP
100 ClipboardSetDataHelper::SetData(nsITransferable* aTransferable,
101 nsIClipboardOwner* aOwner,
102 int32_t aWhichClipboard) {
103 NS_ENSURE_ARG(aTransferable);
104 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
105 return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
108 // Reject existing pending asyncSetData request if any.
109 RejectPendingAsyncSetDataRequestIfAny(aWhichClipboard);
111 return SetNativeClipboardData(aTransferable, aOwner, aWhichClipboard);
114 NS_IMETHODIMP ClipboardSetDataHelper::AsyncSetData(
115 int32_t aWhichClipboard, nsIAsyncSetClipboardDataCallback* aCallback,
116 nsIAsyncSetClipboardData** _retval) {
117 *_retval = nullptr;
118 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
119 return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
122 // Reject existing pending AsyncSetData request if any.
123 RejectPendingAsyncSetDataRequestIfAny(aWhichClipboard);
125 // Create a new AsyncSetClipboardData.
126 RefPtr<AsyncSetClipboardData> request =
127 mozilla::MakeRefPtr<AsyncSetClipboardData>(aWhichClipboard, this,
128 aCallback);
129 mPendingWriteRequests[aWhichClipboard] = request;
130 request.forget(_retval);
131 return NS_OK;
134 nsBaseClipboard::nsBaseClipboard(const ClipboardCapabilities& aClipboardCaps)
135 : mClipboardCaps(aClipboardCaps) {
136 using mozilla::MakeUnique;
137 // Initialize clipboard cache.
138 mCaches[kGlobalClipboard] = MakeUnique<ClipboardCache>();
139 if (mClipboardCaps.supportsSelectionClipboard()) {
140 mCaches[kSelectionClipboard] = MakeUnique<ClipboardCache>();
142 if (mClipboardCaps.supportsFindClipboard()) {
143 mCaches[kFindClipboard] = MakeUnique<ClipboardCache>();
145 if (mClipboardCaps.supportsSelectionCache()) {
146 mCaches[kSelectionCache] = MakeUnique<ClipboardCache>();
150 NS_IMPL_ISUPPORTS_INHERITED0(nsBaseClipboard, ClipboardSetDataHelper)
153 * Sets the transferable object
156 NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable,
157 nsIClipboardOwner* anOwner,
158 int32_t aWhichClipboard) {
159 NS_ASSERTION(aTransferable, "clipboard given a null transferable");
161 CLIPBOARD_LOG("%s", __FUNCTION__);
163 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
164 return NS_ERROR_FAILURE;
167 const auto& clipboardCache = mCaches[aWhichClipboard];
168 MOZ_ASSERT(clipboardCache);
169 if (aTransferable == clipboardCache->GetTransferable() &&
170 anOwner == clipboardCache->GetClipboardOwner()) {
171 CLIPBOARD_LOG("%s: skipping update.", __FUNCTION__);
172 return NS_OK;
175 mEmptyingForSetData = true;
176 if (NS_FAILED(EmptyClipboard(aWhichClipboard))) {
177 CLIPBOARD_LOG("%s: emptying clipboard failed.", __FUNCTION__);
179 mEmptyingForSetData = false;
181 clipboardCache->Update(aTransferable, anOwner);
183 nsresult rv = NS_ERROR_FAILURE;
184 if (aTransferable) {
185 mIgnoreEmptyNotification = true;
186 rv = ClipboardSetDataHelper::SetData(aTransferable, anOwner,
187 aWhichClipboard);
188 mIgnoreEmptyNotification = false;
190 if (NS_FAILED(rv)) {
191 CLIPBOARD_LOG("%s: setting native clipboard data failed.", __FUNCTION__);
194 return rv;
198 * Gets the transferable object
201 NS_IMETHODIMP nsBaseClipboard::GetData(nsITransferable* aTransferable,
202 int32_t aWhichClipboard) {
203 NS_ASSERTION(aTransferable, "clipboard given a null transferable");
205 CLIPBOARD_LOG("%s", __FUNCTION__);
207 if (!nsIClipboard::IsClipboardTypeSupported(kSelectionClipboard) &&
208 !nsIClipboard::IsClipboardTypeSupported(kFindClipboard) &&
209 aWhichClipboard != kGlobalClipboard) {
210 return NS_ERROR_FAILURE;
213 if (aTransferable)
214 return GetNativeClipboardData(aTransferable, aWhichClipboard);
216 return NS_ERROR_FAILURE;
219 RefPtr<GenericPromise> nsBaseClipboard::AsyncGetData(
220 nsITransferable* aTransferable, int32_t aWhichClipboard) {
221 nsresult rv = GetData(aTransferable, aWhichClipboard);
222 if (NS_FAILED(rv)) {
223 return GenericPromise::CreateAndReject(rv, __func__);
226 return GenericPromise::CreateAndResolve(true, __func__);
229 NS_IMETHODIMP nsBaseClipboard::EmptyClipboard(int32_t aWhichClipboard) {
230 CLIPBOARD_LOG("%s: clipboard=%i", __FUNCTION__, aWhichClipboard);
232 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
233 return NS_ERROR_FAILURE;
236 if (mIgnoreEmptyNotification) {
237 MOZ_DIAGNOSTIC_ASSERT(false, "How did we get here?");
238 return NS_OK;
241 const auto& clipboardCache = mCaches[aWhichClipboard];
242 MOZ_ASSERT(clipboardCache);
243 clipboardCache->Clear();
245 return NS_OK;
248 NS_IMETHODIMP
249 nsBaseClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
250 int32_t aWhichClipboard,
251 bool* outResult) {
252 *outResult = true; // say we always do.
253 return NS_OK;
256 RefPtr<DataFlavorsPromise> nsBaseClipboard::AsyncHasDataMatchingFlavors(
257 const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) {
258 nsTArray<nsCString> results;
259 for (const auto& flavor : aFlavorList) {
260 bool hasMatchingFlavor = false;
261 nsresult rv = HasDataMatchingFlavors(AutoTArray<nsCString, 1>{flavor},
262 aWhichClipboard, &hasMatchingFlavor);
263 if (NS_SUCCEEDED(rv) && hasMatchingFlavor) {
264 results.AppendElement(flavor);
268 return DataFlavorsPromise::CreateAndResolve(std::move(results), __func__);
271 NS_IMETHODIMP
272 nsBaseClipboard::IsClipboardTypeSupported(int32_t aWhichClipboard,
273 bool* aRetval) {
274 NS_ENSURE_ARG_POINTER(aRetval);
275 switch (aWhichClipboard) {
276 case kGlobalClipboard:
277 // We always support the global clipboard.
278 *aRetval = true;
279 return NS_OK;
280 case kSelectionClipboard:
281 *aRetval = mClipboardCaps.supportsSelectionClipboard();
282 return NS_OK;
283 case kFindClipboard:
284 *aRetval = mClipboardCaps.supportsFindClipboard();
285 return NS_OK;
286 case kSelectionCache:
287 *aRetval = mClipboardCaps.supportsSelectionCache();
288 return NS_OK;
289 default:
290 *aRetval = false;
291 return NS_OK;
295 void nsBaseClipboard::ClipboardCache::Clear() {
296 if (mClipboardOwner) {
297 mClipboardOwner->LosingOwnership(mTransferable);
298 mClipboardOwner = nullptr;
300 mTransferable = nullptr;