GetFilesHelper.h (4955B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_GetFilesHelper_h 8 #define mozilla_dom_GetFilesHelper_h 9 10 #include "mozilla/MozPromise.h" 11 #include "mozilla/Mutex.h" 12 #include "mozilla/RefPtr.h" 13 #include "nsCycleCollectionTraversalCallback.h" 14 #include "nsTArray.h" 15 #include "nsThreadUtils.h" 16 17 class nsIGlobalObject; 18 19 namespace mozilla { 20 class ErrorResult; 21 22 namespace dom { 23 24 class BlobImpl; 25 class ContentParent; 26 class File; 27 class GetFilesHelperParent; 28 class OwningFileOrDirectory; 29 class Promise; 30 31 class GetFilesCallback { 32 public: 33 NS_INLINE_DECL_REFCOUNTING(GetFilesCallback); 34 35 // This is called once per directory scan and is passed an array of all 36 // of the files found. 37 virtual void Callback(nsresult aStatus, 38 const FallibleTArray<RefPtr<BlobImpl>>& aBlobImpls) = 0; 39 40 protected: 41 virtual ~GetFilesCallback() = default; 42 }; 43 44 class GetFilesHelperBase { 45 protected: 46 explicit GetFilesHelperBase(bool aRecursiveFlag) 47 : mRecursiveFlag(aRecursiveFlag) {} 48 49 virtual ~GetFilesHelperBase() = default; 50 51 virtual bool IsCanceled() { return false; } 52 53 nsresult ExploreDirectory(const nsAString& aDOMPath, nsIFile* aFile); 54 55 bool mRecursiveFlag; 56 57 // We populate this array in the I/O thread with the BlobImpl. 58 FallibleTArray<RefPtr<BlobImpl>> mTargetBlobImplArray; 59 }; 60 61 // Retrieving the list of files can be very time/IO consuming. We use this 62 // helper class to do it just once. 63 class GetFilesHelper : public Runnable, public GetFilesHelperBase { 64 friend class GetFilesHelperParent; 65 class ReleaseRunnable; 66 67 public: 68 static already_AddRefed<GetFilesHelper> Create( 69 const nsTArray<OwningFileOrDirectory>& aFilesOrDirectory, 70 bool aRecursiveFlag, ErrorResult& aRv); 71 72 void AddPromise(Promise* aPromise); 73 74 void AddCallback(GetFilesCallback* aCallback); 75 76 using MozPromiseType = 77 MozPromise<nsTArray<RefPtr<File>>, nsresult, true>::Private; 78 void AddMozPromise(MozPromiseType* aPromise, nsIGlobalObject* aGlobal); 79 80 // CC methods 81 void Unlink(); 82 void Traverse(nsCycleCollectionTraversalCallback& cb); 83 84 protected: 85 explicit GetFilesHelper(bool aRecursiveFlag); 86 87 virtual ~GetFilesHelper(); 88 89 void SetDirectoryPaths(nsTArray<nsString>&& aDirectoryPaths) { 90 mDirectoryPaths = std::move(aDirectoryPaths); 91 } 92 93 virtual bool IsCanceled() override { 94 MutexAutoLock lock(mMutex); 95 return mCanceled; 96 } 97 98 virtual void Work(ErrorResult& aRv); 99 100 virtual void Cancel() {}; 101 102 NS_IMETHOD 103 Run() override; 104 105 void RunIO(); 106 107 void OperationCompleted(); 108 109 struct MozPromiseAndGlobal { 110 RefPtr<MozPromiseType> mMozPromise; 111 RefPtr<nsIGlobalObject> mGlobal; 112 }; 113 114 class PromiseAdapter { 115 public: 116 explicit PromiseAdapter(MozPromiseAndGlobal&& aMozPromise); 117 explicit PromiseAdapter(Promise* aDomPromise); 118 ~PromiseAdapter(); 119 120 void Clear(); 121 void Traverse(nsCycleCollectionTraversalCallback& cb); 122 123 nsIGlobalObject* GetGlobalObject(); 124 void Resolve(nsTArray<RefPtr<File>>&& aFiles); 125 void Reject(nsresult aError); 126 127 private: 128 using PromiseVariant = Variant<RefPtr<Promise>, MozPromiseAndGlobal>; 129 PromiseVariant mPromise; 130 }; 131 132 void AddPromiseInternal(PromiseAdapter&& aPromise); 133 void ResolveOrRejectPromise(PromiseAdapter&& aPromise); 134 135 void RunCallback(GetFilesCallback* aCallback); 136 137 bool mListingCompleted; 138 nsTArray<nsString> mDirectoryPaths; 139 140 // Error code to propagate. 141 nsresult mErrorResult; 142 143 nsTArray<PromiseAdapter> mPromises; 144 145 nsTArray<RefPtr<GetFilesCallback>> mCallbacks; 146 147 Mutex mMutex MOZ_UNANNOTATED; 148 149 // This variable is protected by mutex. 150 bool mCanceled; 151 }; 152 153 class GetFilesHelperChild final : public GetFilesHelper { 154 public: 155 explicit GetFilesHelperChild(bool aRecursiveFlag) 156 : GetFilesHelper(aRecursiveFlag), mPendingOperation(false) {} 157 158 virtual void Work(ErrorResult& aRv) override; 159 160 virtual void Cancel() override; 161 162 bool AppendBlobImpl(BlobImpl* aBlobImpl); 163 164 void Finished(nsresult aResult); 165 166 private: 167 nsID mUUID; 168 bool mPendingOperation; 169 }; 170 171 class GetFilesHelperParentCallback; 172 173 class GetFilesHelperParent final : public GetFilesHelper { 174 friend class GetFilesHelperParentCallback; 175 176 public: 177 static already_AddRefed<GetFilesHelperParent> Create( 178 const nsID& aUUID, nsTArray<nsString>&& aDirectoryPaths, 179 bool aRecursiveFlag, ContentParent* aContentParent, ErrorResult& aRv); 180 181 private: 182 GetFilesHelperParent(const nsID& aUUID, ContentParent* aContentParent, 183 bool aRecursiveFlag); 184 185 ~GetFilesHelperParent(); 186 187 RefPtr<ContentParent> mContentParent; 188 nsID mUUID; 189 }; 190 191 } // namespace dom 192 } // namespace mozilla 193 194 #endif // mozilla_dom_GetFilesHelper_h