diff options
Diffstat (limited to 'dom/file/FileReader.h')
-rw-r--r-- | dom/file/FileReader.h | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/dom/file/FileReader.h b/dom/file/FileReader.h new file mode 100644 index 0000000000..1c07b6193f --- /dev/null +++ b/dom/file/FileReader.h @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FileReader_h +#define mozilla_dom_FileReader_h + +#include "mozilla/Attributes.h" +#include "mozilla/DOMEventTargetHelper.h" + +#include "nsIAsyncInputStream.h" +#include "nsIInterfaceRequestor.h" +#include "nsINamed.h" +#include "nsITimer.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsWeakReference.h" + +#define NS_PROGRESS_EVENT_INTERVAL 50 + +class nsITimer; +class nsIEventTarget; + +namespace mozilla::dom { + +class Blob; +class DOMException; +class OwningStringOrArrayBuffer; +class StrongWorkerRef; +class WeakWorkerRef; + +extern const uint64_t kUnknownSize; + +class FileReaderDecreaseBusyCounter; + +// 26a79031-c94b-47e9-850a-f04fe17bc026 +#define FILEREADER_ID \ + { \ + 0x26a79031, 0xc94b, 0x47e9, { \ + 0x85, 0x0a, 0xf0, 0x4f, 0xe1, 0x7b, 0xc0, 0x26 \ + } \ + } + +class FileReader final : public DOMEventTargetHelper, + public nsIInterfaceRequestor, + public nsSupportsWeakReference, + public nsIInputStreamCallback, + public nsITimerCallback, + public nsINamed { + friend class FileReaderDecreaseBusyCounter; + + public: + FileReader(nsIGlobalObject* aGlobal, WeakWorkerRef* aWorkerRef); + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_NSITIMERCALLBACK + NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSINAMED + + NS_DECLARE_STATIC_IID_ACCESSOR(FILEREADER_ID) + + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(FileReader, + DOMEventTargetHelper) + + JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + + // WebIDL + static already_AddRefed<FileReader> Constructor(const GlobalObject& aGlobal); + void ReadAsArrayBuffer(JSContext* aCx, Blob& aBlob, ErrorResult& aRv) { + ReadFileContent(aBlob, u""_ns, FILE_AS_ARRAYBUFFER, aRv); + } + + void ReadAsText(Blob& aBlob, const Optional<nsAString>& aLabel, + ErrorResult& aRv) { + if (aLabel.WasPassed()) { + ReadFileContent(aBlob, aLabel.Value(), FILE_AS_TEXT, aRv); + } else { + ReadFileContent(aBlob, u""_ns, FILE_AS_TEXT, aRv); + } + } + + void ReadAsDataURL(Blob& aBlob, ErrorResult& aRv) { + ReadFileContent(aBlob, u""_ns, FILE_AS_DATAURL, aRv); + } + + void Abort(); + + uint16_t ReadyState() const { return static_cast<uint16_t>(mReadyState); } + + DOMException* GetError() const { return mError; } + + void GetResult(JSContext* aCx, Nullable<OwningStringOrArrayBuffer>& aResult); + + IMPL_EVENT_HANDLER(loadstart) + IMPL_EVENT_HANDLER(progress) + IMPL_EVENT_HANDLER(load) + IMPL_EVENT_HANDLER(abort) + IMPL_EVENT_HANDLER(error) + IMPL_EVENT_HANDLER(loadend) + + void ReadAsBinaryString(Blob& aBlob, ErrorResult& aRv) { + ReadFileContent(aBlob, u""_ns, FILE_AS_BINARY, aRv); + } + + enum eDataFormat { + FILE_AS_ARRAYBUFFER, + FILE_AS_BINARY, + FILE_AS_TEXT, + FILE_AS_DATAURL + }; + + eDataFormat DataFormat() const { return mDataFormat; } + const nsString& Result() const { return mResult; } + + void InitialAsyncWait(); + + private: + ~FileReader() override; + + // This must be in sync with dom/webidl/FileReader.webidl + enum eReadyState { EMPTY = 0, LOADING = 1, DONE = 2 }; + + void RootResultArrayBuffer(); + + void ReadFileContent(Blob& aBlob, const nsAString& aCharset, + eDataFormat aDataFormat, ErrorResult& aRv); + nsresult GetAsText(Blob* aBlob, const nsACString& aCharset, + const char* aFileData, uint32_t aDataLen, + nsAString& aResult); + nsresult GetAsDataURL(Blob* aBlob, const char* aFileData, uint32_t aDataLen, + nsAString& aResult); + + void OnLoadEnd(nsresult aStatus); + + void StartProgressEventTimer(); + void ClearProgressEventTimer(); + + void FreeDataAndDispatchSuccess(); + void FreeDataAndDispatchError(); + void FreeDataAndDispatchError(nsresult aRv); + nsresult DispatchProgressEvent(const nsAString& aType); + + nsresult DoAsyncWait(); + nsresult DoReadData(uint64_t aCount); + + void OnLoadEndArrayBuffer(); + + void FreeFileData(); + + nsresult IncreaseBusyCounter(); + void DecreaseBusyCounter(); + + void Cleanup(); + void Shutdown(); + + char* mFileData; + RefPtr<Blob> mBlob; + nsCString mCharset; + uint32_t mDataLen; + + eDataFormat mDataFormat; + + nsString mResult; + + JS::Heap<JSObject*> mResultArrayBuffer; + + nsCOMPtr<nsITimer> mProgressNotifier; + bool mProgressEventWasDelayed; + bool mTimerIsActive; + + nsCOMPtr<nsIAsyncInputStream> mAsyncStream; + + RefPtr<DOMException> mError; + + eReadyState mReadyState; + + uint64_t mTotal; + uint64_t mTransferred; + + nsCOMPtr<nsIEventTarget> mTarget; + + uint64_t mBusyCount; + + // This is set if FileReader is created on workers, but it is null if the + // worker is shutting down. The null value is checked in ReadFileContent() + // before starting any reading. + RefPtr<WeakWorkerRef> mWeakWorkerRef; + + // This value is set when the reading starts in order to keep the worker alive + // during the process. + RefPtr<StrongWorkerRef> mStrongWorkerRef; + + // Runnable to start the reading asynchronous. + class AsyncWaitRunnable; + RefPtr<AsyncWaitRunnable> mAsyncWaitRunnable; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(FileReader, FILEREADER_ID) + +} // namespace mozilla::dom + +#endif // mozilla_dom_FileReader_h |