LCOV - code coverage report
Current view: directory - netwerk/base/src - nsAsyncStreamCopier.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 107 79 73.8 %
Date: 2012-06-02 Functions: 21 13 61.9 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is Mozilla.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Netscape Communications Corporation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2002
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Darin Fisher <darin@netscape.com>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "nsIOService.h"
      39                 : #include "nsAsyncStreamCopier.h"
      40                 : #include "nsIEventTarget.h"
      41                 : #include "nsStreamUtils.h"
      42                 : #include "nsNetSegmentUtils.h"
      43                 : #include "nsNetUtil.h"
      44                 : #include "prlog.h"
      45                 : 
      46                 : using namespace mozilla;
      47                 : 
      48                 : #if defined(PR_LOGGING)
      49                 : //
      50                 : // NSPR_LOG_MODULES=nsStreamCopier:5
      51                 : //
      52                 : static PRLogModuleInfo *gStreamCopierLog = nsnull;
      53                 : #endif
      54                 : #define LOG(args) PR_LOG(gStreamCopierLog, PR_LOG_DEBUG, args)
      55                 : 
      56                 : //-----------------------------------------------------------------------------
      57                 : 
      58             399 : nsAsyncStreamCopier::nsAsyncStreamCopier()
      59                 :     : mLock("nsAsyncStreamCopier.mLock")
      60                 :     , mMode(NS_ASYNCCOPY_VIA_READSEGMENTS)
      61                 :     , mChunkSize(nsIOService::gDefaultSegmentSize)
      62                 :     , mStatus(NS_OK)
      63             399 :     , mIsPending(false)
      64                 : {
      65                 : #if defined(PR_LOGGING)
      66             399 :     if (!gStreamCopierLog)
      67              25 :         gStreamCopierLog = PR_NewLogModule("nsStreamCopier");
      68                 : #endif
      69             399 :     LOG(("Creating nsAsyncStreamCopier @%x\n", this));
      70             399 : }
      71                 : 
      72            1197 : nsAsyncStreamCopier::~nsAsyncStreamCopier()
      73                 : {
      74             399 :     LOG(("Destroying nsAsyncStreamCopier @%x\n", this));
      75            1596 : }
      76                 : 
      77                 : bool
      78             396 : nsAsyncStreamCopier::IsComplete(nsresult *status)
      79                 : {
      80             792 :     MutexAutoLock lock(mLock);
      81             396 :     if (status)
      82             396 :         *status = mStatus;
      83             396 :     return !mIsPending;
      84                 : }
      85                 : 
      86                 : void
      87             396 : nsAsyncStreamCopier::Complete(nsresult status)
      88                 : {
      89             396 :     LOG(("nsAsyncStreamCopier::Complete [this=%x status=%x]\n", this, status));
      90                 : 
      91             792 :     nsCOMPtr<nsIRequestObserver> observer;
      92             792 :     nsCOMPtr<nsISupports> ctx;
      93                 :     {
      94             792 :         MutexAutoLock lock(mLock);
      95             396 :         mCopierCtx = nsnull;
      96                 : 
      97             396 :         if (mIsPending) {
      98             396 :             mIsPending = false;
      99             396 :             mStatus = status;
     100                 : 
     101                 :             // setup OnStopRequest callback and release references...
     102             396 :             observer = mObserver;
     103             396 :             ctx = mObserverContext;
     104             396 :             mObserver = nsnull;
     105             396 :             mObserverContext = nsnull;
     106                 :         }
     107                 :     }
     108                 : 
     109             396 :     if (observer) {
     110             396 :         LOG(("  calling OnStopRequest [status=%x]\n", status));
     111             396 :         observer->OnStopRequest(this, ctx, status);
     112                 :     }
     113             396 : }
     114                 : 
     115                 : void
     116             396 : nsAsyncStreamCopier::OnAsyncCopyComplete(void *closure, nsresult status)
     117                 : {
     118             396 :     nsAsyncStreamCopier *self = (nsAsyncStreamCopier *) closure;
     119             396 :     self->Complete(status);
     120             396 :     NS_RELEASE(self); // addref'd in AsyncCopy
     121             396 : }
     122                 : 
     123                 : //-----------------------------------------------------------------------------
     124                 : // nsISupports
     125                 : 
     126           16680 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsAsyncStreamCopier,
     127                 :                               nsIRequest,
     128                 :                               nsIAsyncStreamCopier)
     129                 : 
     130                 : //-----------------------------------------------------------------------------
     131                 : // nsIRequest
     132                 : 
     133                 : NS_IMETHODIMP
     134               0 : nsAsyncStreamCopier::GetName(nsACString &name)
     135                 : {
     136               0 :     name.Truncate();
     137               0 :     return NS_OK;
     138                 : }
     139                 : 
     140                 : NS_IMETHODIMP
     141               0 : nsAsyncStreamCopier::IsPending(bool *result)
     142                 : {
     143               0 :     *result = !IsComplete();
     144               0 :     return NS_OK;
     145                 : }
     146                 : 
     147                 : NS_IMETHODIMP
     148             396 : nsAsyncStreamCopier::GetStatus(nsresult *status)
     149                 : {
     150             396 :     IsComplete(status);
     151             396 :     return NS_OK;
     152                 : }
     153                 : 
     154                 : NS_IMETHODIMP
     155               7 : nsAsyncStreamCopier::Cancel(nsresult status)
     156                 : {
     157              14 :     nsCOMPtr<nsISupports> copierCtx;
     158                 :     {
     159              14 :         MutexAutoLock lock(mLock);
     160               7 :         if (!mIsPending)
     161               0 :             return NS_OK;
     162              14 :         copierCtx.swap(mCopierCtx);
     163                 :     }
     164                 : 
     165               7 :     if (NS_SUCCEEDED(status)) {
     166               0 :         NS_WARNING("cancel with non-failure status code");
     167               0 :         status = NS_BASE_STREAM_CLOSED;
     168                 :     }
     169                 : 
     170               7 :     if (copierCtx)
     171               7 :         NS_CancelAsyncCopy(copierCtx, status);
     172                 : 
     173               7 :     return NS_OK;
     174                 : }
     175                 : 
     176                 : NS_IMETHODIMP
     177               0 : nsAsyncStreamCopier::Suspend()
     178                 : {
     179               0 :     NS_NOTREACHED("nsAsyncStreamCopier::Suspend");
     180               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     181                 : }
     182                 : 
     183                 : NS_IMETHODIMP
     184               0 : nsAsyncStreamCopier::Resume()
     185                 : {
     186               0 :     NS_NOTREACHED("nsAsyncStreamCopier::Resume");
     187               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     188                 : }
     189                 : 
     190                 : NS_IMETHODIMP
     191               0 : nsAsyncStreamCopier::GetLoadFlags(nsLoadFlags *aLoadFlags)
     192                 : {
     193               0 :     *aLoadFlags = LOAD_NORMAL;
     194               0 :     return NS_OK;
     195                 : }
     196                 : 
     197                 : NS_IMETHODIMP
     198               0 : nsAsyncStreamCopier::SetLoadFlags(nsLoadFlags aLoadFlags)
     199                 : {
     200               0 :     return NS_OK;
     201                 : }
     202                 : 
     203                 : NS_IMETHODIMP
     204               0 : nsAsyncStreamCopier::GetLoadGroup(nsILoadGroup **aLoadGroup)
     205                 : {
     206               0 :     *aLoadGroup = nsnull;
     207               0 :     return NS_OK;
     208                 : }
     209                 : 
     210                 : NS_IMETHODIMP
     211               0 : nsAsyncStreamCopier::SetLoadGroup(nsILoadGroup *aLoadGroup)
     212                 : {
     213               0 :     return NS_OK;
     214                 : }
     215                 : 
     216                 : //-----------------------------------------------------------------------------
     217                 : // nsIAsyncStreamCopier
     218                 : 
     219                 : NS_IMETHODIMP
     220             399 : nsAsyncStreamCopier::Init(nsIInputStream *source,
     221                 :                           nsIOutputStream *sink,
     222                 :                           nsIEventTarget *target,
     223                 :                           bool sourceBuffered,
     224                 :                           bool sinkBuffered,
     225                 :                           PRUint32 chunkSize,
     226                 :                           bool closeSource,
     227                 :                           bool closeSink)
     228                 : {
     229             399 :     NS_ASSERTION(sourceBuffered || sinkBuffered, "at least one stream must be buffered");
     230                 : 
     231             399 :     if (chunkSize == 0)
     232               0 :         chunkSize = nsIOService::gDefaultSegmentSize;
     233             399 :     mChunkSize = chunkSize;
     234                 : 
     235             399 :     mSource = source;
     236             399 :     mSink = sink;
     237             399 :     mCloseSource = closeSource;
     238             399 :     mCloseSink = closeSink;
     239                 : 
     240                 :     mMode = sourceBuffered ? NS_ASYNCCOPY_VIA_READSEGMENTS
     241             399 :                            : NS_ASYNCCOPY_VIA_WRITESEGMENTS;
     242             399 :     if (target)
     243               0 :         mTarget = target;
     244                 :     else {
     245                 :         nsresult rv;
     246             399 :         mTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
     247             399 :         if (NS_FAILED(rv)) return rv;
     248                 :     }
     249             399 :     return NS_OK;
     250                 : }
     251                 : 
     252                 : NS_IMETHODIMP
     253             399 : nsAsyncStreamCopier::AsyncCopy(nsIRequestObserver *observer, nsISupports *ctx)
     254                 : {
     255             399 :     LOG(("nsAsyncStreamCopier::AsyncCopy [this=%x observer=%x]\n", this, observer));
     256                 : 
     257             399 :     NS_ASSERTION(mSource && mSink, "not initialized");
     258                 :     nsresult rv;
     259                 : 
     260             399 :     if (observer) {
     261                 :         // build proxy for observer events
     262             399 :         rv = NS_NewRequestObserverProxy(getter_AddRefs(mObserver), observer);
     263             399 :         if (NS_FAILED(rv)) return rv;
     264                 :     }
     265                 : 
     266                 :     // from this point forward, AsyncCopy is going to return NS_OK.  any errors
     267                 :     // will be reported via OnStopRequest.
     268             399 :     mIsPending = true;
     269                 : 
     270             399 :     mObserverContext = ctx;
     271             399 :     if (mObserver) {
     272             399 :         rv = mObserver->OnStartRequest(this, mObserverContext);
     273             399 :         if (NS_FAILED(rv))
     274               0 :             Cancel(rv);
     275                 :     }
     276                 :     
     277                 :     // we want to receive progress notifications; release happens in
     278                 :     // OnAsyncCopyComplete.
     279             399 :     NS_ADDREF_THIS();
     280                 :     rv = NS_AsyncCopy(mSource, mSink, mTarget, mMode, mChunkSize,
     281                 :                       OnAsyncCopyComplete, this, mCloseSource, mCloseSink,
     282             399 :                       getter_AddRefs(mCopierCtx));
     283             399 :     if (NS_FAILED(rv)) {
     284               3 :         NS_RELEASE_THIS();
     285               3 :         Cancel(rv);
     286                 :     }
     287                 : 
     288             399 :     return NS_OK;
     289                 : }

Generated by: LCOV version 1.7