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/contentanalysis/ContentAnalysisIPCTypes.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 "nsIContentAnalysis.h"
16 #include "nsITransferable.h"
19 static mozilla::LazyLogModule
sWidgetClipboardLog("WidgetClipboard");
20 #define MOZ_CLIPBOARD_LOG(...) \
21 MOZ_LOG(sWidgetClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
22 #define MOZ_CLIPBOARD_LOG_ENABLED() \
23 MOZ_LOG_TEST(sWidgetClipboardLog, mozilla::LogLevel::Debug)
25 class nsITransferable
;
26 class nsIClipboardOwner
;
30 namespace mozilla::dom
{
32 } // namespace mozilla::dom
35 * A base clipboard class for all platform, so that they can share the same
38 class nsBaseClipboard
: public nsIClipboard
{
40 explicit nsBaseClipboard(
41 const mozilla::dom::ClipboardCapabilities
& aClipboardCaps
);
48 nsITransferable
* aTransferable
, nsIClipboardOwner
* aOwner
,
49 int32_t aWhichClipboard
,
50 mozilla::dom::WindowContext
* aWindowContext
) override final
;
51 NS_IMETHOD
AsyncSetData(int32_t aWhichClipboard
,
52 mozilla::dom::WindowContext
* aSettingWindowContext
,
53 nsIAsyncClipboardRequestCallback
* aCallback
,
54 nsIAsyncSetClipboardData
** _retval
) override final
;
56 nsITransferable
* aTransferable
, int32_t aWhichClipboard
,
57 mozilla::dom::WindowContext
* aWindowContext
) override final
;
58 NS_IMETHOD
AsyncGetData(
59 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
60 mozilla::dom::WindowContext
* aRequestingWindowContext
,
61 nsIPrincipal
* aRequestingPrincipal
,
62 nsIAsyncClipboardGetCallback
* aCallback
) override final
;
63 NS_IMETHOD
GetDataSnapshotSync(
64 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
65 mozilla::dom::WindowContext
* aRequestingWindowContext
,
66 nsIAsyncGetClipboardData
** _retval
) override final
;
67 NS_IMETHOD
EmptyClipboard(int32_t aWhichClipboard
) override final
;
68 NS_IMETHOD
HasDataMatchingFlavors(const nsTArray
<nsCString
>& aFlavorList
,
69 int32_t aWhichClipboard
,
70 bool* aOutResult
) override final
;
71 NS_IMETHOD
IsClipboardTypeSupported(int32_t aWhichClipboard
,
72 bool* aRetval
) override final
;
74 void AsyncGetDataInternal(
75 const nsTArray
<nsCString
>& aFlavorList
, int32_t aClipboardType
,
76 mozilla::dom::WindowContext
* aRequestingWindowContext
,
77 nsIAsyncClipboardGetCallback
* aCallback
);
79 using GetDataCallback
= mozilla::MoveOnlyFunction
<void(nsresult
)>;
80 using HasMatchingFlavorsCallback
= mozilla::MoveOnlyFunction
<void(
81 mozilla::Result
<nsTArray
<nsCString
>, nsresult
>)>;
84 virtual ~nsBaseClipboard();
86 // Implement the native clipboard behavior.
87 NS_IMETHOD
SetNativeClipboardData(nsITransferable
* aTransferable
,
88 int32_t aWhichClipboard
) = 0;
89 NS_IMETHOD
GetNativeClipboardData(nsITransferable
* aTransferable
,
90 int32_t aWhichClipboard
) = 0;
91 virtual void AsyncGetNativeClipboardData(nsITransferable
* aTransferable
,
92 int32_t aWhichClipboard
,
93 GetDataCallback
&& aCallback
);
94 virtual nsresult
EmptyNativeClipboardData(int32_t aWhichClipboard
) = 0;
95 virtual mozilla::Result
<int32_t, nsresult
> GetNativeClipboardSequenceNumber(
96 int32_t aWhichClipboard
) = 0;
97 virtual mozilla::Result
<bool, nsresult
> HasNativeClipboardDataMatchingFlavors(
98 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
) = 0;
99 virtual void AsyncHasNativeClipboardDataMatchingFlavors(
100 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
101 HasMatchingFlavorsCallback
&& aCallback
);
103 void ClearClipboardCache(int32_t aClipboardType
);
106 void RejectPendingAsyncSetDataRequestIfAny(int32_t aClipboardType
);
108 class AsyncSetClipboardData final
: public nsIAsyncSetClipboardData
{
111 NS_DECL_NSIASYNCSETCLIPBOARDDATA
113 AsyncSetClipboardData(int32_t aClipboardType
, nsBaseClipboard
* aClipboard
,
114 mozilla::dom::WindowContext
* aRequestingWindowContext
,
115 nsIAsyncClipboardRequestCallback
* aCallback
);
118 virtual ~AsyncSetClipboardData() = default;
119 bool IsValid() const {
120 // If this request is no longer valid, the callback should be notified.
121 MOZ_ASSERT_IF(!mClipboard
, !mCallback
);
124 void MaybeNotifyCallback(nsresult aResult
);
126 // The clipboard type defined in nsIClipboard.
127 int32_t mClipboardType
;
128 // It is safe to use a raw pointer as it will be nullified (by calling
129 // NotifyCallback()) once nsBaseClipboard stops tracking us. This is
130 // also used to indicate whether this request is valid.
131 nsBaseClipboard
* mClipboard
;
132 RefPtr
<mozilla::dom::WindowContext
> mWindowContext
;
133 // mCallback will be nullified once the callback is notified to ensure the
134 // callback is only notified once.
135 nsCOMPtr
<nsIAsyncClipboardRequestCallback
> mCallback
;
138 class AsyncGetClipboardData final
: public nsIAsyncGetClipboardData
{
140 AsyncGetClipboardData(
141 int32_t aClipboardType
, int32_t aSequenceNumber
,
142 nsTArray
<nsCString
>&& aFlavors
, bool aFromCache
,
143 nsBaseClipboard
* aClipboard
,
144 mozilla::dom::WindowContext
* aRequestingWindowContext
);
147 NS_DECL_NSIASYNCGETCLIPBOARDDATA
150 virtual ~AsyncGetClipboardData() = default;
153 // The clipboard type defined in nsIClipboard.
154 const int32_t mClipboardType
;
155 // The sequence number associated with the clipboard content for this
156 // request. If it doesn't match with the current sequence number in system
157 // clipboard, this request targets stale data and is deemed invalid.
158 const int32_t mSequenceNumber
;
159 // List of available data types for clipboard content.
160 const nsTArray
<nsCString
> mFlavors
;
161 // Data should be read from cache.
162 const bool mFromCache
;
163 // This is also used to indicate whether this request is still valid.
164 RefPtr
<nsBaseClipboard
> mClipboard
;
165 // The requesting window, which is used for Content Analysis purposes.
166 RefPtr
<mozilla::dom::WindowContext
> mRequestingWindowContext
;
169 class ClipboardCache final
{
172 // In order to notify the old clipboard owner.
177 * Clear the cached transferable and notify the original clipboard owner
178 * that it has lost ownership.
181 void Update(nsITransferable
* aTransferable
,
182 nsIClipboardOwner
* aClipboardOwner
, int32_t aSequenceNumber
,
183 mozilla::Maybe
<uint64_t> aInnerWindowId
) {
184 // Clear first to notify the old clipboard owner.
186 mTransferable
= aTransferable
;
187 mClipboardOwner
= aClipboardOwner
;
188 mSequenceNumber
= aSequenceNumber
;
189 mInnerWindowId
= aInnerWindowId
;
191 nsITransferable
* GetTransferable() const { return mTransferable
; }
192 nsIClipboardOwner
* GetClipboardOwner() const { return mClipboardOwner
; }
193 int32_t GetSequenceNumber() const { return mSequenceNumber
; }
194 mozilla::Maybe
<uint64_t> GetInnerWindowId() const { return mInnerWindowId
; }
195 nsresult
GetData(nsITransferable
* aTransferable
) const;
198 nsCOMPtr
<nsITransferable
> mTransferable
;
199 nsCOMPtr
<nsIClipboardOwner
> mClipboardOwner
;
200 int32_t mSequenceNumber
= -1;
201 mozilla::Maybe
<uint64_t> mInnerWindowId
;
204 class SafeContentAnalysisResultCallback final
205 : public nsIContentAnalysisCallback
{
207 explicit SafeContentAnalysisResultCallback(
208 std::function
<void(RefPtr
<nsIContentAnalysisResult
>&&)> aResolver
)
209 : mResolver(std::move(aResolver
)) {}
210 void Callback(RefPtr
<nsIContentAnalysisResult
>&& aResult
) {
211 MOZ_ASSERT(mResolver
, "Called SafeContentAnalysisResultCallback twice!");
212 if (auto resolver
= std::move(mResolver
)) {
213 resolver(std::move(aResult
));
217 NS_IMETHODIMP
ContentResult(
218 nsIContentAnalysisResponse
* aResponse
) override
{
219 using namespace mozilla::contentanalysis
;
220 RefPtr
<ContentAnalysisResult
> result
=
221 ContentAnalysisResult::FromContentAnalysisResponse(aResponse
);
226 NS_IMETHODIMP
Error(nsresult aError
) override
{
227 using namespace mozilla::contentanalysis
;
228 Callback(ContentAnalysisResult::FromNoResult(
229 NoContentAnalysisResult::DENY_DUE_TO_OTHER_ERROR
));
233 NS_DECL_THREADSAFE_ISUPPORTS
235 ~SafeContentAnalysisResultCallback() {
236 MOZ_ASSERT(!mResolver
, "SafeContentAnalysisResultCallback never called!");
238 mozilla::MoveOnlyFunction
<void(RefPtr
<nsIContentAnalysisResult
>&&)>
242 void MaybeRetryGetAvailableFlavors(
243 const nsTArray
<nsCString
>& aFlavorList
, int32_t aWhichClipboard
,
244 nsIAsyncClipboardGetCallback
* aCallback
, int32_t aRetryCount
,
245 mozilla::dom::WindowContext
* aRequestingWindowContext
);
247 // Return clipboard cache if the cached data is valid, otherwise clear the
248 // cached data and returns null.
249 ClipboardCache
* GetClipboardCacheIfValid(int32_t aClipboardType
);
251 mozilla::Result
<nsTArray
<nsCString
>, nsresult
> GetFlavorsFromClipboardCache(
252 int32_t aClipboardType
);
253 nsresult
GetDataFromClipboardCache(nsITransferable
* aTransferable
,
254 int32_t aClipboardType
);
255 bool CheckClipboardContentAnalysisSync(
256 mozilla::dom::WindowGlobalParent
* aWindow
,
257 const nsCOMPtr
<nsITransferable
>& trans
, int32_t aClipboardType
);
258 void CheckClipboardContentAnalysis(
259 mozilla::dom::WindowGlobalParent
* aWindow
, nsITransferable
* aTransferable
,
260 int32_t aClipboardType
, SafeContentAnalysisResultCallback
* aResolver
);
261 // - true means a content analysis request was fired
262 // - false means there is no text data in the transferable
263 // - NoContentAnalysisResult means there was an error
264 using ClipboardContentAnalysisResult
=
265 mozilla::Result
<bool, mozilla::contentanalysis::NoContentAnalysisResult
>;
266 ClipboardContentAnalysisResult
CheckClipboardContentAnalysisAsText(
267 uint64_t aInnerWindowId
, SafeContentAnalysisResultCallback
* aResolver
,
268 nsIURI
* aDocumentURI
, nsIContentAnalysis
* aContentAnalysis
,
269 nsITransferable
* aTextTrans
);
270 ClipboardContentAnalysisResult
CheckClipboardContentAnalysisAsFile(
271 uint64_t aInnerWindowId
, SafeContentAnalysisResultCallback
* aResolver
,
272 nsIURI
* aDocumentURI
, nsIContentAnalysis
* aContentAnalysis
,
273 nsITransferable
* aFileTrans
);
275 void RequestUserConfirmation(int32_t aClipboardType
,
276 const nsTArray
<nsCString
>& aFlavorList
,
277 mozilla::dom::WindowContext
* aWindowContext
,
278 nsIPrincipal
* aRequestingPrincipal
,
279 nsIAsyncClipboardGetCallback
* aCallback
);
281 already_AddRefed
<nsIAsyncGetClipboardData
>
282 MaybeCreateGetRequestFromClipboardCache(
283 const nsTArray
<nsCString
>& aFlavorList
, int32_t aClipboardType
,
284 mozilla::dom::WindowContext
* aRequestingWindowContext
);
286 // Track the pending request for each clipboard type separately. And only need
287 // to track the latest request for each clipboard type as the prior pending
288 // request will be canceled when a new request is made.
289 RefPtr
<AsyncSetClipboardData
>
290 mPendingWriteRequests
[nsIClipboard::kClipboardTypeCount
];
292 mozilla::UniquePtr
<ClipboardCache
> mCaches
[nsIClipboard::kClipboardTypeCount
];
293 const mozilla::dom::ClipboardCapabilities mClipboardCaps
;
294 bool mIgnoreEmptyNotification
= false;
297 #endif // nsBaseClipboard_h__