1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsStreamListenerTee.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,141 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsStreamListenerTee.h" 1.9 +#include "nsProxyRelease.h" 1.10 + 1.11 +NS_IMPL_ISUPPORTS(nsStreamListenerTee, 1.12 + nsIStreamListener, 1.13 + nsIRequestObserver, 1.14 + nsIStreamListenerTee, 1.15 + nsIThreadRetargetableStreamListener) 1.16 + 1.17 +NS_IMETHODIMP 1.18 +nsStreamListenerTee::OnStartRequest(nsIRequest *request, 1.19 + nsISupports *context) 1.20 +{ 1.21 + NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED); 1.22 + nsresult rv1 = mListener->OnStartRequest(request, context); 1.23 + nsresult rv2 = NS_OK; 1.24 + if (mObserver) 1.25 + rv2 = mObserver->OnStartRequest(request, context); 1.26 + 1.27 + // Preserve NS_SUCCESS_XXX in rv1 in case mObserver didn't throw 1.28 + return (NS_FAILED(rv2) && NS_SUCCEEDED(rv1)) ? rv2 : rv1; 1.29 +} 1.30 + 1.31 +NS_IMETHODIMP 1.32 +nsStreamListenerTee::OnStopRequest(nsIRequest *request, 1.33 + nsISupports *context, 1.34 + nsresult status) 1.35 +{ 1.36 + NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED); 1.37 + // it is critical that we close out the input stream tee 1.38 + if (mInputTee) { 1.39 + mInputTee->SetSink(nullptr); 1.40 + mInputTee = 0; 1.41 + } 1.42 + 1.43 + // release sink on the same thread where the data was written (bug 716293) 1.44 + if (mEventTarget) { 1.45 + nsIOutputStream *sink = nullptr; 1.46 + mSink.swap(sink); 1.47 + if (NS_FAILED(NS_ProxyRelease(mEventTarget, sink))) { 1.48 + NS_WARNING("Releasing sink on the current thread!"); 1.49 + NS_RELEASE(sink); 1.50 + } 1.51 + } 1.52 + else { 1.53 + mSink = 0; 1.54 + } 1.55 + 1.56 + nsresult rv = mListener->OnStopRequest(request, context, status); 1.57 + if (mObserver) 1.58 + mObserver->OnStopRequest(request, context, status); 1.59 + mObserver = 0; 1.60 + return rv; 1.61 +} 1.62 + 1.63 +NS_IMETHODIMP 1.64 +nsStreamListenerTee::OnDataAvailable(nsIRequest *request, 1.65 + nsISupports *context, 1.66 + nsIInputStream *input, 1.67 + uint64_t offset, 1.68 + uint32_t count) 1.69 +{ 1.70 + NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED); 1.71 + NS_ENSURE_TRUE(mSink, NS_ERROR_NOT_INITIALIZED); 1.72 + 1.73 + nsCOMPtr<nsIInputStream> tee; 1.74 + nsresult rv; 1.75 + 1.76 + if (!mInputTee) { 1.77 + if (mEventTarget) 1.78 + rv = NS_NewInputStreamTeeAsync(getter_AddRefs(tee), input, 1.79 + mSink, mEventTarget); 1.80 + else 1.81 + rv = NS_NewInputStreamTee(getter_AddRefs(tee), input, mSink); 1.82 + if (NS_FAILED(rv)) return rv; 1.83 + 1.84 + mInputTee = do_QueryInterface(tee, &rv); 1.85 + if (NS_FAILED(rv)) return rv; 1.86 + } 1.87 + else { 1.88 + // re-initialize the input tee since the input stream may have changed. 1.89 + rv = mInputTee->SetSource(input); 1.90 + if (NS_FAILED(rv)) return rv; 1.91 + 1.92 + tee = do_QueryInterface(mInputTee, &rv); 1.93 + if (NS_FAILED(rv)) return rv; 1.94 + } 1.95 + 1.96 + return mListener->OnDataAvailable(request, context, tee, offset, count); 1.97 +} 1.98 + 1.99 +NS_IMETHODIMP 1.100 +nsStreamListenerTee::CheckListenerChain() 1.101 +{ 1.102 + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!"); 1.103 + nsresult rv = NS_OK; 1.104 + nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener = 1.105 + do_QueryInterface(mListener, &rv); 1.106 + if (retargetableListener) { 1.107 + rv = retargetableListener->CheckListenerChain(); 1.108 + } 1.109 + if (NS_FAILED(rv)) { 1.110 + return rv; 1.111 + } 1.112 + if (!mObserver) { 1.113 + return rv; 1.114 + } 1.115 + retargetableListener = do_QueryInterface(mObserver, &rv); 1.116 + if (retargetableListener) { 1.117 + rv = retargetableListener->CheckListenerChain(); 1.118 + } 1.119 + return rv; 1.120 +} 1.121 + 1.122 +NS_IMETHODIMP 1.123 +nsStreamListenerTee::Init(nsIStreamListener *listener, 1.124 + nsIOutputStream *sink, 1.125 + nsIRequestObserver *requestObserver) 1.126 +{ 1.127 + NS_ENSURE_ARG_POINTER(listener); 1.128 + NS_ENSURE_ARG_POINTER(sink); 1.129 + mListener = listener; 1.130 + mSink = sink; 1.131 + mObserver = requestObserver; 1.132 + return NS_OK; 1.133 +} 1.134 + 1.135 +NS_IMETHODIMP 1.136 +nsStreamListenerTee::InitAsync(nsIStreamListener *listener, 1.137 + nsIEventTarget *eventTarget, 1.138 + nsIOutputStream *sink, 1.139 + nsIRequestObserver *requestObserver) 1.140 +{ 1.141 + NS_ENSURE_ARG_POINTER(eventTarget); 1.142 + mEventTarget = eventTarget; 1.143 + return Init(listener, sink, requestObserver); 1.144 +}