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/dom/PContent.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/MoveOnlyFunction.h"
12 #include "mozilla/Result.h"
13 #include "nsIClipboard.h"
14 #include "nsITransferable.h"
17 static mozilla::LazyLogModule
sWidgetClipboardLog("WidgetClipboard");
18 #define MOZ_CLIPBOARD_LOG(...) \
19 MOZ_LOG(sWidgetClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
20 #define MOZ_CLIPBOARD_LOG_ENABLED() \
21 MOZ_LOG_TEST(sWidgetClipboardLog, mozilla::LogLevel::Debug)
23 class nsITransferable
;
24 class nsIClipboardOwner
;
28 namespace mozilla::dom
{
30 } // namespace mozilla::dom
33 * A base clipboard class for all platform, so that they can share the same
36 class nsBaseClipboard
: public nsIClipboard
{
38 explicit nsBaseClipboard(
39 const mozilla::dom::ClipboardCapabilities
& aClipboardCaps
);
46 nsITransferable
* aTransferable
, nsIClipboardOwner
* aOwner
,
47 int32_t aWhichClipboard
,
48 mozilla::dom::WindowContext
* aWindowContext
) override final
;
49 NS_IMETHOD
AsyncSetData(int32_t aWhichClipboard
,
50 mozilla::dom::WindowContext
* aSettingWindowContext
,
51 nsIAsyncClipboardRequestCallback
* aCallback
,
52 nsIAsyncSetClipboardData
** _retval
) override final
;
54 nsITransferable
* aTransferable
, int32_t aWhichClipboard
,
55 mozilla::dom::WindowContext
* aWindowContext
) override final
;
56 NS_IMETHOD
AsyncGetData(
57 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
58 mozilla::dom::WindowContext
* aRequestingWindowContext
,
59 nsIPrincipal
* aRequestingPrincipal
,
60 nsIAsyncClipboardGetCallback
* aCallback
) override final
;
61 NS_IMETHOD
GetDataSnapshotSync(
62 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
63 mozilla::dom::WindowContext
* aRequestingWindowContext
,
64 nsIAsyncGetClipboardData
** _retval
) override final
;
65 NS_IMETHOD
EmptyClipboard(int32_t aWhichClipboard
) override final
;
66 NS_IMETHOD
HasDataMatchingFlavors(const nsTArray
<nsCString
>& aFlavorList
,
67 int32_t aWhichClipboard
,
68 bool* aOutResult
) override final
;
69 NS_IMETHOD
IsClipboardTypeSupported(int32_t aWhichClipboard
,
70 bool* aRetval
) override final
;
72 void AsyncGetDataInternal(
73 const nsTArray
<nsCString
>& aFlavorList
, int32_t aClipboardType
,
74 mozilla::dom::WindowContext
* aRequestingWindowContext
,
75 nsIAsyncClipboardGetCallback
* aCallback
);
77 using GetDataCallback
= mozilla::MoveOnlyFunction
<void(nsresult
)>;
78 using HasMatchingFlavorsCallback
= mozilla::MoveOnlyFunction
<void(
79 mozilla::Result
<nsTArray
<nsCString
>, nsresult
>)>;
81 mozilla::Maybe
<uint64_t> GetClipboardCacheInnerWindowId(
82 int32_t aClipboardType
);
85 virtual ~nsBaseClipboard();
87 // Implement the native clipboard behavior.
88 NS_IMETHOD
SetNativeClipboardData(nsITransferable
* aTransferable
,
89 int32_t aWhichClipboard
) = 0;
90 NS_IMETHOD
GetNativeClipboardData(nsITransferable
* aTransferable
,
91 int32_t aWhichClipboard
) = 0;
92 virtual void AsyncGetNativeClipboardData(nsITransferable
* aTransferable
,
93 int32_t aWhichClipboard
,
94 GetDataCallback
&& aCallback
);
95 virtual nsresult
EmptyNativeClipboardData(int32_t aWhichClipboard
) = 0;
96 virtual mozilla::Result
<int32_t, nsresult
> GetNativeClipboardSequenceNumber(
97 int32_t aWhichClipboard
) = 0;
98 virtual mozilla::Result
<bool, nsresult
> HasNativeClipboardDataMatchingFlavors(
99 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
) = 0;
100 virtual void AsyncHasNativeClipboardDataMatchingFlavors(
101 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
102 HasMatchingFlavorsCallback
&& aCallback
);
104 void ClearClipboardCache(int32_t aClipboardType
);
107 void RejectPendingAsyncSetDataRequestIfAny(int32_t aClipboardType
);
109 class AsyncSetClipboardData final
: public nsIAsyncSetClipboardData
{
112 NS_DECL_NSIASYNCSETCLIPBOARDDATA
114 AsyncSetClipboardData(int32_t aClipboardType
, nsBaseClipboard
* aClipboard
,
115 mozilla::dom::WindowContext
* aRequestingWindowContext
,
116 nsIAsyncClipboardRequestCallback
* aCallback
);
119 virtual ~AsyncSetClipboardData() = default;
120 bool IsValid() const {
121 // If this request is no longer valid, the callback should be notified.
122 MOZ_ASSERT_IF(!mClipboard
, !mCallback
);
125 void MaybeNotifyCallback(nsresult aResult
);
127 // The clipboard type defined in nsIClipboard.
128 int32_t mClipboardType
;
129 // It is safe to use a raw pointer as it will be nullified (by calling
130 // NotifyCallback()) once nsBaseClipboard stops tracking us. This is
131 // also used to indicate whether this request is valid.
132 nsBaseClipboard
* mClipboard
;
133 RefPtr
<mozilla::dom::WindowContext
> mWindowContext
;
134 // mCallback will be nullified once the callback is notified to ensure the
135 // callback is only notified once.
136 nsCOMPtr
<nsIAsyncClipboardRequestCallback
> mCallback
;
139 class AsyncGetClipboardData final
: public nsIAsyncGetClipboardData
{
141 AsyncGetClipboardData(
142 int32_t aClipboardType
, int32_t aSequenceNumber
,
143 nsTArray
<nsCString
>&& aFlavors
, bool aFromCache
,
144 nsBaseClipboard
* aClipboard
,
145 mozilla::dom::WindowContext
* aRequestingWindowContext
);
148 NS_DECL_NSIASYNCGETCLIPBOARDDATA
151 virtual ~AsyncGetClipboardData() = default;
154 // The clipboard type defined in nsIClipboard.
155 const int32_t mClipboardType
;
156 // The sequence number associated with the clipboard content for this
157 // request. If it doesn't match with the current sequence number in system
158 // clipboard, this request targets stale data and is deemed invalid.
159 const int32_t mSequenceNumber
;
160 // List of available data types for clipboard content.
161 const nsTArray
<nsCString
> mFlavors
;
162 // Data should be read from cache.
163 const bool mFromCache
;
164 // This is also used to indicate whether this request is still valid.
165 RefPtr
<nsBaseClipboard
> mClipboard
;
166 // The requesting window, which is used for Content Analysis purposes.
167 RefPtr
<mozilla::dom::WindowContext
> mRequestingWindowContext
;
170 class ClipboardCache final
{
173 // In order to notify the old clipboard owner.
178 * Clear the cached transferable and notify the original clipboard owner
179 * that it has lost ownership.
182 void Update(nsITransferable
* aTransferable
,
183 nsIClipboardOwner
* aClipboardOwner
, int32_t aSequenceNumber
,
184 mozilla::Maybe
<uint64_t> aInnerWindowId
) {
185 // Clear first to notify the old clipboard owner.
187 mTransferable
= aTransferable
;
188 mClipboardOwner
= aClipboardOwner
;
189 mSequenceNumber
= aSequenceNumber
;
190 mInnerWindowId
= aInnerWindowId
;
192 nsITransferable
* GetTransferable() const { return mTransferable
; }
193 nsIClipboardOwner
* GetClipboardOwner() const { return mClipboardOwner
; }
194 int32_t GetSequenceNumber() const { return mSequenceNumber
; }
195 mozilla::Maybe
<uint64_t> GetInnerWindowId() const { return mInnerWindowId
; }
196 nsresult
GetData(nsITransferable
* aTransferable
) const;
199 nsCOMPtr
<nsITransferable
> mTransferable
;
200 nsCOMPtr
<nsIClipboardOwner
> mClipboardOwner
;
201 int32_t mSequenceNumber
= -1;
202 mozilla::Maybe
<uint64_t> mInnerWindowId
;
205 void MaybeRetryGetAvailableFlavors(
206 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
207 nsIAsyncClipboardGetCallback
* aCallback
, int32_t aRetryCount
,
208 mozilla::dom::WindowContext
* aRequestingWindowContext
);
210 // Return clipboard cache if the cached data is valid, otherwise clear the
211 // cached data and returns null.
212 ClipboardCache
* GetClipboardCacheIfValid(int32_t aClipboardType
);
214 mozilla::Result
<nsTArray
<nsCString
>, nsresult
> GetFlavorsFromClipboardCache(
215 int32_t aClipboardType
);
216 nsresult
GetDataFromClipboardCache(nsITransferable
* aTransferable
,
217 int32_t aClipboardType
);
218 void RequestUserConfirmation(int32_t aClipboardType
,
219 const nsTArray
<nsCString
>& aFlavorList
,
220 mozilla::dom::WindowContext
* aWindowContext
,
221 nsIPrincipal
* aRequestingPrincipal
,
222 nsIAsyncClipboardGetCallback
* aCallback
);
224 already_AddRefed
<nsIAsyncGetClipboardData
>
225 MaybeCreateGetRequestFromClipboardCache(
226 const nsTArray
<nsCString
>& aFlavorList
, int32_t aClipboardType
,
227 mozilla::dom::WindowContext
* aRequestingWindowContext
);
229 // Track the pending request for each clipboard type separately. And only need
230 // to track the latest request for each clipboard type as the prior pending
231 // request will be canceled when a new request is made.
232 RefPtr
<AsyncSetClipboardData
>
233 mPendingWriteRequests
[nsIClipboard::kClipboardTypeCount
];
235 mozilla::UniquePtr
<ClipboardCache
> mCaches
[nsIClipboard::kClipboardTypeCount
];
236 const mozilla::dom::ClipboardCapabilities mClipboardCaps
;
237 bool mIgnoreEmptyNotification
= false;
240 #endif // nsBaseClipboard_h__