Bug 1942006 - Upstream a variety of Servo-specific code from Servo's downstream fork...
[gecko.git] / widget / nsBaseClipboard.h
blob9d2ea396cfc511f1794d29cb523351a5a3fd1402
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 #ifndef nsBaseClipboard_h__
7 #define nsBaseClipboard_h__
9 #include "mozilla/Array.h"
10 #include "mozilla/dom/PContent.h"
11 #include "mozilla/Logging.h"
12 #include "mozilla/MoveOnlyFunction.h"
13 #include "mozilla/Result.h"
14 #include "nsIClipboard.h"
15 #include "nsITransferable.h"
16 #include "nsCOMPtr.h"
18 extern mozilla::LazyLogModule gWidgetClipboardLog;
19 #define MOZ_CLIPBOARD_LOG(...) \
20 MOZ_LOG(gWidgetClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
21 #define MOZ_CLIPBOARD_LOG_ENABLED() \
22 MOZ_LOG_TEST(gWidgetClipboardLog, mozilla::LogLevel::Debug)
24 class nsITransferable;
25 class nsIClipboardOwner;
26 class nsIPrincipal;
27 class nsIWidget;
29 namespace mozilla::dom {
30 class WindowContext;
31 } // namespace mozilla::dom
33 /**
34 * A base clipboard class for all platform, so that they can share the same
35 * implementation.
37 class nsBaseClipboard : public nsIClipboard {
38 public:
39 explicit nsBaseClipboard(
40 const mozilla::dom::ClipboardCapabilities& aClipboardCaps);
42 // nsISupports
43 NS_DECL_ISUPPORTS
45 // nsIClipboard
46 NS_IMETHOD SetData(
47 nsITransferable* aTransferable, nsIClipboardOwner* aOwner,
48 ClipboardType aWhichClipboard,
49 mozilla::dom::WindowContext* aWindowContext) override final;
50 NS_IMETHOD AsyncSetData(ClipboardType aWhichClipboard,
51 mozilla::dom::WindowContext* aSettingWindowContext,
52 nsIAsyncClipboardRequestCallback* aCallback,
53 nsIAsyncSetClipboardData** _retval) override final;
54 NS_IMETHOD GetData(
55 nsITransferable* aTransferable, ClipboardType aWhichClipboard,
56 mozilla::dom::WindowContext* aWindowContext) override final;
57 NS_IMETHOD GetDataSnapshot(
58 const nsTArray<nsCString>& aFlavorList, ClipboardType aWhichClipboard,
59 mozilla::dom::WindowContext* aRequestingWindowContext,
60 nsIPrincipal* aRequestingPrincipal,
61 nsIClipboardGetDataSnapshotCallback* aCallback) override final;
62 NS_IMETHOD GetDataSnapshotSync(
63 const nsTArray<nsCString>& aFlavorList, ClipboardType aWhichClipboard,
64 mozilla::dom::WindowContext* aRequestingWindowContext,
65 nsIClipboardDataSnapshot** _retval) override final;
66 NS_IMETHOD EmptyClipboard(ClipboardType aWhichClipboard) override final;
67 NS_IMETHOD HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
68 ClipboardType aWhichClipboard,
69 bool* aOutResult) override final;
70 NS_IMETHOD IsClipboardTypeSupported(ClipboardType aWhichClipboard,
71 bool* aRetval) override final;
73 void GetDataSnapshotInternal(
74 const nsTArray<nsCString>& aFlavorList,
75 nsIClipboard::ClipboardType aClipboardType,
76 mozilla::dom::WindowContext* aRequestingWindowContext,
77 nsIClipboardGetDataSnapshotCallback* aCallback);
79 using GetDataCallback = mozilla::MoveOnlyFunction<void(nsresult)>;
80 using HasMatchingFlavorsCallback = mozilla::MoveOnlyFunction<void(
81 mozilla::Result<nsTArray<nsCString>, nsresult>)>;
83 mozilla::Maybe<uint64_t> GetClipboardCacheInnerWindowId(
84 ClipboardType aClipboardType);
85 virtual mozilla::Result<int32_t, nsresult> GetNativeClipboardSequenceNumber(
86 ClipboardType aWhichClipboard) = 0;
88 class ClipboardPopulatedDataSnapshot final : public nsIClipboardDataSnapshot {
89 public:
90 explicit ClipboardPopulatedDataSnapshot(nsITransferable* aTransferable);
92 NS_DECL_ISUPPORTS
93 NS_DECL_NSICLIPBOARDDATASNAPSHOT
94 private:
95 virtual ~ClipboardPopulatedDataSnapshot() = default;
96 nsCOMPtr<nsITransferable> mTransferable;
97 // List of available data types for clipboard content.
98 nsTArray<nsCString> mFlavors;
101 protected:
102 virtual ~nsBaseClipboard();
104 // Implement the native clipboard behavior.
105 NS_IMETHOD SetNativeClipboardData(nsITransferable* aTransferable,
106 ClipboardType aWhichClipboard) = 0;
107 NS_IMETHOD GetNativeClipboardData(nsITransferable* aTransferable,
108 ClipboardType aWhichClipboard) = 0;
109 virtual void AsyncGetNativeClipboardData(nsITransferable* aTransferable,
110 ClipboardType aWhichClipboard,
111 GetDataCallback&& aCallback);
112 virtual nsresult EmptyNativeClipboardData(ClipboardType aWhichClipboard) = 0;
113 virtual mozilla::Result<bool, nsresult> HasNativeClipboardDataMatchingFlavors(
114 const nsTArray<nsCString>& aFlavorList,
115 ClipboardType aWhichClipboard) = 0;
116 virtual void AsyncHasNativeClipboardDataMatchingFlavors(
117 const nsTArray<nsCString>& aFlavorList, ClipboardType aWhichClipboard,
118 HasMatchingFlavorsCallback&& aCallback);
120 void ClearClipboardCache(ClipboardType aClipboardType);
122 private:
123 void RejectPendingAsyncSetDataRequestIfAny(ClipboardType aClipboardType);
125 class AsyncSetClipboardData final : public nsIAsyncSetClipboardData {
126 public:
127 NS_DECL_ISUPPORTS
128 NS_DECL_NSIASYNCSETCLIPBOARDDATA
130 AsyncSetClipboardData(nsIClipboard::ClipboardType aClipboardType,
131 nsBaseClipboard* aClipboard,
132 mozilla::dom::WindowContext* aRequestingWindowContext,
133 nsIAsyncClipboardRequestCallback* aCallback);
135 private:
136 virtual ~AsyncSetClipboardData() = default;
137 bool IsValid() const {
138 // If this request is no longer valid, the callback should be notified.
139 MOZ_ASSERT_IF(!mClipboard, !mCallback);
140 return !!mClipboard;
142 void MaybeNotifyCallback(nsresult aResult);
144 // The clipboard type defined in nsIClipboard.
145 nsIClipboard::ClipboardType mClipboardType;
146 // It is safe to use a raw pointer as it will be nullified (by calling
147 // NotifyCallback()) once nsBaseClipboard stops tracking us. This is
148 // also used to indicate whether this request is valid.
149 nsBaseClipboard* mClipboard;
150 RefPtr<mozilla::dom::WindowContext> mWindowContext;
151 // mCallback will be nullified once the callback is notified to ensure the
152 // callback is only notified once.
153 nsCOMPtr<nsIAsyncClipboardRequestCallback> mCallback;
156 class ClipboardDataSnapshot final : public nsIClipboardDataSnapshot {
157 public:
158 ClipboardDataSnapshot(
159 nsIClipboard::ClipboardType aClipboardType, int32_t aSequenceNumber,
160 nsTArray<nsCString>&& aFlavors, bool aFromCache,
161 nsBaseClipboard* aClipboard,
162 mozilla::dom::WindowContext* aRequestingWindowContext);
164 NS_DECL_ISUPPORTS
165 NS_DECL_NSICLIPBOARDDATASNAPSHOT
167 private:
168 virtual ~ClipboardDataSnapshot() = default;
169 bool IsValid();
171 // The clipboard type defined in nsIClipboard.
172 const nsIClipboard::ClipboardType mClipboardType;
173 // The sequence number associated with the clipboard content for this
174 // request. If it doesn't match with the current sequence number in system
175 // clipboard, this request targets stale data and is deemed invalid.
176 const int32_t mSequenceNumber;
177 // List of available data types for clipboard content.
178 const nsTArray<nsCString> mFlavors;
179 // Data should be read from cache.
180 const bool mFromCache;
181 // This is also used to indicate whether this request is still valid.
182 RefPtr<nsBaseClipboard> mClipboard;
183 // The requesting window, which is used for Content Analysis purposes.
184 RefPtr<mozilla::dom::WindowContext> mRequestingWindowContext;
187 class ClipboardCache final {
188 public:
189 ~ClipboardCache() {
190 // In order to notify the old clipboard owner.
191 Clear();
195 * Clear the cached transferable and notify the original clipboard owner
196 * that it has lost ownership.
198 void Clear();
199 void Update(nsITransferable* aTransferable,
200 nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber,
201 mozilla::Maybe<uint64_t> aInnerWindowId) {
202 // Clear first to notify the old clipboard owner.
203 Clear();
204 mTransferable = aTransferable;
205 mClipboardOwner = aClipboardOwner;
206 mSequenceNumber = aSequenceNumber;
207 mInnerWindowId = aInnerWindowId;
209 nsITransferable* GetTransferable() const { return mTransferable; }
210 nsIClipboardOwner* GetClipboardOwner() const { return mClipboardOwner; }
211 int32_t GetSequenceNumber() const { return mSequenceNumber; }
212 mozilla::Maybe<uint64_t> GetInnerWindowId() const { return mInnerWindowId; }
213 nsresult GetData(nsITransferable* aTransferable) const;
215 private:
216 nsCOMPtr<nsITransferable> mTransferable;
217 nsCOMPtr<nsIClipboardOwner> mClipboardOwner;
218 int32_t mSequenceNumber = -1;
219 mozilla::Maybe<uint64_t> mInnerWindowId;
222 void MaybeRetryGetAvailableFlavors(
223 const nsTArray<nsCString>& aFlavorList,
224 nsIClipboard::ClipboardType aWhichClipboard,
225 nsIClipboardGetDataSnapshotCallback* aCallback, int32_t aRetryCount,
226 mozilla::dom::WindowContext* aRequestingWindowContext);
228 // Return clipboard cache if the cached data is valid, otherwise clear the
229 // cached data and returns null.
230 ClipboardCache* GetClipboardCacheIfValid(ClipboardType aClipboardType);
232 mozilla::Result<nsTArray<nsCString>, nsresult> GetFlavorsFromClipboardCache(
233 ClipboardType aClipboardType);
234 nsresult GetDataFromClipboardCache(nsITransferable* aTransferable,
235 ClipboardType aClipboardType);
236 void RequestUserConfirmation(ClipboardType aClipboardType,
237 const nsTArray<nsCString>& aFlavorList,
238 mozilla::dom::WindowContext* aWindowContext,
239 nsIPrincipal* aRequestingPrincipal,
240 nsIClipboardGetDataSnapshotCallback* aCallback);
242 already_AddRefed<nsIClipboardDataSnapshot>
243 MaybeCreateGetRequestFromClipboardCache(
244 const nsTArray<nsCString>& aFlavorList, ClipboardType aClipboardType,
245 mozilla::dom::WindowContext* aRequestingWindowContext);
247 // Track the pending request for each clipboard type separately. And only need
248 // to track the latest request for each clipboard type as the prior pending
249 // request will be canceled when a new request is made.
250 mozilla::Array<RefPtr<AsyncSetClipboardData>,
251 nsIClipboard::kClipboardTypeCount>
252 mPendingWriteRequests;
254 mozilla::Array<mozilla::UniquePtr<ClipboardCache>,
255 nsIClipboard::kClipboardTypeCount>
256 mCaches;
257 const mozilla::dom::ClipboardCapabilities mClipboardCaps;
258 bool mIgnoreEmptyNotification = false;
261 #endif // nsBaseClipboard_h__