diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/base/BodyStream.h | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/base/BodyStream.h')
-rw-r--r-- | dom/base/BodyStream.h | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/dom/base/BodyStream.h b/dom/base/BodyStream.h new file mode 100644 index 0000000000..33b1166006 --- /dev/null +++ b/dom/base/BodyStream.h @@ -0,0 +1,177 @@ +/* -*- 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_BodyStream_h +#define mozilla_dom_BodyStream_h + +#include "jsapi.h" +#include "js/Stream.h" +#include "nsIAsyncInputStream.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIObserver.h" +#include "nsISupportsImpl.h" +#include "nsNetCID.h" +#include "nsWeakReference.h" +#include "mozilla/Mutex.h" + +class nsIGlobalObject; + +class nsIInputStream; + +namespace mozilla { +class ErrorResult; + +namespace dom { + +class BodyStream; +class WeakWorkerRef; + +class BodyStreamHolder : public nsISupports { + friend class BodyStream; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(BodyStreamHolder) + + BodyStreamHolder(); + + virtual void NullifyStream() = 0; + + virtual void MarkAsRead() = 0; + + virtual void SetReadableStreamBody(JSObject* aBody) = 0; + + virtual JSObject* GetReadableStreamBody() = 0; + + protected: + virtual ~BodyStreamHolder() = default; + + private: + void StoreBodyStream(BodyStream* aBodyStream); + void ForgetBodyStream(); + + // Raw pointer because BodyStream keeps BodyStreamHolder alive and it + // nullifies this stream before being released. + BodyStream* mBodyStream; + +#ifdef DEBUG + bool mStreamCreated = false; +#endif +}; + +class BodyStream final : public nsIInputStreamCallback, + public nsIObserver, + public nsSupportsWeakReference, + private JS::ReadableStreamUnderlyingSource { + friend class BodyStreamHolder; + + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSIOBSERVER + + // This method creates a JS ReadableStream object and it assigns it to the + // aStreamHolder calling SetReadableStreamBody(). + static void Create(JSContext* aCx, BodyStreamHolder* aStreamHolder, + nsIGlobalObject* aGlobal, nsIInputStream* aInputStream, + ErrorResult& aRv); + + void Close(); + + static nsresult RetrieveInputStream( + JS::ReadableStreamUnderlyingSource* aUnderlyingReadableStreamSource, + nsIInputStream** aInputStream); + + private: + BodyStream(nsIGlobalObject* aGlobal, BodyStreamHolder* aStreamHolder, + nsIInputStream* aInputStream); + ~BodyStream(); + +#ifdef DEBUG + void AssertIsOnOwningThread(); +#else + void AssertIsOnOwningThread() {} +#endif + + void requestData(JSContext* aCx, JS::HandleObject aStream, + size_t aDesiredSize) override; + + void writeIntoReadRequestBuffer(JSContext* aCx, JS::HandleObject aStream, + void* aBuffer, size_t aLength, + size_t* aBytesWritten) override; + + JS::Value cancel(JSContext* aCx, JS::HandleObject aStream, + JS::HandleValue aReason) override; + + void onClosed(JSContext* aCx, JS::HandleObject aStream) override; + + void onErrored(JSContext* aCx, JS::HandleObject aStream, + JS::HandleValue aReason) override; + + void finalize() override; + + void ErrorPropagation(JSContext* aCx, const MutexAutoLock& aProofOfLock, + JS::HandleObject aStream, nsresult aRv); + + void CloseAndReleaseObjects(JSContext* aCx, const MutexAutoLock& aProofOfLock, + JS::HandleObject aSteam); + + class WorkerShutdown; + + void ReleaseObjects(const MutexAutoLock& aProofOfLock); + + void ReleaseObjects(); + + // Common methods + + enum State { + // This is the beginning state before any reading operation. + eInitializing, + + // RequestDataCallback has not been called yet. We haven't started to read + // data from the stream yet. + eWaiting, + + // We are reading data in a separate I/O thread. + eReading, + + // We are ready to write something in the JS Buffer. + eWriting, + + // After a writing, we want to check if the stream is closed. After the + // check, we go back to eWaiting. If a reading request happens in the + // meantime, we move to eReading state. + eChecking, + + // Operation completed. + eClosed, + }; + + // We need a mutex because JS engine can release BodyStream on a non-owning + // thread. We must be sure that the releasing of resources doesn't trigger + // race conditions. + Mutex mMutex; + + // Protected by mutex. + State mState; + + nsCOMPtr<nsIGlobalObject> mGlobal; + RefPtr<BodyStreamHolder> mStreamHolder; + nsCOMPtr<nsIEventTarget> mOwningEventTarget; + + // This is the original inputStream received during the CTOR. It will be + // converted into an nsIAsyncInputStream and stored into mInputStream at the + // first use. + nsCOMPtr<nsIInputStream> mOriginalInputStream; + nsCOMPtr<nsIAsyncInputStream> mInputStream; + + RefPtr<WeakWorkerRef> mWorkerRef; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_BodyStream_h |