Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / widget / nsBaseClipboard.h
blobf3d14c1602e5a6e9d785a07aa408473e5c3ee4ee
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"
15 #include "nsCOMPtr.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;
25 class nsIPrincipal;
26 class nsIWidget;
28 namespace mozilla::dom {
29 class WindowContext;
30 } // namespace mozilla::dom
32 /**
33 * A base clipboard class for all platform, so that they can share the same
34 * implementation.
36 class nsBaseClipboard : public nsIClipboard {
37 public:
38 explicit nsBaseClipboard(
39 const mozilla::dom::ClipboardCapabilities& aClipboardCaps);
41 // nsISupports
42 NS_DECL_ISUPPORTS
44 // nsIClipboard
45 NS_IMETHOD SetData(
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;
53 NS_IMETHOD GetData(
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);
84 protected:
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);
106 private:
107 void RejectPendingAsyncSetDataRequestIfAny(int32_t aClipboardType);
109 class AsyncSetClipboardData final : public nsIAsyncSetClipboardData {
110 public:
111 NS_DECL_ISUPPORTS
112 NS_DECL_NSIASYNCSETCLIPBOARDDATA
114 AsyncSetClipboardData(int32_t aClipboardType, nsBaseClipboard* aClipboard,
115 mozilla::dom::WindowContext* aRequestingWindowContext,
116 nsIAsyncClipboardRequestCallback* aCallback);
118 private:
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);
123 return !!mClipboard;
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 {
140 public:
141 AsyncGetClipboardData(
142 int32_t aClipboardType, int32_t aSequenceNumber,
143 nsTArray<nsCString>&& aFlavors, bool aFromCache,
144 nsBaseClipboard* aClipboard,
145 mozilla::dom::WindowContext* aRequestingWindowContext);
147 NS_DECL_ISUPPORTS
148 NS_DECL_NSIASYNCGETCLIPBOARDDATA
150 private:
151 virtual ~AsyncGetClipboardData() = default;
152 bool IsValid();
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 {
171 public:
172 ~ClipboardCache() {
173 // In order to notify the old clipboard owner.
174 Clear();
178 * Clear the cached transferable and notify the original clipboard owner
179 * that it has lost ownership.
181 void Clear();
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.
186 Clear();
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;
198 private:
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__