michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsBaseContentStream_h__ michael@0: #define nsBaseContentStream_h__ michael@0: michael@0: #include "nsIAsyncInputStream.h" michael@0: #include "nsIEventTarget.h" michael@0: #include "nsCOMPtr.h" michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsBaseContentStream is designed to be subclassed with the intention of being michael@0: // used to satisfy the nsBaseChannel::OpenContentStream method. michael@0: // michael@0: // The subclass typically overrides the default Available, ReadSegments and michael@0: // CloseWithStatus methods. By default, Read is implemented in terms of michael@0: // ReadSegments, and Close is implemented in terms of CloseWithStatus. If michael@0: // CloseWithStatus is overriden, then the subclass will usually want to call michael@0: // the base class' CloseWithStatus method before returning. michael@0: // michael@0: // If the stream is non-blocking, then readSegments may return the exception michael@0: // NS_BASE_STREAM_WOULD_BLOCK if there is no data available and the stream is michael@0: // not at the "end-of-file" or already closed. This error code must not be michael@0: // returned from the Available implementation. When the caller receives this michael@0: // error code, he may choose to call the stream's AsyncWait method, in which michael@0: // case the base stream will have a non-null PendingCallback. When the stream michael@0: // has data or encounters an error, it should be sure to dispatch a pending michael@0: // callback if one exists (see DispatchCallback). The implementation of the michael@0: // base stream's CloseWithStatus (and Close) method will ensure that any michael@0: // pending callback is dispatched. It is the responsibility of the subclass michael@0: // to ensure that the pending callback is dispatched when it wants to have its michael@0: // ReadSegments method called again. michael@0: michael@0: class nsBaseContentStream : public nsIAsyncInputStream michael@0: { michael@0: public: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIINPUTSTREAM michael@0: NS_DECL_NSIASYNCINPUTSTREAM michael@0: michael@0: nsBaseContentStream(bool nonBlocking) michael@0: : mStatus(NS_OK) michael@0: , mNonBlocking(nonBlocking) { michael@0: } michael@0: michael@0: nsresult Status() { return mStatus; } michael@0: bool IsNonBlocking() { return mNonBlocking; } michael@0: bool IsClosed() { return NS_FAILED(mStatus); } michael@0: michael@0: // Called to test if the stream has a pending callback. michael@0: bool HasPendingCallback() { return mCallback != nullptr; } michael@0: michael@0: // The current dispatch target (may be null) for the pending callback if any. michael@0: nsIEventTarget *CallbackTarget() { return mCallbackTarget; } michael@0: michael@0: // Called to dispatch a pending callback. If there is no pending callback, michael@0: // then this function does nothing. Pass true to this function to cause the michael@0: // callback to occur asynchronously; otherwise, the callback will happen michael@0: // before this function returns. michael@0: void DispatchCallback(bool async = true); michael@0: michael@0: // Helper function to make code more self-documenting. michael@0: void DispatchCallbackSync() { DispatchCallback(false); } michael@0: michael@0: protected: michael@0: virtual ~nsBaseContentStream() {} michael@0: michael@0: private: michael@0: // Called from the base stream's AsyncWait method when a pending callback michael@0: // is installed on the stream. michael@0: virtual void OnCallbackPending() {} michael@0: michael@0: private: michael@0: nsCOMPtr mCallback; michael@0: nsCOMPtr mCallbackTarget; michael@0: nsresult mStatus; michael@0: bool mNonBlocking; michael@0: }; michael@0: michael@0: #endif // nsBaseContentStream_h__