ClipboardItem.h (4623B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_ClipboardItem_h_ 8 #define mozilla_dom_ClipboardItem_h_ 9 10 #include "mozilla/MozPromise.h" 11 #include "mozilla/dom/Blob.h" 12 #include "mozilla/dom/ClipboardBinding.h" 13 #include "mozilla/dom/PromiseNativeHandler.h" 14 #include "nsIClipboard.h" 15 #include "nsWrapperCache.h" 16 17 class nsITransferable; 18 19 namespace mozilla::dom { 20 21 struct ClipboardItemOptions; 22 template <typename KeyType, typename ValueType> 23 class Record; 24 class Promise; 25 26 class ClipboardItem final : public nsWrapperCache { 27 public: 28 class ItemEntry final : public PromiseNativeHandler, 29 public nsIAsyncClipboardRequestCallback { 30 public: 31 using GetDataPromise = 32 MozPromise<OwningStringOrBlob, nsresult, /* IsExclusive = */ true>; 33 34 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 35 NS_DECL_NSIASYNCCLIPBOARDREQUESTCALLBACK 36 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ItemEntry, PromiseNativeHandler) 37 38 explicit ItemEntry(nsIGlobalObject* aGlobal, const nsAString& aType) 39 : mGlobal(aGlobal), mType(aType) { 40 MOZ_ASSERT(mGlobal); 41 } 42 ItemEntry(nsIGlobalObject* aGlobal, const nsAString& aType, 43 const nsAString& aData) 44 : ItemEntry(aGlobal, aType) { 45 mLoadResult.emplace(NS_OK); 46 mData.SetAsString() = aData; 47 } 48 49 // PromiseNativeHandler 50 void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue, 51 ErrorResult& aRv) override; 52 void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue, 53 ErrorResult& aRv) override; 54 55 const nsString& Type() const { return mType; } 56 RefPtr<GetDataPromise> GetData(); 57 58 // Load data from system clipboard. 59 void LoadDataFromSystemClipboard(nsIClipboardDataSnapshot* aDataGetter); 60 void LoadDataFromDataPromise(Promise& aDataPromise); 61 62 // If clipboard data is in the process of loading from either system 63 // clipboard or data promise, add `aPromise` to the pending list which will 64 // be resolved/rejected later when process is finished. Otherwise, 65 // resolve/reject `aPromise` based on cached result and data. 66 void ReactGetTypePromise(Promise& aPromise); 67 68 private: 69 ~ItemEntry() { 70 if (!mPendingGetDataRequests.IsEmpty()) { 71 RejectPendingPromises(NS_ERROR_FAILURE); 72 } 73 }; 74 75 void MaybeResolveGetTypePromise(const OwningStringOrBlob& aData, 76 Promise& aPromise); 77 void MaybeResolvePendingPromises(OwningStringOrBlob&& aData); 78 void RejectPendingPromises(nsresult rv); 79 80 nsCOMPtr<nsIGlobalObject> mGlobal; 81 82 // MIME type of this entry. 83 nsString mType; 84 85 // Cache the loading result. 86 OwningStringOrBlob mData; 87 Maybe<nsresult> mLoadResult; 88 89 // Indicates if the data is still being loaded. 90 bool mIsLoadingData = false; 91 nsCOMPtr<nsITransferable> mTransferable; 92 93 // Pending promises for data retrieval requests. 94 nsTArray<MozPromiseHolder<GetDataPromise>> mPendingGetDataRequests; 95 nsTArray<RefPtr<Promise>> mPendingGetTypeRequests; 96 }; 97 98 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ClipboardItem) 99 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(ClipboardItem) 100 101 ClipboardItem(nsISupports* aOwner, dom::PresentationStyle aPresentationStyle, 102 nsTArray<RefPtr<ItemEntry>>&& aItems); 103 104 static already_AddRefed<ClipboardItem> Constructor( 105 const GlobalObject& aGlobal, 106 const Record<nsString, OwningNonNull<Promise>>& aItems, 107 const ClipboardItemOptions& aOptions, ErrorResult& aRv); 108 109 static bool Supports(const GlobalObject& aGlobal, const nsAString& aType); 110 111 dom::PresentationStyle PresentationStyle() const { 112 return mPresentationStyle; 113 }; 114 void GetTypes(nsTArray<nsString>& aTypes) const; 115 116 already_AddRefed<Promise> GetType(const nsAString& aType, ErrorResult& aRv); 117 118 nsISupports* GetParentObject() const { return mOwner; } 119 120 JSObject* WrapObject(JSContext* aCx, 121 JS::Handle<JSObject*> aGivenProto) override; 122 123 const nsTArray<RefPtr<ItemEntry>>& Entries() const { return mItems; } 124 125 private: 126 ~ClipboardItem() = default; 127 128 nsCOMPtr<nsISupports> mOwner; 129 dom::PresentationStyle mPresentationStyle; 130 nsTArray<RefPtr<ItemEntry>> mItems; 131 }; 132 133 } // namespace mozilla::dom 134 135 #endif // mozilla_dom_ClipboardItem_h_