summaryrefslogtreecommitdiffstats
path: root/netwerk/base/nsInputStreamPump.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/base/nsInputStreamPump.h129
1 files changed, 129 insertions, 0 deletions
diff --git a/netwerk/base/nsInputStreamPump.h b/netwerk/base/nsInputStreamPump.h
new file mode 100644
index 0000000000..21e75c0276
--- /dev/null
+++ b/netwerk/base/nsInputStreamPump.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 nsInputStreamPump_h__
+#define nsInputStreamPump_h__
+
+#include "nsIInputStreamPump.h"
+#include "nsIAsyncInputStream.h"
+#include "nsIThreadRetargetableRequest.h"
+#include "nsCOMPtr.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/RecursiveMutex.h"
+
+#ifdef DEBUG
+# include "MainThreadUtils.h"
+# include "nsISerialEventTarget.h"
+#endif
+
+class nsIInputStream;
+class nsILoadGroup;
+class nsIStreamListener;
+
+#define NS_INPUT_STREAM_PUMP_IID \
+ { \
+ 0x42f1cc9b, 0xdf5f, 0x4c9b, { \
+ 0xbd, 0x71, 0x8d, 0x4a, 0xe2, 0x27, 0xc1, 0x8a \
+ } \
+ }
+
+class nsInputStreamPump final : public nsIInputStreamPump,
+ public nsIInputStreamCallback,
+ public nsIThreadRetargetableRequest {
+ ~nsInputStreamPump() = default;
+
+ public:
+ using RecursiveMutexAutoLock = mozilla::RecursiveMutexAutoLock;
+ using RecursiveMutexAutoUnlock = mozilla::RecursiveMutexAutoUnlock;
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIREQUEST
+ NS_DECL_NSIINPUTSTREAMPUMP
+ NS_DECL_NSIINPUTSTREAMCALLBACK
+ NS_DECL_NSITHREADRETARGETABLEREQUEST
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_INPUT_STREAM_PUMP_IID)
+
+ nsInputStreamPump();
+
+ static nsresult Create(nsInputStreamPump** result, nsIInputStream* stream,
+ uint32_t segsize = 0, uint32_t segcount = 0,
+ bool closeWhenDone = false,
+ nsISerialEventTarget* mainThreadTarget = nullptr);
+
+ using PeekSegmentFun = void (*)(void*, const uint8_t*, uint32_t);
+ /**
+ * Peek into the first chunk of data that's in the stream. Note that this
+ * method will not call the callback when there is no data in the stream.
+ * The callback will be called at most once.
+ *
+ * The data from the stream will not be consumed, i.e. the pump's listener
+ * can still read all the data
+ *
+ * Do not call before asyncRead. Do not call after onStopRequest.
+ */
+ nsresult PeekStream(PeekSegmentFun callback, void* closure);
+
+ /**
+ * Dispatched (to the main thread) by OnStateStop if it's called off main
+ * thread. Updates mState based on return value of OnStateStop.
+ */
+ nsresult CallOnStateStop();
+
+ protected:
+ enum { STATE_IDLE, STATE_START, STATE_TRANSFER, STATE_STOP, STATE_DEAD };
+
+ nsresult EnsureWaiting();
+ uint32_t OnStateStart();
+ uint32_t OnStateTransfer();
+ uint32_t OnStateStop();
+ nsresult CreateBufferedStreamIfNeeded() MOZ_REQUIRES(mMutex);
+
+ // This should optimize away in non-DEBUG builds
+ MOZ_ALWAYS_INLINE void AssertOnThread() const MOZ_REQUIRES(mMutex) {
+ if (mOffMainThread) {
+ MOZ_ASSERT(mTargetThread->IsOnCurrentThread());
+ } else {
+ MOZ_ASSERT(NS_IsMainThread());
+ }
+ }
+
+ uint32_t mState MOZ_GUARDED_BY(mMutex){STATE_IDLE};
+ nsCOMPtr<nsILoadGroup> mLoadGroup MOZ_GUARDED_BY(mMutex);
+ // mListener is written on a single thread (either MainThread or an
+ // off-MainThread thread), read from that thread and perhaps others (in
+ // RetargetDeliveryTo)
+ nsCOMPtr<nsIStreamListener> mListener MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsISerialEventTarget> mTargetThread MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsISerialEventTarget> mLabeledMainThreadTarget
+ MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsIInputStream> mStream MOZ_GUARDED_BY(mMutex);
+ // mAsyncStream is written on a single thread (either MainThread or an
+ // off-MainThread thread), and lives from AsyncRead() to OnStateStop().
+ nsCOMPtr<nsIAsyncInputStream> mAsyncStream MOZ_GUARDED_BY(mMutex);
+ uint64_t mStreamOffset MOZ_GUARDED_BY(mMutex){0};
+ uint64_t mStreamLength MOZ_GUARDED_BY(mMutex){0};
+ uint32_t mSegSize MOZ_GUARDED_BY(mMutex){0};
+ uint32_t mSegCount MOZ_GUARDED_BY(mMutex){0};
+ nsresult mStatus MOZ_GUARDED_BY(mMutex){NS_OK};
+ uint32_t mSuspendCount MOZ_GUARDED_BY(mMutex){0};
+ uint32_t mLoadFlags MOZ_GUARDED_BY(mMutex){LOAD_NORMAL};
+ bool mIsPending MOZ_GUARDED_BY(mMutex){false};
+ // True while in OnInputStreamReady, calling OnStateStart, OnStateTransfer
+ // and OnStateStop. Used to prevent calls to AsyncWait during callbacks.
+ bool mProcessingCallbacks MOZ_GUARDED_BY(mMutex){false};
+ // True if waiting on the "input stream ready" callback.
+ bool mWaitingForInputStreamReady MOZ_GUARDED_BY(mMutex){false};
+ bool mCloseWhenDone MOZ_GUARDED_BY(mMutex){false};
+ bool mRetargeting MOZ_GUARDED_BY(mMutex){false};
+ bool mAsyncStreamIsBuffered MOZ_GUARDED_BY(mMutex){false};
+ // Indicate whether nsInputStreamPump is used completely off main thread.
+ // If true, OnStateStop() is executed off main thread. Set at creation.
+ const bool mOffMainThread;
+ // Protects state/member var accesses across multiple threads.
+ mozilla::RecursiveMutex mMutex{"nsInputStreamPump"};
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsInputStreamPump, NS_INPUT_STREAM_PUMP_IID)
+
+#endif // !nsInputStreamChannel_h__