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"
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
;
29 namespace mozilla::dom
{
31 } // namespace mozilla::dom
34 * A base clipboard class for all platform, so that they can share the same
37 class nsBaseClipboard
: public nsIClipboard
{
39 explicit nsBaseClipboard(
40 const mozilla::dom::ClipboardCapabilities
& aClipboardCaps
);
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
;
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
{
90 explicit ClipboardPopulatedDataSnapshot(nsITransferable
* aTransferable
);
93 NS_DECL_NSICLIPBOARDDATASNAPSHOT
95 virtual ~ClipboardPopulatedDataSnapshot() = default;
96 nsCOMPtr
<nsITransferable
> mTransferable
;
97 // List of available data types for clipboard content.
98 nsTArray
<nsCString
> mFlavors
;
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
);
123 void RejectPendingAsyncSetDataRequestIfAny(ClipboardType aClipboardType
);
125 class AsyncSetClipboardData final
: public nsIAsyncSetClipboardData
{
128 NS_DECL_NSIASYNCSETCLIPBOARDDATA
130 AsyncSetClipboardData(nsIClipboard::ClipboardType aClipboardType
,
131 nsBaseClipboard
* aClipboard
,
132 mozilla::dom::WindowContext
* aRequestingWindowContext
,
133 nsIAsyncClipboardRequestCallback
* aCallback
);
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
);
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
{
158 ClipboardDataSnapshot(
159 nsIClipboard::ClipboardType aClipboardType
, int32_t aSequenceNumber
,
160 nsTArray
<nsCString
>&& aFlavors
, bool aFromCache
,
161 nsBaseClipboard
* aClipboard
,
162 mozilla::dom::WindowContext
* aRequestingWindowContext
);
165 NS_DECL_NSICLIPBOARDDATASNAPSHOT
168 virtual ~ClipboardDataSnapshot() = default;
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
{
190 // In order to notify the old clipboard owner.
195 * Clear the cached transferable and notify the original clipboard owner
196 * that it has lost ownership.
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.
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;
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
>
257 const mozilla::dom::ClipboardCapabilities mClipboardCaps
;
258 bool mIgnoreEmptyNotification
= false;
261 #endif // nsBaseClipboard_h__