Source code

Revision control

Other Tools

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