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 : #include "nsBaseContentStream.h"
7 : #include "nsStreamUtils.h"
8 :
9 : //-----------------------------------------------------------------------------
10 :
11 : void
12 0 : nsBaseContentStream::DispatchCallback(bool async)
13 : {
14 0 : if (!mCallback)
15 0 : return;
16 :
17 : // It's important to clear mCallback and mCallbackTarget up-front because the
18 : // OnInputStreamReady implementation may call our AsyncWait method.
19 :
20 0 : nsCOMPtr<nsIInputStreamCallback> callback;
21 0 : if (async) {
22 0 : callback = NS_NewInputStreamReadyEvent("nsBaseContentStream::DispatchCallback",
23 0 : mCallback, mCallbackTarget);
24 0 : mCallback = nullptr;
25 : } else {
26 0 : callback.swap(mCallback);
27 : }
28 0 : mCallbackTarget = nullptr;
29 :
30 0 : callback->OnInputStreamReady(this);
31 : }
32 :
33 : //-----------------------------------------------------------------------------
34 : // nsBaseContentStream::nsISupports
35 :
36 0 : NS_IMPL_ADDREF(nsBaseContentStream)
37 0 : NS_IMPL_RELEASE(nsBaseContentStream)
38 :
39 : // We only support nsIAsyncInputStream when we are in non-blocking mode.
40 0 : NS_INTERFACE_MAP_BEGIN(nsBaseContentStream)
41 0 : NS_INTERFACE_MAP_ENTRY(nsIInputStream)
42 0 : NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mNonBlocking)
43 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
44 0 : NS_INTERFACE_MAP_END_THREADSAFE
45 :
46 : //-----------------------------------------------------------------------------
47 : // nsBaseContentStream::nsIInputStream
48 :
49 : NS_IMETHODIMP
50 0 : nsBaseContentStream::Close()
51 : {
52 0 : return IsClosed() ? NS_OK : CloseWithStatus(NS_BASE_STREAM_CLOSED);
53 : }
54 :
55 : NS_IMETHODIMP
56 0 : nsBaseContentStream::Available(uint64_t *result)
57 : {
58 0 : *result = 0;
59 0 : return mStatus;
60 : }
61 :
62 : NS_IMETHODIMP
63 0 : nsBaseContentStream::Read(char *buf, uint32_t count, uint32_t *result)
64 : {
65 0 : return ReadSegments(NS_CopySegmentToBuffer, buf, count, result);
66 : }
67 :
68 : NS_IMETHODIMP
69 0 : nsBaseContentStream::ReadSegments(nsWriteSegmentFun fun, void *closure,
70 : uint32_t count, uint32_t *result)
71 : {
72 0 : *result = 0;
73 :
74 0 : if (mStatus == NS_BASE_STREAM_CLOSED)
75 0 : return NS_OK;
76 :
77 : // No data yet
78 0 : if (!IsClosed() && IsNonBlocking())
79 0 : return NS_BASE_STREAM_WOULD_BLOCK;
80 :
81 0 : return mStatus;
82 : }
83 :
84 : NS_IMETHODIMP
85 0 : nsBaseContentStream::IsNonBlocking(bool *result)
86 : {
87 0 : *result = mNonBlocking;
88 0 : return NS_OK;
89 : }
90 :
91 : //-----------------------------------------------------------------------------
92 : // nsBaseContentStream::nsIAsyncInputStream
93 :
94 : NS_IMETHODIMP
95 0 : nsBaseContentStream::CloseWithStatus(nsresult status)
96 : {
97 0 : if (IsClosed())
98 0 : return NS_OK;
99 :
100 0 : NS_ENSURE_ARG(NS_FAILED(status));
101 0 : mStatus = status;
102 :
103 0 : DispatchCallback();
104 0 : return NS_OK;
105 : }
106 :
107 : NS_IMETHODIMP
108 0 : nsBaseContentStream::AsyncWait(nsIInputStreamCallback *callback,
109 : uint32_t flags, uint32_t requestedCount,
110 : nsIEventTarget *target)
111 : {
112 : // Our _only_ consumer is nsInputStreamPump, so we simplify things here by
113 : // making assumptions about how we will be called.
114 0 : NS_ASSERTION(target, "unexpected parameter");
115 0 : NS_ASSERTION(flags == 0, "unexpected parameter");
116 0 : NS_ASSERTION(requestedCount == 0, "unexpected parameter");
117 :
118 : #ifdef DEBUG
119 : bool correctThread;
120 0 : target->IsOnCurrentThread(&correctThread);
121 0 : NS_ASSERTION(correctThread, "event target must be on the current thread");
122 : #endif
123 :
124 0 : mCallback = callback;
125 0 : mCallbackTarget = target;
126 :
127 0 : if (!mCallback)
128 0 : return NS_OK;
129 :
130 : // If we're already closed, then dispatch this callback immediately.
131 0 : if (IsClosed()) {
132 0 : DispatchCallback();
133 0 : return NS_OK;
134 : }
135 :
136 0 : OnCallbackPending();
137 0 : return NS_OK;
138 : }
|