Bug 1804798 - Explicitly set auto page name (and corresponding debug flag) when inser...
[gecko.git] / netwerk / base / nsStreamListenerTee.cpp
blob0a6a78068f63258e7be35d9b480c0a899e0c1edc
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsStreamListenerTee.h"
6 #include "nsProxyRelease.h"
8 namespace mozilla {
9 namespace net {
11 NS_IMPL_ISUPPORTS(nsStreamListenerTee, nsIStreamListener, nsIRequestObserver,
12 nsIStreamListenerTee, nsIThreadRetargetableStreamListener,
13 nsIMultiPartChannelListener)
15 NS_IMETHODIMP
16 nsStreamListenerTee::OnStartRequest(nsIRequest* request) {
17 NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
19 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(request);
20 if (multiPartChannel) {
21 mIsMultiPart = true;
24 nsresult rv1 = mListener->OnStartRequest(request);
25 nsresult rv2 = NS_OK;
26 if (mObserver) rv2 = mObserver->OnStartRequest(request);
28 // Preserve NS_SUCCESS_XXX in rv1 in case mObserver didn't throw
29 return (NS_FAILED(rv2) && NS_SUCCEEDED(rv1)) ? rv2 : rv1;
32 NS_IMETHODIMP
33 nsStreamListenerTee::OnStopRequest(nsIRequest* request, nsresult status) {
34 NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
35 // it is critical that we close out the input stream tee
36 if (mInputTee) {
37 mInputTee->SetSink(nullptr);
38 mInputTee = nullptr;
41 if (!mIsMultiPart) {
42 // release sink on the same thread where the data was written (bug 716293)
43 if (mEventTarget) {
44 NS_ProxyRelease("nsStreamListenerTee::mSink", mEventTarget,
45 mSink.forget());
46 } else {
47 mSink = nullptr;
51 nsresult rv = mListener->OnStopRequest(request, status);
52 if (mObserver) mObserver->OnStopRequest(request, status);
53 if (!mIsMultiPart) {
54 mObserver = nullptr;
56 return rv;
59 NS_IMETHODIMP
60 nsStreamListenerTee::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
61 uint64_t offset, uint32_t count) {
62 NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
63 NS_ENSURE_TRUE(mSink, NS_ERROR_NOT_INITIALIZED);
65 nsCOMPtr<nsIInputStream> tee;
66 nsresult rv;
68 if (!mInputTee) {
69 if (mEventTarget) {
70 rv = NS_NewInputStreamTeeAsync(getter_AddRefs(tee), input, mSink,
71 mEventTarget);
72 } else {
73 rv = NS_NewInputStreamTee(getter_AddRefs(tee), input, mSink);
75 if (NS_FAILED(rv)) return rv;
77 mInputTee = do_QueryInterface(tee, &rv);
78 if (NS_FAILED(rv)) return rv;
79 } else {
80 // re-initialize the input tee since the input stream may have changed.
81 rv = mInputTee->SetSource(input);
82 if (NS_FAILED(rv)) return rv;
84 tee = mInputTee;
87 return mListener->OnDataAvailable(request, tee, offset, count);
90 NS_IMETHODIMP
91 nsStreamListenerTee::OnAfterLastPart(nsresult aStatus) {
92 // release sink on the same thread where the data was written (bug 716293)
93 if (mEventTarget) {
94 NS_ProxyRelease("nsStreamListenerTee::mSink", mEventTarget, mSink.forget());
95 } else {
96 mSink = nullptr;
99 if (nsCOMPtr<nsIMultiPartChannelListener> multi =
100 do_QueryInterface(mListener)) {
101 multi->OnAfterLastPart(aStatus);
103 if (!SameCOMIdentity(mListener, mObserver)) {
104 if (nsCOMPtr<nsIMultiPartChannelListener> multi =
105 do_QueryInterface(mObserver)) {
106 multi->OnAfterLastPart(aStatus);
110 mObserver = nullptr;
111 return NS_OK;
114 NS_IMETHODIMP
115 nsStreamListenerTee::CheckListenerChain() {
116 NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
117 nsresult rv = NS_OK;
118 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
119 do_QueryInterface(mListener, &rv);
120 if (retargetableListener) {
121 rv = retargetableListener->CheckListenerChain();
123 if (NS_FAILED(rv)) {
124 return rv;
126 if (!mObserver) {
127 return rv;
129 retargetableListener = do_QueryInterface(mObserver, &rv);
130 if (retargetableListener) {
131 rv = retargetableListener->CheckListenerChain();
133 return rv;
136 NS_IMETHODIMP
137 nsStreamListenerTee::Init(nsIStreamListener* listener, nsIOutputStream* sink,
138 nsIRequestObserver* requestObserver) {
139 NS_ENSURE_ARG_POINTER(listener);
140 NS_ENSURE_ARG_POINTER(sink);
141 mListener = listener;
142 mSink = sink;
143 mObserver = requestObserver;
144 return NS_OK;
147 NS_IMETHODIMP
148 nsStreamListenerTee::InitAsync(nsIStreamListener* listener,
149 nsIEventTarget* eventTarget,
150 nsIOutputStream* sink,
151 nsIRequestObserver* requestObserver) {
152 NS_ENSURE_ARG_POINTER(eventTarget);
153 mEventTarget = eventTarget;
154 return Init(listener, sink, requestObserver);
157 } // namespace net
158 } // namespace mozilla