netwerk/base/src/nsStreamListenerTee.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 }

mercurial