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_FileReader_h 8 #define mozilla_dom_FileReader_h 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/DOMEventTargetHelper.h" 12 13 #include "nsIAsyncInputStream.h" 14 #include "nsIInterfaceRequestor.h" 15 #include "nsINamed.h" 16 #include "nsCOMPtr.h" 17 #include "nsString.h" 18 #include "nsWeakReference.h" 19 20 #define NS_PROGRESS_EVENT_INTERVAL 50 21 22 class nsITimer; 23 class nsIEventTarget; 24 25 namespace mozilla { 26 namespace dom { 27 28 class Blob; 29 class DOMException; 30 class OwningStringOrArrayBuffer; 31 class StrongWorkerRef; 32 class WeakWorkerRef; 33 34 extern const uint64_t kUnknownSize; 35 36 class FileReaderDecreaseBusyCounter; 37 38 // 26a79031-c94b-47e9-850a-f04fe17bc026 39 #define FILEREADER_ID \ 40 { \ 41 0x26a79031, 0xc94b, 0x47e9, { \ 42 0x85, 0x0a, 0xf0, 0x4f, 0xe1, 0x7b, 0xc0, 0x26 \ 43 } \ 44 } 45 46 class FileReader final : public DOMEventTargetHelper, 47 public nsIInterfaceRequestor, 48 public nsSupportsWeakReference, 49 public nsIInputStreamCallback, 50 public nsITimerCallback, 51 public nsINamed { 52 friend class FileReaderDecreaseBusyCounter; 53 54 public: 55 FileReader(nsIGlobalObject* aGlobal, WeakWorkerRef* aWorkerRef); 56 57 NS_DECL_ISUPPORTS_INHERITED 58 59 NS_DECL_NSITIMERCALLBACK 60 NS_DECL_NSIINPUTSTREAMCALLBACK 61 NS_DECL_NSIINTERFACEREQUESTOR 62 NS_DECL_NSINAMED 63 64 NS_DECLARE_STATIC_IID_ACCESSOR(FILEREADER_ID) 65 66 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(FileReader, 67 DOMEventTargetHelper) 68 69 virtual JSObject* WrapObject(JSContext* aCx, 70 JS::Handle<JSObject*> aGivenProto) override; 71 72 // WebIDL 73 static already_AddRefed<FileReader> Constructor(const GlobalObject& aGlobal); ReadAsArrayBuffer(JSContext * aCx,Blob & aBlob,ErrorResult & aRv)74 void ReadAsArrayBuffer(JSContext* aCx, Blob& aBlob, ErrorResult& aRv) { 75 ReadFileContent(aBlob, EmptyString(), FILE_AS_ARRAYBUFFER, aRv); 76 } 77 ReadAsText(Blob & aBlob,const Optional<nsAString> & aLabel,ErrorResult & aRv)78 void ReadAsText(Blob& aBlob, const Optional<nsAString>& aLabel, 79 ErrorResult& aRv) { 80 if (aLabel.WasPassed()) { 81 ReadFileContent(aBlob, aLabel.Value(), FILE_AS_TEXT, aRv); 82 } else { 83 ReadFileContent(aBlob, EmptyString(), FILE_AS_TEXT, aRv); 84 } 85 } 86 ReadAsDataURL(Blob & aBlob,ErrorResult & aRv)87 void ReadAsDataURL(Blob& aBlob, ErrorResult& aRv) { 88 ReadFileContent(aBlob, EmptyString(), FILE_AS_DATAURL, aRv); 89 } 90 91 void Abort(); 92 ReadyState()93 uint16_t ReadyState() const { return static_cast<uint16_t>(mReadyState); } 94 GetError()95 DOMException* GetError() const { return mError; } 96 97 void GetResult(JSContext* aCx, Nullable<OwningStringOrArrayBuffer>& aResult); 98 99 IMPL_EVENT_HANDLER(loadstart) IMPL_EVENT_HANDLER(progress)100 IMPL_EVENT_HANDLER(progress) 101 IMPL_EVENT_HANDLER(load) 102 IMPL_EVENT_HANDLER(abort) 103 IMPL_EVENT_HANDLER(error) 104 IMPL_EVENT_HANDLER(loadend) 105 106 void ReadAsBinaryString(Blob& aBlob, ErrorResult& aRv) { 107 ReadFileContent(aBlob, EmptyString(), FILE_AS_BINARY, aRv); 108 } 109 110 enum eDataFormat { 111 FILE_AS_ARRAYBUFFER, 112 FILE_AS_BINARY, 113 FILE_AS_TEXT, 114 FILE_AS_DATAURL 115 }; 116 DataFormat()117 eDataFormat DataFormat() const { return mDataFormat; } Result()118 const nsString& Result() const { return mResult; } 119 120 private: 121 virtual ~FileReader(); 122 123 // This must be in sync with dom/webidl/FileReader.webidl 124 enum eReadyState { EMPTY = 0, LOADING = 1, DONE = 2 }; 125 126 void RootResultArrayBuffer(); 127 128 void ReadFileContent(Blob& aBlob, const nsAString& aCharset, 129 eDataFormat aDataFormat, ErrorResult& aRv); 130 nsresult GetAsText(Blob* aBlob, const nsACString& aCharset, 131 const char* aFileData, uint32_t aDataLen, 132 nsAString& aResult); 133 nsresult GetAsDataURL(Blob* aBlob, const char* aFileData, uint32_t aDataLen, 134 nsAString& aResult); 135 136 void OnLoadEnd(nsresult aStatus); 137 138 void StartProgressEventTimer(); 139 void ClearProgressEventTimer(); 140 141 void FreeDataAndDispatchSuccess(); 142 void FreeDataAndDispatchError(); 143 void FreeDataAndDispatchError(nsresult aRv); 144 nsresult DispatchProgressEvent(const nsAString& aType); 145 146 nsresult DoAsyncWait(); 147 nsresult DoReadData(uint64_t aCount); 148 149 void OnLoadEndArrayBuffer(); 150 151 void FreeFileData(); 152 153 nsresult IncreaseBusyCounter(); 154 void DecreaseBusyCounter(); 155 156 void Shutdown(); 157 158 char* mFileData; 159 RefPtr<Blob> mBlob; 160 nsCString mCharset; 161 uint32_t mDataLen; 162 163 eDataFormat mDataFormat; 164 165 nsString mResult; 166 167 JS::Heap<JSObject*> mResultArrayBuffer; 168 169 nsCOMPtr<nsITimer> mProgressNotifier; 170 bool mProgressEventWasDelayed; 171 bool mTimerIsActive; 172 173 nsCOMPtr<nsIAsyncInputStream> mAsyncStream; 174 175 RefPtr<DOMException> mError; 176 177 eReadyState mReadyState; 178 179 uint64_t mTotal; 180 uint64_t mTransferred; 181 182 nsCOMPtr<nsIEventTarget> mTarget; 183 184 uint64_t mBusyCount; 185 186 // This is set if FileReader is created on workers, but it is null if the 187 // worker is shutting down. The null value is checked in ReadFileContent() 188 // before starting any reading. 189 RefPtr<WeakWorkerRef> mWeakWorkerRef; 190 191 // This value is set when the reading starts in order to keep the worker alive 192 // during the process. 193 RefPtr<StrongWorkerRef> mStrongWorkerRef; 194 }; 195 196 NS_DEFINE_STATIC_IID_ACCESSOR(FileReader, FILEREADER_ID) 197 198 } // namespace dom 199 } // namespace mozilla 200 201 #endif // mozilla_dom_FileReader_h 202