Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 NS_IMPL_ISUPPORTS(nsStreamListenerTee,
9 nsIStreamListener,
10 nsIRequestObserver,
11 nsIStreamListenerTee,
12 nsIThreadRetargetableStreamListener)
14 NS_IMETHODIMP
15 nsStreamListenerTee::OnStartRequest(nsIRequest *request,
16 nsISupports *context)
17 {
18 NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
19 nsresult rv1 = mListener->OnStartRequest(request, context);
20 nsresult rv2 = NS_OK;
21 if (mObserver)
22 rv2 = mObserver->OnStartRequest(request, context);
24 // Preserve NS_SUCCESS_XXX in rv1 in case mObserver didn't throw
25 return (NS_FAILED(rv2) && NS_SUCCEEDED(rv1)) ? rv2 : rv1;
26 }
28 NS_IMETHODIMP
29 nsStreamListenerTee::OnStopRequest(nsIRequest *request,
30 nsISupports *context,
31 nsresult status)
32 {
33 NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
34 // it is critical that we close out the input stream tee
35 if (mInputTee) {
36 mInputTee->SetSink(nullptr);
37 mInputTee = 0;
38 }
40 // release sink on the same thread where the data was written (bug 716293)
41 if (mEventTarget) {
42 nsIOutputStream *sink = nullptr;
43 mSink.swap(sink);
44 if (NS_FAILED(NS_ProxyRelease(mEventTarget, sink))) {
45 NS_WARNING("Releasing sink on the current thread!");
46 NS_RELEASE(sink);
47 }
48 }
49 else {
50 mSink = 0;
51 }
53 nsresult rv = mListener->OnStopRequest(request, context, status);
54 if (mObserver)
55 mObserver->OnStopRequest(request, context, status);
56 mObserver = 0;
57 return rv;
58 }
60 NS_IMETHODIMP
61 nsStreamListenerTee::OnDataAvailable(nsIRequest *request,
62 nsISupports *context,
63 nsIInputStream *input,
64 uint64_t offset,
65 uint32_t count)
66 {
67 NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
68 NS_ENSURE_TRUE(mSink, NS_ERROR_NOT_INITIALIZED);
70 nsCOMPtr<nsIInputStream> tee;
71 nsresult rv;
73 if (!mInputTee) {
74 if (mEventTarget)
75 rv = NS_NewInputStreamTeeAsync(getter_AddRefs(tee), input,
76 mSink, mEventTarget);
77 else
78 rv = NS_NewInputStreamTee(getter_AddRefs(tee), input, mSink);
79 if (NS_FAILED(rv)) return rv;
81 mInputTee = do_QueryInterface(tee, &rv);
82 if (NS_FAILED(rv)) return rv;
83 }
84 else {
85 // re-initialize the input tee since the input stream may have changed.
86 rv = mInputTee->SetSource(input);
87 if (NS_FAILED(rv)) return rv;
89 tee = do_QueryInterface(mInputTee, &rv);
90 if (NS_FAILED(rv)) return rv;
91 }
93 return mListener->OnDataAvailable(request, context, tee, offset, count);
94 }
96 NS_IMETHODIMP
97 nsStreamListenerTee::CheckListenerChain()
98 {
99 NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
100 nsresult rv = NS_OK;
101 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
102 do_QueryInterface(mListener, &rv);
103 if (retargetableListener) {
104 rv = retargetableListener->CheckListenerChain();
105 }
106 if (NS_FAILED(rv)) {
107 return rv;
108 }
109 if (!mObserver) {
110 return rv;
111 }
112 retargetableListener = do_QueryInterface(mObserver, &rv);
113 if (retargetableListener) {
114 rv = retargetableListener->CheckListenerChain();
115 }
116 return rv;
117 }
119 NS_IMETHODIMP
120 nsStreamListenerTee::Init(nsIStreamListener *listener,
121 nsIOutputStream *sink,
122 nsIRequestObserver *requestObserver)
123 {
124 NS_ENSURE_ARG_POINTER(listener);
125 NS_ENSURE_ARG_POINTER(sink);
126 mListener = listener;
127 mSink = sink;
128 mObserver = requestObserver;
129 return NS_OK;
130 }
132 NS_IMETHODIMP
133 nsStreamListenerTee::InitAsync(nsIStreamListener *listener,
134 nsIEventTarget *eventTarget,
135 nsIOutputStream *sink,
136 nsIRequestObserver *requestObserver)
137 {
138 NS_ENSURE_ARG_POINTER(eventTarget);
139 mEventTarget = eventTarget;
140 return Init(listener, sink, requestObserver);
141 }