LCOV - code coverage report
Current view: directory - netwerk/cache - nsCacheEntryDescriptor.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 460 232 50.4 %
Date: 2012-06-02 Functions: 72 42 58.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is nsCacheEntryDescriptor.cpp, released
      17                 :  * February 22, 2001.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Gordon Sheridan, 22-February-2001
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsICache.h"
      42                 : #include "nsCache.h"
      43                 : #include "nsCacheService.h"
      44                 : #include "nsCacheEntryDescriptor.h"
      45                 : #include "nsCacheEntry.h"
      46                 : #include "nsReadableUtils.h"
      47                 : #include "nsIOutputStream.h"
      48                 : #include "nsCRT.h"
      49                 : 
      50                 : #define kMinDecompressReadBufLen 1024
      51                 : #define kMinCompressWriteBufLen  1024
      52                 : 
      53           17618 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsCacheEntryDescriptor,
      54                 :                               nsICacheEntryDescriptor,
      55                 :                               nsICacheEntryInfo)
      56                 : 
      57            1778 : nsCacheEntryDescriptor::nsCacheEntryDescriptor(nsCacheEntry * entry,
      58                 :                                                nsCacheAccessMode accessGranted)
      59                 :     : mCacheEntry(entry),
      60                 :       mAccessGranted(accessGranted),
      61            1778 :       mOutput(nsnull)
      62                 : {
      63            1778 :     PR_INIT_CLIST(this);
      64            1778 :     NS_ADDREF(nsCacheService::GlobalInstance());  // ensure it lives for the lifetime of the descriptor
      65            1778 : }
      66                 : 
      67                 : 
      68            3556 : nsCacheEntryDescriptor::~nsCacheEntryDescriptor()
      69                 : {
      70                 :     // No need to close if the cache entry has already been severed.  This
      71                 :     // helps avoid a shutdown assertion (bug 285519) that is caused when
      72                 :     // consumers end up holding onto these objects past xpcom-shutdown.  It's
      73                 :     // okay for them to do that because the cache service calls our Close
      74                 :     // method during xpcom-shutdown, so we don't need to complain about it.
      75            1778 :     if (mCacheEntry)
      76            1727 :         Close();
      77                 : 
      78            1778 :     nsCacheService * service = nsCacheService::GlobalInstance();
      79            1778 :     NS_RELEASE(service);
      80            7112 : }
      81                 : 
      82                 : 
      83                 : NS_IMETHODIMP
      84               0 : nsCacheEntryDescriptor::GetClientID(char ** result)
      85                 : {
      86               0 :     NS_ENSURE_ARG_POINTER(result);
      87                 : 
      88               0 :     nsCacheServiceAutoLock lock;
      89               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
      90                 : 
      91               0 :     return ClientIDFromCacheKey(*(mCacheEntry->Key()), result);
      92                 : }
      93                 : 
      94                 : 
      95                 : NS_IMETHODIMP
      96            1488 : nsCacheEntryDescriptor::GetDeviceID(char ** aDeviceID)
      97                 : {
      98            1488 :     NS_ENSURE_ARG_POINTER(aDeviceID);
      99            2976 :     nsCacheServiceAutoLock lock;
     100            1488 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     101                 : 
     102            1488 :     const char* deviceID = mCacheEntry->GetDeviceID();
     103            1488 :     if (!deviceID) {
     104             901 :         *aDeviceID = nsnull;
     105             901 :         return NS_OK;
     106                 :     }
     107                 : 
     108             587 :     *aDeviceID = NS_strdup(deviceID);
     109             587 :     return *aDeviceID ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     110                 : }
     111                 : 
     112                 : 
     113                 : NS_IMETHODIMP
     114               0 : nsCacheEntryDescriptor::GetKey(nsACString &result)
     115                 : {
     116               0 :     nsCacheServiceAutoLock lock;
     117               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     118                 : 
     119               0 :     return ClientKeyFromCacheKey(*(mCacheEntry->Key()), result);
     120                 : }
     121                 : 
     122                 : 
     123                 : NS_IMETHODIMP
     124               0 : nsCacheEntryDescriptor::GetFetchCount(PRInt32 *result)
     125                 : {
     126               0 :     NS_ENSURE_ARG_POINTER(result);
     127               0 :     nsCacheServiceAutoLock lock;
     128               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     129                 : 
     130               0 :     *result = mCacheEntry->FetchCount();
     131               0 :     return NS_OK;
     132                 : }
     133                 : 
     134                 : 
     135                 : NS_IMETHODIMP
     136               0 : nsCacheEntryDescriptor::GetLastFetched(PRUint32 *result)
     137                 : {
     138               0 :     NS_ENSURE_ARG_POINTER(result);
     139               0 :     nsCacheServiceAutoLock lock;
     140               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     141                 : 
     142               0 :     *result = mCacheEntry->LastFetched();
     143               0 :     return NS_OK;
     144                 : }
     145                 : 
     146                 : 
     147                 : NS_IMETHODIMP
     148             567 : nsCacheEntryDescriptor::GetLastModified(PRUint32 *result)
     149                 : {
     150             567 :     NS_ENSURE_ARG_POINTER(result);
     151            1134 :     nsCacheServiceAutoLock lock;
     152             567 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     153                 : 
     154             567 :     *result = mCacheEntry->LastModified();
     155             567 :     return NS_OK;
     156                 : }
     157                 : 
     158                 : 
     159                 : NS_IMETHODIMP
     160             289 : nsCacheEntryDescriptor::GetExpirationTime(PRUint32 *result)
     161                 : {
     162             289 :     NS_ENSURE_ARG_POINTER(result);
     163             578 :     nsCacheServiceAutoLock lock;
     164             289 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     165                 : 
     166             289 :     *result = mCacheEntry->ExpirationTime();
     167             289 :     return NS_OK;
     168                 : }
     169                 : 
     170                 : 
     171                 : NS_IMETHODIMP
     172            1357 : nsCacheEntryDescriptor::SetExpirationTime(PRUint32 expirationTime)
     173                 : {
     174            2714 :     nsCacheServiceAutoLock lock;
     175            1357 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     176                 : 
     177            1357 :     mCacheEntry->SetExpirationTime(expirationTime);
     178            1357 :     mCacheEntry->MarkEntryDirty();
     179            1357 :     return NS_OK;
     180                 : }
     181                 : 
     182                 : 
     183               0 : NS_IMETHODIMP nsCacheEntryDescriptor::IsStreamBased(bool *result)
     184                 : {
     185               0 :     NS_ENSURE_ARG_POINTER(result);
     186               0 :     nsCacheServiceAutoLock lock;
     187               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     188                 : 
     189               0 :     *result = mCacheEntry->IsStreamData();
     190               0 :     return NS_OK;
     191                 : }
     192                 : 
     193               0 : NS_IMETHODIMP nsCacheEntryDescriptor::GetPredictedDataSize(PRInt64 *result)
     194                 : {
     195               0 :     NS_ENSURE_ARG_POINTER(result);
     196               0 :     nsCacheServiceAutoLock lock;
     197               0 :     if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
     198                 : 
     199               0 :     *result = mCacheEntry->PredictedDataSize();
     200               0 :     return NS_OK;
     201                 : }
     202                 : 
     203            1363 : NS_IMETHODIMP nsCacheEntryDescriptor::SetPredictedDataSize(PRInt64
     204                 :                                                            predictedSize)
     205                 : {
     206            2726 :     nsCacheServiceAutoLock lock;
     207            1363 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     208                 : 
     209            1363 :     mCacheEntry->SetPredictedDataSize(predictedSize);
     210            1363 :     return NS_OK;
     211                 : }
     212                 : 
     213             536 : NS_IMETHODIMP nsCacheEntryDescriptor::GetDataSize(PRUint32 *result)
     214                 : {
     215             536 :     NS_ENSURE_ARG_POINTER(result);
     216            1072 :     nsCacheServiceAutoLock lock;
     217             536 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     218                 : 
     219             536 :     const char* val = mCacheEntry->GetMetaDataElement("uncompressed-len");
     220             536 :     if (!val) {
     221             536 :         *result = mCacheEntry->DataSize();
     222                 :     } else {
     223               0 :         *result = atol(val);
     224                 :     }
     225                 : 
     226             536 :     return NS_OK;
     227                 : }
     228                 : 
     229                 : 
     230               2 : NS_IMETHODIMP nsCacheEntryDescriptor::GetStorageDataSize(PRUint32 *result)
     231                 : {
     232               2 :     NS_ENSURE_ARG_POINTER(result);
     233               4 :     nsCacheServiceAutoLock lock;
     234               2 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     235                 : 
     236               2 :     *result = mCacheEntry->DataSize();
     237                 : 
     238               2 :     return NS_OK;
     239                 : }
     240                 : 
     241                 : 
     242                 : nsresult
     243            1496 : nsCacheEntryDescriptor::RequestDataSizeChange(PRInt32 deltaSize)
     244                 : {
     245            2992 :     nsCacheServiceAutoLock lock;
     246            1496 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     247                 : 
     248                 :     nsresult  rv;
     249            1496 :     rv = nsCacheService::OnDataSizeChange(mCacheEntry, deltaSize);
     250            1496 :     if (NS_SUCCEEDED(rv)) {
     251                 :         // XXX review for signed/unsigned math errors
     252            1496 :         PRUint32  newDataSize = mCacheEntry->DataSize() + deltaSize;
     253            1496 :         mCacheEntry->SetDataSize(newDataSize);
     254            1496 :         mCacheEntry->TouchData();
     255                 :     }
     256            1496 :     return rv;
     257                 : }
     258                 : 
     259                 : 
     260                 : NS_IMETHODIMP
     261               0 : nsCacheEntryDescriptor::SetDataSize(PRUint32 dataSize)
     262                 : {
     263               0 :     nsCacheServiceAutoLock lock;
     264               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     265                 : 
     266                 :     // XXX review for signed/unsigned math errors
     267               0 :     PRInt32  deltaSize = dataSize - mCacheEntry->DataSize();
     268                 : 
     269                 :     nsresult  rv;
     270               0 :     rv = nsCacheService::OnDataSizeChange(mCacheEntry, deltaSize);
     271                 :     // this had better be NS_OK, this call instance is advisory for memory cache objects
     272               0 :     if (NS_SUCCEEDED(rv)) {
     273                 :         // XXX review for signed/unsigned math errors
     274               0 :         PRUint32  newDataSize = mCacheEntry->DataSize() + deltaSize;
     275               0 :         mCacheEntry->SetDataSize(newDataSize);
     276               0 :         mCacheEntry->TouchData();
     277                 :     } else {
     278               0 :         NS_WARNING("failed SetDataSize() on memory cache object!");
     279                 :     }
     280                 :     
     281               0 :     return rv;
     282                 : }
     283                 : 
     284                 : 
     285                 : NS_IMETHODIMP
     286             242 : nsCacheEntryDescriptor::OpenInputStream(PRUint32 offset, nsIInputStream ** result)
     287                 : {
     288             242 :     NS_ENSURE_ARG_POINTER(result);
     289                 : 
     290                 :     {
     291             484 :         nsCacheServiceAutoLock lock;
     292             242 :         if (!mCacheEntry)                  return NS_ERROR_NOT_AVAILABLE;
     293             242 :         if (!mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
     294                 : 
     295                 :         // ensure valid permissions
     296             242 :         if (!(mAccessGranted & nsICache::ACCESS_READ))
     297               0 :             return NS_ERROR_CACHE_READ_ACCESS_DENIED;
     298                 :     }
     299                 : 
     300             242 :     nsInputStreamWrapper* cacheInput = nsnull;
     301                 :     const char *val;
     302             242 :     val = mCacheEntry->GetMetaDataElement("uncompressed-len");
     303             242 :     if (val) {
     304               0 :         cacheInput = new nsDecompressInputStreamWrapper(this, offset);
     305                 :     } else {
     306             242 :         cacheInput = new nsInputStreamWrapper(this, offset);
     307                 :     }
     308             242 :     if (!cacheInput) return NS_ERROR_OUT_OF_MEMORY;
     309                 : 
     310             242 :     NS_ADDREF(*result = cacheInput);
     311             242 :     return NS_OK;
     312                 : }
     313                 : 
     314                 : NS_IMETHODIMP
     315            1194 : nsCacheEntryDescriptor::OpenOutputStream(PRUint32 offset, nsIOutputStream ** result)
     316                 : {
     317            1194 :     NS_ENSURE_ARG_POINTER(result);
     318                 : 
     319                 :     {
     320            2388 :         nsCacheServiceAutoLock lock;
     321            1194 :         if (!mCacheEntry)                  return NS_ERROR_NOT_AVAILABLE;
     322            1194 :         if (!mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
     323                 : 
     324                 :         // ensure valid permissions
     325            1194 :         if (!(mAccessGranted & nsICache::ACCESS_WRITE))
     326               0 :             return NS_ERROR_CACHE_WRITE_ACCESS_DENIED;
     327                 :     }
     328                 : 
     329            1194 :     nsOutputStreamWrapper* cacheOutput = nsnull;
     330            1194 :     PRInt32 compressionLevel = nsCacheService::CacheCompressionLevel();
     331                 :     const char *val;
     332            1194 :     val = mCacheEntry->GetMetaDataElement("uncompressed-len");
     333            1194 :     if ((compressionLevel > 0) && val) {
     334               0 :         cacheOutput = new nsCompressOutputStreamWrapper(this, offset);
     335                 :     } else {
     336                 :         // clear compression flag when compression disabled - see bug #715198
     337            1194 :         if (val) {
     338             903 :             mCacheEntry->SetMetaDataElement("uncompressed-len", nsnull);
     339                 :         }
     340            1194 :         cacheOutput = new nsOutputStreamWrapper(this, offset);
     341                 :     }
     342            1194 :     if (!cacheOutput) return NS_ERROR_OUT_OF_MEMORY;
     343                 : 
     344            1194 :     NS_ADDREF(*result = cacheOutput);
     345            1194 :     return NS_OK;
     346                 : }
     347                 : 
     348                 : 
     349                 : NS_IMETHODIMP
     350               0 : nsCacheEntryDescriptor::GetCacheElement(nsISupports ** result)
     351                 : {
     352               0 :     NS_ENSURE_ARG_POINTER(result);
     353               0 :     nsCacheServiceAutoLock lock;
     354               0 :     if (!mCacheEntry)                 return NS_ERROR_NOT_AVAILABLE;
     355               0 :     if (mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_STREAM;
     356                 : 
     357               0 :     NS_IF_ADDREF(*result = mCacheEntry->Data());
     358               0 :     return NS_OK;
     359                 : }
     360                 : 
     361                 : 
     362                 : NS_IMETHODIMP
     363               0 : nsCacheEntryDescriptor::SetCacheElement(nsISupports * cacheElement)
     364                 : {
     365               0 :     nsCacheServiceAutoLock lock;
     366               0 :     if (!mCacheEntry)                 return NS_ERROR_NOT_AVAILABLE;
     367               0 :     if (mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_STREAM;
     368                 : 
     369               0 :     return nsCacheService::SetCacheElement(mCacheEntry, cacheElement);
     370                 : }
     371                 : 
     372                 : 
     373                 : NS_IMETHODIMP
     374            1580 : nsCacheEntryDescriptor::GetAccessGranted(nsCacheAccessMode *result)
     375                 : {
     376            1580 :     NS_ENSURE_ARG_POINTER(result);
     377            1580 :     *result = mAccessGranted;
     378            1580 :     return NS_OK;
     379                 : }
     380                 : 
     381                 : 
     382                 : NS_IMETHODIMP
     383            2244 : nsCacheEntryDescriptor::GetStoragePolicy(nsCacheStoragePolicy *result)
     384                 : {
     385            2244 :     NS_ENSURE_ARG_POINTER(result);
     386            4488 :     nsCacheServiceAutoLock lock;
     387            2244 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     388                 :     
     389            2244 :     *result = mCacheEntry->StoragePolicy();
     390            2244 :     return NS_OK;
     391                 : }
     392                 : 
     393                 : 
     394                 : NS_IMETHODIMP
     395               6 : nsCacheEntryDescriptor::SetStoragePolicy(nsCacheStoragePolicy policy)
     396                 : {
     397              12 :     nsCacheServiceAutoLock lock;
     398               6 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     399                 :     // XXX validate policy against session?
     400                 :     
     401               6 :     bool        storageEnabled = false;
     402               6 :     storageEnabled = nsCacheService::IsStorageEnabledForPolicy_Locked(policy);
     403               6 :     if (!storageEnabled)    return NS_ERROR_FAILURE;
     404                 : 
     405                 :     // Don't change the storage policy of entries we can't write
     406               5 :     if (!(mAccessGranted & nsICache::ACCESS_WRITE))
     407               0 :         return NS_ERROR_NOT_AVAILABLE;
     408                 :     
     409                 :     // Don't allow a cache entry to move from memory-only to anything else
     410               5 :     if (mCacheEntry->StoragePolicy() == nsICache::STORE_IN_MEMORY &&
     411                 :         policy != nsICache::STORE_IN_MEMORY)
     412               0 :         return NS_ERROR_NOT_AVAILABLE;
     413                 :         
     414               5 :     mCacheEntry->SetStoragePolicy(policy);
     415               5 :     mCacheEntry->MarkEntryDirty();
     416               5 :     return NS_OK;
     417                 : }
     418                 : 
     419                 : 
     420                 : NS_IMETHODIMP
     421               0 : nsCacheEntryDescriptor::GetFile(nsIFile ** result)
     422                 : {
     423               0 :     NS_ENSURE_ARG_POINTER(result);
     424               0 :     nsCacheServiceAutoLock lock;
     425               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     426                 : 
     427               0 :     return nsCacheService::GetFileForEntry(mCacheEntry, result);
     428                 : }
     429                 : 
     430                 : 
     431                 : NS_IMETHODIMP
     432             228 : nsCacheEntryDescriptor::GetSecurityInfo(nsISupports ** result)
     433                 : {
     434             228 :     NS_ENSURE_ARG_POINTER(result);
     435             456 :     nsCacheServiceAutoLock lock;
     436             228 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     437                 : 
     438             228 :     *result = mCacheEntry->SecurityInfo();
     439             228 :     NS_IF_ADDREF(*result);
     440             228 :     return NS_OK;
     441                 : }
     442                 : 
     443                 : 
     444                 : NS_IMETHODIMP
     445               4 : nsCacheEntryDescriptor::SetSecurityInfo(nsISupports * securityInfo)
     446                 : {
     447               8 :     nsCacheServiceAutoLock lock;
     448               4 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     449                 : 
     450               4 :     mCacheEntry->SetSecurityInfo(securityInfo);
     451               4 :     mCacheEntry->MarkEntryDirty();
     452               4 :     return NS_OK;
     453                 : }
     454                 : 
     455                 : 
     456                 : NS_IMETHODIMP
     457             252 : nsCacheEntryDescriptor::Doom()
     458                 : {
     459             504 :     nsCacheServiceAutoLock lock;
     460             252 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     461                 : 
     462             244 :     return nsCacheService::DoomEntry(mCacheEntry);
     463                 : }
     464                 : 
     465                 : 
     466                 : NS_IMETHODIMP
     467               0 : nsCacheEntryDescriptor::DoomAndFailPendingRequests(nsresult status)
     468                 : {
     469               0 :     nsCacheServiceAutoLock lock;
     470               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     471                 : 
     472               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     473                 : }
     474                 : 
     475                 : 
     476                 : NS_IMETHODIMP
     477             212 : nsCacheEntryDescriptor::MarkValid()
     478                 : {
     479             424 :     nsCacheServiceAutoLock lock;
     480             212 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     481                 : 
     482             212 :     nsresult  rv = nsCacheService::ValidateEntry(mCacheEntry);
     483             212 :     return rv;
     484                 : }
     485                 : 
     486                 : 
     487                 : NS_IMETHODIMP
     488            1770 : nsCacheEntryDescriptor::Close()
     489                 : {
     490            3540 :     nsCacheServiceAutoLock lock;
     491            1770 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     492                 : 
     493                 :     // XXX perhaps closing descriptors should clear/sever transports
     494                 : 
     495                 :     // tell nsCacheService we're going away
     496            1770 :     nsCacheService::CloseDescriptor(this);
     497            1770 :     NS_ASSERTION(mCacheEntry == nsnull, "mCacheEntry not null");
     498                 : 
     499            1770 :     return NS_OK;
     500                 : }
     501                 : 
     502                 : 
     503                 : NS_IMETHODIMP
     504            1395 : nsCacheEntryDescriptor::GetMetaDataElement(const char *key, char **result)
     505                 : {
     506            1395 :     NS_ENSURE_ARG_POINTER(key);
     507            1395 :     *result = nsnull;
     508                 : 
     509            2790 :     nsCacheServiceAutoLock lock;
     510            1395 :     NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_AVAILABLE);
     511                 : 
     512                 :     const char *value;
     513                 : 
     514            1395 :     value = mCacheEntry->GetMetaDataElement(key);
     515            1395 :     if (!value) return NS_ERROR_NOT_AVAILABLE;
     516                 : 
     517            1177 :     *result = NS_strdup(value);
     518            1177 :     if (!*result) return NS_ERROR_OUT_OF_MEMORY;
     519                 : 
     520            1177 :     return NS_OK;
     521                 : }
     522                 : 
     523                 : 
     524                 : NS_IMETHODIMP
     525            3941 : nsCacheEntryDescriptor::SetMetaDataElement(const char *key, const char *value)
     526                 : {
     527            3941 :     NS_ENSURE_ARG_POINTER(key);
     528                 : 
     529            7882 :     nsCacheServiceAutoLock lock;
     530            3941 :     NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_AVAILABLE);
     531                 : 
     532                 :     // XXX allow null value, for clearing key?
     533                 : 
     534            3941 :     nsresult rv = mCacheEntry->SetMetaDataElement(key, value);
     535            3941 :     if (NS_SUCCEEDED(rv))
     536            3941 :         mCacheEntry->TouchMetaData();
     537            3941 :     return rv;
     538                 : }
     539                 : 
     540                 : 
     541                 : NS_IMETHODIMP
     542               0 : nsCacheEntryDescriptor::VisitMetaData(nsICacheMetaDataVisitor * visitor)
     543                 : {
     544               0 :     nsCacheServiceAutoLock lock;  // XXX check callers, we're calling out of module
     545               0 :     NS_ENSURE_ARG_POINTER(visitor);
     546               0 :     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
     547                 : 
     548               0 :     return mCacheEntry->VisitMetaDataElements(visitor);
     549                 : }
     550                 : 
     551                 : 
     552                 : /******************************************************************************
     553                 :  * nsCacheInputStream - a wrapper for nsIInputStream keeps the cache entry
     554                 :  *                      open while referenced.
     555                 :  ******************************************************************************/
     556                 : 
     557            3601 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheEntryDescriptor::nsInputStreamWrapper,
     558                 :                               nsIInputStream)
     559                 : 
     560             242 : nsresult nsCacheEntryDescriptor::
     561                 : nsInputStreamWrapper::LazyInit()
     562                 : {
     563             484 :     nsCacheServiceAutoLock lock;
     564                 : 
     565                 :     nsCacheAccessMode mode;
     566             242 :     nsresult rv = mDescriptor->GetAccessGranted(&mode);
     567             242 :     if (NS_FAILED(rv)) return rv;
     568                 : 
     569             242 :     NS_ENSURE_TRUE(mode & nsICache::ACCESS_READ, NS_ERROR_UNEXPECTED);
     570                 : 
     571             242 :     nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
     572             242 :     if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
     573                 : 
     574                 :     rv = nsCacheService::OpenInputStreamForEntry(cacheEntry, mode,
     575                 :                                                  mStartOffset,
     576             242 :                                                  getter_AddRefs(mInput));
     577             242 :     if (NS_FAILED(rv)) return rv;
     578                 : 
     579             242 :     mInitialized = true;
     580             242 :     return NS_OK;
     581                 : }
     582                 : 
     583             242 : nsresult nsCacheEntryDescriptor::
     584                 : nsInputStreamWrapper::Close()
     585                 : {
     586             242 :     nsresult rv = EnsureInit();
     587             242 :     if (NS_FAILED(rv)) return rv;
     588                 : 
     589             242 :     return mInput->Close();
     590                 : }
     591                 : 
     592              16 : nsresult nsCacheEntryDescriptor::
     593                 : nsInputStreamWrapper::Available(PRUint32 *avail)
     594                 : {
     595              16 :     nsresult rv = EnsureInit();
     596              16 :     if (NS_FAILED(rv)) return rv;
     597                 : 
     598              16 :     return mInput->Available(avail);
     599                 : }
     600                 : 
     601             476 : nsresult nsCacheEntryDescriptor::
     602                 : nsInputStreamWrapper::Read(char *buf, PRUint32 count, PRUint32 *countRead)
     603                 : {
     604             476 :     nsresult rv = EnsureInit();
     605             476 :     if (NS_FAILED(rv)) return rv;
     606                 : 
     607             476 :     return mInput->Read(buf, count, countRead);
     608                 : }
     609                 : 
     610               0 : nsresult nsCacheEntryDescriptor::
     611                 : nsInputStreamWrapper::ReadSegments(nsWriteSegmentFun writer, void *closure,
     612                 :                                    PRUint32 count, PRUint32 *countRead)
     613                 : {
     614                 :     // cache stream not buffered
     615               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     616                 : }
     617                 : 
     618             217 : nsresult nsCacheEntryDescriptor::
     619                 : nsInputStreamWrapper::IsNonBlocking(bool *result)
     620                 : {
     621                 :     // cache streams will never return NS_BASE_STREAM_WOULD_BLOCK
     622             217 :     *result = false;
     623             217 :     return NS_OK;
     624                 : }
     625                 : 
     626                 : 
     627                 : /******************************************************************************
     628                 :  * nsDecompressInputStreamWrapper - an input stream wrapper that decompresses
     629                 :  ******************************************************************************/
     630                 : 
     631               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheEntryDescriptor::nsDecompressInputStreamWrapper,
     632                 :                               nsIInputStream)
     633                 : 
     634               0 : NS_IMETHODIMP nsCacheEntryDescriptor::
     635                 : nsDecompressInputStreamWrapper::Read(char *    buf, 
     636                 :                                      PRUint32  count, 
     637                 :                                      PRUint32 *countRead)
     638                 : {
     639               0 :     int zerr = Z_OK;
     640               0 :     nsresult rv = NS_OK;
     641                 : 
     642               0 :     if (!mStreamInitialized) {
     643               0 :         rv = InitZstream();
     644               0 :         if (NS_FAILED(rv)) {
     645               0 :             return rv;
     646                 :         }
     647                 :     }
     648                 : 
     649               0 :     mZstream.next_out = (Bytef*)buf;
     650               0 :     mZstream.avail_out = count;
     651                 : 
     652               0 :     if (mReadBufferLen < count) {
     653                 :         // Allocate a buffer for reading from the input stream. This will
     654                 :         // determine the max number of compressed bytes read from the
     655                 :         // input stream at one time. Making the buffer size proportional
     656                 :         // to the request size is not necessary, but helps minimize the
     657                 :         // number of read requests to the input stream.
     658               0 :         PRUint32 newBufLen = NS_MAX(count, (PRUint32)kMinDecompressReadBufLen);
     659                 :         unsigned char* newBuf;
     660                 :         newBuf = (unsigned char*)nsMemory::Realloc(mReadBuffer, 
     661               0 :             newBufLen);
     662               0 :         if (newBuf) {
     663               0 :             mReadBuffer = newBuf;
     664               0 :             mReadBufferLen = newBufLen;
     665                 :         }
     666               0 :         if (!mReadBuffer) {
     667               0 :             mReadBufferLen = 0;
     668               0 :             return NS_ERROR_OUT_OF_MEMORY;
     669                 :         }
     670                 :     }
     671                 : 
     672                 :     // read and inflate data until the output buffer is full, or
     673                 :     // there is no more data to read
     674               0 :     while (NS_SUCCEEDED(rv) &&
     675                 :            zerr == Z_OK && 
     676                 :            mZstream.avail_out > 0 &&
     677                 :            count > 0) {
     678               0 :         if (mZstream.avail_in == 0) {
     679                 :             rv = nsInputStreamWrapper::Read((char*)mReadBuffer, 
     680                 :                                             mReadBufferLen, 
     681               0 :                                             &mZstream.avail_in);
     682               0 :             if (NS_FAILED(rv) || !mZstream.avail_in) {
     683               0 :                 break;
     684                 :             }
     685               0 :             mZstream.next_in = mReadBuffer;
     686                 :         }
     687               0 :         zerr = inflate(&mZstream, Z_NO_FLUSH);
     688               0 :         if (zerr == Z_STREAM_END) {
     689                 :             // The compressed data may have been stored in multiple
     690                 :             // chunks/streams. To allow for this case, re-initialize 
     691                 :             // the inflate stream and continue decompressing from 
     692                 :             // the next byte.
     693               0 :             Bytef * saveNextIn = mZstream.next_in;
     694               0 :             unsigned int saveAvailIn = mZstream.avail_in;
     695               0 :             Bytef * saveNextOut = mZstream.next_out;
     696               0 :             unsigned int saveAvailOut = mZstream.avail_out;
     697               0 :             inflateReset(&mZstream);
     698               0 :             mZstream.next_in = saveNextIn;
     699               0 :             mZstream.avail_in = saveAvailIn;
     700               0 :             mZstream.next_out = saveNextOut;
     701               0 :             mZstream.avail_out = saveAvailOut;
     702               0 :             zerr = Z_OK;
     703               0 :         } else if (zerr != Z_OK) {
     704               0 :             rv = NS_ERROR_INVALID_CONTENT_ENCODING;
     705                 :         }
     706                 :     }
     707               0 :     if (NS_SUCCEEDED(rv)) {
     708               0 :         *countRead = count - mZstream.avail_out;
     709                 :     }
     710               0 :     return rv;
     711                 : }
     712                 : 
     713               0 : nsresult nsCacheEntryDescriptor::
     714                 : nsDecompressInputStreamWrapper::Close()
     715                 : {
     716               0 :     EndZstream();
     717               0 :     if (mReadBuffer) {
     718               0 :         nsMemory::Free(mReadBuffer);
     719               0 :         mReadBuffer = 0;
     720               0 :         mReadBufferLen = 0;
     721                 :     }
     722               0 :     return nsInputStreamWrapper::Close();
     723                 : }
     724                 : 
     725               0 : nsresult nsCacheEntryDescriptor::
     726                 : nsDecompressInputStreamWrapper::InitZstream()
     727                 : {
     728                 :     // Initialize zlib inflate stream
     729               0 :     mZstream.zalloc = Z_NULL;
     730               0 :     mZstream.zfree = Z_NULL;
     731               0 :     mZstream.opaque = Z_NULL;
     732               0 :     mZstream.next_out = Z_NULL;
     733               0 :     mZstream.avail_out = 0;
     734               0 :     mZstream.next_in = Z_NULL;
     735               0 :     mZstream.avail_in = 0;
     736               0 :     if (inflateInit(&mZstream) != Z_OK) {
     737               0 :         return NS_ERROR_FAILURE;
     738                 :     }
     739               0 :     mStreamInitialized = PR_TRUE;
     740               0 :     return NS_OK;
     741                 : }
     742                 : 
     743               0 : nsresult nsCacheEntryDescriptor::
     744                 : nsDecompressInputStreamWrapper::EndZstream()
     745                 : {
     746               0 :     if (mStreamInitialized && !mStreamEnded) {
     747               0 :         inflateEnd(&mZstream);
     748               0 :         mStreamEnded = PR_TRUE;
     749                 :     }
     750               0 :     return NS_OK;
     751                 : }
     752                 : 
     753                 : 
     754                 : /******************************************************************************
     755                 :  * nsOutputStreamWrapper - a wrapper for nsIOutputstream to track the amount of
     756                 :  *                         data written to a cache entry.
     757                 :  *                       - also keeps the cache entry open while referenced.
     758                 :  ******************************************************************************/
     759                 : 
     760           24254 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheEntryDescriptor::nsOutputStreamWrapper,
     761                 :                               nsIOutputStream)
     762                 : 
     763            1254 : nsresult nsCacheEntryDescriptor::
     764                 : nsOutputStreamWrapper::LazyInit()
     765                 : {
     766            2508 :     nsCacheServiceAutoLock lock;
     767                 : 
     768                 :     nsCacheAccessMode mode;
     769            1254 :     nsresult rv = mDescriptor->GetAccessGranted(&mode);
     770            1254 :     if (NS_FAILED(rv)) return rv;
     771                 : 
     772            1254 :     NS_ENSURE_TRUE(mode & nsICache::ACCESS_WRITE, NS_ERROR_UNEXPECTED);
     773                 : 
     774            1254 :     nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
     775            1254 :     if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
     776                 : 
     777            1253 :     NS_ASSERTION(mOutput == nsnull, "mOutput set in LazyInit");
     778                 : 
     779            2506 :     nsCOMPtr<nsIOutputStream> stream;
     780                 :     rv = nsCacheService::OpenOutputStreamForEntry(cacheEntry, mode, mStartOffset,
     781            1253 :                                                   getter_AddRefs(stream));
     782            1253 :     if (NS_FAILED(rv))
     783             119 :         return rv;
     784                 : 
     785            1134 :     nsCacheDevice* device = cacheEntry->CacheDevice();
     786            1134 :     if (device) {
     787                 :         // the entry has been truncated to mStartOffset bytes, inform device
     788            1134 :         PRInt32 size = cacheEntry->DataSize();
     789            1134 :         rv = device->OnDataSizeChange(cacheEntry, mStartOffset - size);
     790            1134 :         if (NS_SUCCEEDED(rv))
     791            1132 :             cacheEntry->SetDataSize(mStartOffset);
     792                 :     } else {
     793               0 :         rv = NS_ERROR_NOT_AVAILABLE;
     794                 :     }
     795                 : 
     796                 :     // If anything above failed, clean up internal state and get out of here
     797                 :     // (see bug #654926)...
     798            1134 :     if (NS_FAILED(rv)) {
     799               2 :         mDescriptor->InternalCleanup(stream);
     800               2 :         return rv;
     801                 :     }
     802                 : 
     803                 :     // ... otherwise, set members and mark initialized
     804            1132 :     mDescriptor->mOutput = mOutput = stream;
     805            1132 :     mInitialized = true;
     806            1132 :     return NS_OK;
     807                 : }
     808                 : 
     809            1496 : nsresult nsCacheEntryDescriptor::
     810                 : nsOutputStreamWrapper::OnWrite(PRUint32 count)
     811                 : {
     812            1496 :     if (count > PR_INT32_MAX)  return NS_ERROR_UNEXPECTED;
     813            1496 :     return mDescriptor->RequestDataSizeChange((PRInt32)count);
     814                 : }
     815                 : 
     816            1230 : NS_IMETHODIMP nsCacheEntryDescriptor::
     817                 : nsOutputStreamWrapper::Close()
     818                 : {
     819            1230 :     nsresult rv = EnsureInit();
     820            1230 :     if (NS_FAILED(rv)) return rv;
     821                 : 
     822            1167 :     return mOutput->Close();
     823                 : }
     824                 : 
     825               0 : NS_IMETHODIMP nsCacheEntryDescriptor::
     826                 : nsOutputStreamWrapper::Flush()
     827                 : {
     828               0 :     nsresult rv = EnsureInit();
     829               0 :     if (NS_FAILED(rv)) return rv;
     830                 : 
     831               0 :     return mOutput->Flush();
     832                 : }
     833                 : 
     834            1555 : NS_IMETHODIMP nsCacheEntryDescriptor::
     835                 : nsOutputStreamWrapper::Write(const char * buf,
     836                 :                              PRUint32     count,
     837                 :                              PRUint32 *   result)
     838                 : {
     839            1555 :     nsresult rv = EnsureInit();
     840            1555 :     if (NS_FAILED(rv)) return rv;
     841                 : 
     842            1496 :     rv = OnWrite(count);
     843            1496 :     if (NS_FAILED(rv)) return rv;
     844                 : 
     845            1496 :     return mOutput->Write(buf, count, result);
     846                 : }
     847                 : 
     848               0 : NS_IMETHODIMP nsCacheEntryDescriptor::
     849                 : nsOutputStreamWrapper::WriteFrom(nsIInputStream * inStr,
     850                 :                                  PRUint32         count,
     851                 :                                  PRUint32 *       result)
     852                 : {
     853               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     854                 : }
     855                 : 
     856               0 : NS_IMETHODIMP nsCacheEntryDescriptor::
     857                 : nsOutputStreamWrapper::WriteSegments(nsReadSegmentFun  reader,
     858                 :                                      void *            closure,
     859                 :                                      PRUint32          count,
     860                 :                                      PRUint32 *        result)
     861                 : {
     862               0 :     return NS_ERROR_NOT_IMPLEMENTED;
     863                 : }
     864                 : 
     865            2434 : NS_IMETHODIMP nsCacheEntryDescriptor::
     866                 : nsOutputStreamWrapper::IsNonBlocking(bool *result)
     867                 : {
     868                 :     // cache streams will never return NS_BASE_STREAM_WOULD_BLOCK
     869            2434 :     *result = false;
     870            2434 :     return NS_OK;
     871                 : }
     872                 : 
     873                 : 
     874                 : /******************************************************************************
     875                 :  * nsCompressOutputStreamWrapper - an output stream wrapper that compresses
     876                 :  *   data before it is written
     877                 :  ******************************************************************************/
     878                 : 
     879               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheEntryDescriptor::nsCompressOutputStreamWrapper,
     880                 :                               nsIOutputStream)
     881                 : 
     882               0 : NS_IMETHODIMP nsCacheEntryDescriptor::
     883                 : nsCompressOutputStreamWrapper::Write(const char * buf,
     884                 :                                      PRUint32     count,
     885                 :                                      PRUint32 *   result)
     886                 : {
     887               0 :     int zerr = Z_OK;
     888               0 :     nsresult rv = NS_OK;
     889                 : 
     890               0 :     if (!mStreamInitialized) {
     891               0 :         rv = InitZstream();
     892               0 :         if (NS_FAILED(rv)) {
     893               0 :             return rv;
     894                 :         }
     895                 :     }
     896                 : 
     897               0 :     if (!mWriteBuffer) {
     898                 :         // Once allocated, this buffer is referenced by the zlib stream and
     899                 :         // cannot be grown. We use 2x(initial write request) to approximate
     900                 :         // a stream buffer size proportional to request buffers.
     901               0 :         mWriteBufferLen = NS_MAX(count*2, (PRUint32)kMinCompressWriteBufLen);
     902               0 :         mWriteBuffer = (unsigned char*)nsMemory::Alloc(mWriteBufferLen);
     903               0 :         if (!mWriteBuffer) {
     904               0 :             mWriteBufferLen = 0;
     905               0 :             return NS_ERROR_OUT_OF_MEMORY;
     906                 :         }
     907               0 :         mZstream.next_out = mWriteBuffer;
     908               0 :         mZstream.avail_out = mWriteBufferLen;
     909                 :     }
     910                 : 
     911                 :     // Compress (deflate) the requested buffer. Keep going
     912                 :     // until the entire buffer has been deflated.
     913               0 :     mZstream.avail_in = count;
     914               0 :     mZstream.next_in = (Bytef*)buf;
     915               0 :     while (mZstream.avail_in > 0) {
     916               0 :         zerr = deflate(&mZstream, Z_NO_FLUSH);
     917               0 :         if (zerr == Z_STREAM_ERROR) {
     918               0 :             deflateEnd(&mZstream);
     919               0 :             mStreamInitialized = PR_FALSE;
     920               0 :             return NS_ERROR_FAILURE;
     921                 :         }
     922                 :         // Note: Z_BUF_ERROR is non-fatal and sometimes expected here.
     923                 : 
     924                 :         // If the compression stream output buffer is filled, write
     925                 :         // it out to the underlying stream wrapper.
     926               0 :         if (mZstream.avail_out == 0) {
     927               0 :             rv = WriteBuffer();
     928               0 :             if (NS_FAILED(rv)) {
     929               0 :                 deflateEnd(&mZstream);
     930               0 :                 mStreamInitialized = PR_FALSE;
     931               0 :                 return rv;
     932                 :             }
     933                 :         }
     934                 :     }
     935               0 :     *result = count;
     936               0 :     mUncompressedCount += *result;
     937               0 :     return NS_OK;
     938                 : }
     939                 : 
     940               0 : NS_IMETHODIMP nsCacheEntryDescriptor::
     941                 : nsCompressOutputStreamWrapper::Close()
     942                 : {
     943               0 :     nsresult rv = NS_OK;
     944               0 :     int zerr = 0;
     945                 : 
     946               0 :     if (mStreamInitialized) {
     947                 :         // complete compression of any data remaining in the zlib stream
     948               0 :         do {
     949               0 :             zerr = deflate(&mZstream, Z_FINISH);
     950               0 :             rv = WriteBuffer();
     951                 :         } while (zerr == Z_OK && rv == NS_OK);
     952               0 :         deflateEnd(&mZstream);
     953                 :     }
     954                 : 
     955               0 :     if (mDescriptor->CacheEntry()) {
     956               0 :         nsCAutoString uncompressedLenStr;
     957                 :         rv = mDescriptor->GetMetaDataElement("uncompressed-len",
     958               0 :                                              getter_Copies(uncompressedLenStr));
     959               0 :         if (NS_SUCCEEDED(rv)) {
     960               0 :             PRInt32 oldCount = uncompressedLenStr.ToInteger(&rv);
     961               0 :             if (NS_SUCCEEDED(rv)) {
     962               0 :                 mUncompressedCount += oldCount;
     963                 :             }
     964                 :         }
     965               0 :         uncompressedLenStr.Adopt(0);
     966               0 :         uncompressedLenStr.AppendInt(mUncompressedCount);
     967                 :         rv = mDescriptor->SetMetaDataElement("uncompressed-len",
     968               0 :             uncompressedLenStr.get());
     969                 :     }
     970                 : 
     971               0 :     if (mWriteBuffer) {
     972               0 :         nsMemory::Free(mWriteBuffer);
     973               0 :         mWriteBuffer = 0;
     974               0 :         mWriteBufferLen = 0;
     975                 :     }
     976                 : 
     977               0 :     return nsOutputStreamWrapper::Close();
     978                 : }
     979                 : 
     980               0 : nsresult nsCacheEntryDescriptor::
     981                 : nsCompressOutputStreamWrapper::InitZstream()
     982                 : {
     983                 :     // Determine compression level: Aggressive compression
     984                 :     // may impact performance on mobile devices, while a
     985                 :     // lower compression level still provides substantial
     986                 :     // space savings for many text streams.
     987               0 :     PRInt32 compressionLevel = nsCacheService::CacheCompressionLevel();
     988                 : 
     989                 :     // Initialize zlib deflate stream
     990               0 :     mZstream.zalloc = Z_NULL;
     991               0 :     mZstream.zfree = Z_NULL;
     992               0 :     mZstream.opaque = Z_NULL;
     993               0 :     if (deflateInit2(&mZstream, compressionLevel, Z_DEFLATED,
     994                 :                      MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
     995               0 :         return NS_ERROR_FAILURE;
     996                 :     }
     997               0 :     mZstream.next_in = Z_NULL;
     998               0 :     mZstream.avail_in = 0;
     999                 : 
    1000               0 :     mStreamInitialized = PR_TRUE;
    1001                 : 
    1002               0 :     return NS_OK;
    1003                 : }
    1004                 : 
    1005               0 : nsresult nsCacheEntryDescriptor::
    1006                 : nsCompressOutputStreamWrapper::WriteBuffer()
    1007                 : {
    1008               0 :     PRUint32 bytesToWrite = mWriteBufferLen - mZstream.avail_out;
    1009               0 :     PRUint32 result = 0;
    1010                 :     nsresult rv = nsCacheEntryDescriptor::nsOutputStreamWrapper::Write(
    1011               0 :         (const char *)mWriteBuffer, bytesToWrite, &result);
    1012               0 :     mZstream.next_out = mWriteBuffer;
    1013               0 :     mZstream.avail_out = mWriteBufferLen;
    1014               0 :     return rv;
    1015                 : }
    1016                 : 

Generated by: LCOV version 1.7