Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef nsBaseContentStream_h__
7 : #define nsBaseContentStream_h__
8 :
9 : #include "nsIAsyncInputStream.h"
10 : #include "nsIEventTarget.h"
11 : #include "nsCOMPtr.h"
12 :
13 : //-----------------------------------------------------------------------------
14 : // nsBaseContentStream is designed to be subclassed with the intention of being
15 : // used to satisfy the nsBaseChannel::OpenContentStream method.
16 : //
17 : // The subclass typically overrides the default Available, ReadSegments and
18 : // CloseWithStatus methods. By default, Read is implemented in terms of
19 : // ReadSegments, and Close is implemented in terms of CloseWithStatus. If
20 : // CloseWithStatus is overriden, then the subclass will usually want to call
21 : // the base class' CloseWithStatus method before returning.
22 : //
23 : // If the stream is non-blocking, then readSegments may return the exception
24 : // NS_BASE_STREAM_WOULD_BLOCK if there is no data available and the stream is
25 : // not at the "end-of-file" or already closed. This error code must not be
26 : // returned from the Available implementation. When the caller receives this
27 : // error code, he may choose to call the stream's AsyncWait method, in which
28 : // case the base stream will have a non-null PendingCallback. When the stream
29 : // has data or encounters an error, it should be sure to dispatch a pending
30 : // callback if one exists (see DispatchCallback). The implementation of the
31 : // base stream's CloseWithStatus (and Close) method will ensure that any
32 : // pending callback is dispatched. It is the responsibility of the subclass
33 : // to ensure that the pending callback is dispatched when it wants to have its
34 : // ReadSegments method called again.
35 :
36 : class nsBaseContentStream : public nsIAsyncInputStream
37 : {
38 : public:
39 : NS_DECL_THREADSAFE_ISUPPORTS
40 : NS_DECL_NSIINPUTSTREAM
41 : NS_DECL_NSIASYNCINPUTSTREAM
42 :
43 0 : explicit nsBaseContentStream(bool nonBlocking)
44 0 : : mStatus(NS_OK)
45 0 : , mNonBlocking(nonBlocking) {
46 0 : }
47 :
48 : nsresult Status() { return mStatus; }
49 0 : bool IsNonBlocking() { return mNonBlocking; }
50 0 : bool IsClosed() { return NS_FAILED(mStatus); }
51 :
52 : // Called to test if the stream has a pending callback.
53 0 : bool HasPendingCallback() { return mCallback != nullptr; }
54 :
55 : // The current dispatch target (may be null) for the pending callback if any.
56 0 : nsIEventTarget *CallbackTarget() { return mCallbackTarget; }
57 :
58 : // Called to dispatch a pending callback. If there is no pending callback,
59 : // then this function does nothing. Pass true to this function to cause the
60 : // callback to occur asynchronously; otherwise, the callback will happen
61 : // before this function returns.
62 : void DispatchCallback(bool async = true);
63 :
64 : // Helper function to make code more self-documenting.
65 0 : void DispatchCallbackSync() { DispatchCallback(false); }
66 :
67 : protected:
68 0 : virtual ~nsBaseContentStream() {}
69 :
70 : private:
71 : // Called from the base stream's AsyncWait method when a pending callback
72 : // is installed on the stream.
73 0 : virtual void OnCallbackPending() {}
74 :
75 : private:
76 : nsCOMPtr<nsIInputStreamCallback> mCallback;
77 : nsCOMPtr<nsIEventTarget> mCallbackTarget;
78 : nsresult mStatus;
79 : bool mNonBlocking;
80 : };
81 :
82 : #endif // nsBaseContentStream_h__
|