Bug 1832850 - Part 3: Remove an unnecessary include and some unnecessary forward...
[gecko.git] / widget / nsBaseClipboard.cpp
blob5b1e4399d41f3d4452951f8936134c1924e10889
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;
15 NS_IMPL_ISUPPORTS(ClipboardSetDataHelper::AsyncSetClipboardData,
16 nsIAsyncSetClipboardData)
18 ClipboardSetDataHelper::AsyncSetClipboardData::AsyncSetClipboardData(
19 int32_t aClipboardType, ClipboardSetDataHelper* aClipboard,
20 nsIAsyncSetClipboardDataCallback* aCallback)
21 : mClipboardType(aClipboardType),
22 mClipboard(aClipboard),
23 mCallback(aCallback) {
24 MOZ_ASSERT(mClipboard);
25 MOZ_ASSERT(mClipboard->IsClipboardTypeSupported(mClipboardType));
28 NS_IMETHODIMP
29 ClipboardSetDataHelper::AsyncSetClipboardData::SetData(
30 nsITransferable* aTransferable, nsIClipboardOwner* aOwner) {
31 if (!IsValid()) {
32 return NS_ERROR_FAILURE;
35 MOZ_ASSERT(mClipboard);
36 MOZ_ASSERT(mClipboard->IsClipboardTypeSupported(mClipboardType));
37 MOZ_DIAGNOSTIC_ASSERT(mClipboard->mPendingWriteRequests[mClipboardType] ==
38 this);
40 RefPtr<AsyncSetClipboardData> request =
41 std::move(mClipboard->mPendingWriteRequests[mClipboardType]);
42 nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType);
43 MaybeNotifyCallback(rv);
45 return rv;
48 NS_IMETHODIMP
49 ClipboardSetDataHelper::AsyncSetClipboardData::Abort(nsresult aReason) {
50 // Note: This may be called during destructor, so it should not attempt to
51 // take a reference to mClipboard.
53 if (!IsValid() || !NS_FAILED(aReason)) {
54 return NS_ERROR_FAILURE;
57 MaybeNotifyCallback(aReason);
58 return NS_OK;
61 void ClipboardSetDataHelper::AsyncSetClipboardData::MaybeNotifyCallback(
62 nsresult aResult) {
63 // Note: This may be called during destructor, so it should not attempt to
64 // take a reference to mClipboard.
66 MOZ_ASSERT(IsValid());
67 if (nsCOMPtr<nsIAsyncSetClipboardDataCallback> callback =
68 mCallback.forget()) {
69 callback->OnComplete(aResult);
71 // Once the callback is notified, setData should not be allowed, so invalidate
72 // this request.
73 mClipboard = nullptr;
76 NS_IMPL_ISUPPORTS(ClipboardSetDataHelper, nsIClipboard)
78 ClipboardSetDataHelper::~ClipboardSetDataHelper() {
79 for (auto& request : mPendingWriteRequests) {
80 if (request) {
81 request->Abort(NS_ERROR_ABORT);
82 request = nullptr;
87 void ClipboardSetDataHelper::RejectPendingAsyncSetDataRequestIfAny(
88 int32_t aClipboardType) {
89 MOZ_ASSERT(nsIClipboard::IsClipboardTypeSupported(aClipboardType));
90 auto& request = mPendingWriteRequests[aClipboardType];
91 if (request) {
92 request->Abort(NS_ERROR_ABORT);
93 request = nullptr;
97 NS_IMETHODIMP
98 ClipboardSetDataHelper::SetData(nsITransferable* aTransferable,
99 nsIClipboardOwner* aOwner,
100 int32_t aWhichClipboard) {
101 NS_ENSURE_ARG(aTransferable);
102 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
103 return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
106 // Reject existing pending asyncSetData request if any.
107 RejectPendingAsyncSetDataRequestIfAny(aWhichClipboard);
109 return SetNativeClipboardData(aTransferable, aOwner, aWhichClipboard);
112 NS_IMETHODIMP ClipboardSetDataHelper::AsyncSetData(
113 int32_t aWhichClipboard, nsIAsyncSetClipboardDataCallback* aCallback,
114 nsIAsyncSetClipboardData** _retval) {
115 *_retval = nullptr;
116 if (!nsIClipboard::IsClipboardTypeSupported(aWhichClipboard)) {
117 return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
120 // Reject existing pending AsyncSetData request if any.
121 RejectPendingAsyncSetDataRequestIfAny(aWhichClipboard);
123 // Create a new AsyncSetClipboardData.
124 RefPtr<AsyncSetClipboardData> request =
125 mozilla::MakeRefPtr<AsyncSetClipboardData>(aWhichClipboard, this,
126 aCallback);
127 mPendingWriteRequests[aWhichClipboard] = request;
128 request.forget(_retval);
129 return NS_OK;
132 nsBaseClipboard::nsBaseClipboard() : mEmptyingForSetData(false) {}
134 nsBaseClipboard::~nsBaseClipboard() {
135 EmptyClipboard(kSelectionClipboard);
136 EmptyClipboard(kGlobalClipboard);
137 EmptyClipboard(kFindClipboard);
140 NS_IMPL_ISUPPORTS_INHERITED0(nsBaseClipboard, ClipboardSetDataHelper)
143 * Sets the transferable object
146 NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable,
147 nsIClipboardOwner* anOwner,
148 int32_t aWhichClipboard) {
149 NS_ASSERTION(aTransferable, "clipboard given a null transferable");
151 CLIPBOARD_LOG("%s", __FUNCTION__);
153 if (aTransferable == mTransferable && anOwner == mClipboardOwner) {
154 CLIPBOARD_LOG("%s: skipping update.", __FUNCTION__);
155 return NS_OK;
158 if (!nsIClipboard::IsClipboardTypeSupported(kSelectionClipboard) &&
159 !nsIClipboard::IsClipboardTypeSupported(kFindClipboard) &&
160 aWhichClipboard != kGlobalClipboard) {
161 return NS_ERROR_FAILURE;
164 mEmptyingForSetData = true;
165 if (NS_FAILED(EmptyClipboard(aWhichClipboard))) {
166 CLIPBOARD_LOG("%s: emptying clipboard failed.", __FUNCTION__);
168 mEmptyingForSetData = false;
170 mClipboardOwner = anOwner;
171 mTransferable = aTransferable;
173 nsresult rv = NS_ERROR_FAILURE;
174 if (mTransferable) {
175 mIgnoreEmptyNotification = true;
176 rv = ClipboardSetDataHelper::SetData(aTransferable, anOwner,
177 aWhichClipboard);
178 mIgnoreEmptyNotification = false;
180 if (NS_FAILED(rv)) {
181 CLIPBOARD_LOG("%s: setting native clipboard data failed.", __FUNCTION__);
184 return rv;
188 * Gets the transferable object
191 NS_IMETHODIMP nsBaseClipboard::GetData(nsITransferable* aTransferable,
192 int32_t aWhichClipboard) {
193 NS_ASSERTION(aTransferable, "clipboard given a null transferable");
195 CLIPBOARD_LOG("%s", __FUNCTION__);
197 if (!nsIClipboard::IsClipboardTypeSupported(kSelectionClipboard) &&
198 !nsIClipboard::IsClipboardTypeSupported(kFindClipboard) &&
199 aWhichClipboard != kGlobalClipboard) {
200 return NS_ERROR_FAILURE;
203 if (aTransferable)
204 return GetNativeClipboardData(aTransferable, aWhichClipboard);
206 return NS_ERROR_FAILURE;
209 RefPtr<GenericPromise> nsBaseClipboard::AsyncGetData(
210 nsITransferable* aTransferable, int32_t aWhichClipboard) {
211 nsresult rv = GetData(aTransferable, aWhichClipboard);
212 if (NS_FAILED(rv)) {
213 return GenericPromise::CreateAndReject(rv, __func__);
216 return GenericPromise::CreateAndResolve(true, __func__);
219 NS_IMETHODIMP nsBaseClipboard::EmptyClipboard(int32_t aWhichClipboard) {
220 CLIPBOARD_LOG("%s: clipboard=%i", __FUNCTION__, aWhichClipboard);
222 if (!nsIClipboard::IsClipboardTypeSupported(kSelectionClipboard) &&
223 !nsIClipboard::IsClipboardTypeSupported(kFindClipboard) &&
224 aWhichClipboard != kGlobalClipboard) {
225 return NS_ERROR_FAILURE;
228 if (mIgnoreEmptyNotification) {
229 MOZ_DIAGNOSTIC_ASSERT(false, "How did we get here?");
230 return NS_OK;
233 ClearClipboardCache();
234 return NS_OK;
237 NS_IMETHODIMP
238 nsBaseClipboard::HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
239 int32_t aWhichClipboard,
240 bool* outResult) {
241 *outResult = true; // say we always do.
242 return NS_OK;
245 RefPtr<DataFlavorsPromise> nsBaseClipboard::AsyncHasDataMatchingFlavors(
246 const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) {
247 nsTArray<nsCString> results;
248 for (const auto& flavor : aFlavorList) {
249 bool hasMatchingFlavor = false;
250 nsresult rv = HasDataMatchingFlavors(AutoTArray<nsCString, 1>{flavor},
251 aWhichClipboard, &hasMatchingFlavor);
252 if (NS_SUCCEEDED(rv) && hasMatchingFlavor) {
253 results.AppendElement(flavor);
257 return DataFlavorsPromise::CreateAndResolve(std::move(results), __func__);
260 NS_IMETHODIMP
261 nsBaseClipboard::IsClipboardTypeSupported(int32_t aWhichClipboard,
262 bool* _retval) {
263 NS_ENSURE_ARG_POINTER(_retval);
264 // We support global clipboard by default.
265 *_retval = kGlobalClipboard == aWhichClipboard;
266 return NS_OK;
269 void nsBaseClipboard::ClearClipboardCache() {
270 if (mClipboardOwner) {
271 mClipboardOwner->LosingOwnership(mTransferable);
272 mClipboardOwner = nullptr;
274 mTransferable = nullptr;