LCOV - code coverage report
Current view: directory - image/src - imgLoader.h (source / functions) Found Hit Coverage
Test: app.info Lines: 69 50 72.5 %
Date: 2012-06-02 Functions: 19 15 78.9 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       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 mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Stuart Parmenter <pavlov@netscape.com>
      25                 :  *   Ehsan Akhgari <ehsan.akhgari@gmail.com>
      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                 : #ifndef imgLoader_h__
      42                 : #define imgLoader_h__
      43                 : 
      44                 : #include "mozilla/Attributes.h"
      45                 : 
      46                 : #include "imgILoader.h"
      47                 : #include "imgICache.h"
      48                 : #include "nsWeakReference.h"
      49                 : #include "nsIContentSniffer.h"
      50                 : #include "nsRefPtrHashtable.h"
      51                 : #include "nsExpirationTracker.h"
      52                 : #include "nsAutoPtr.h"
      53                 : #include "prtypes.h"
      54                 : #include "imgRequest.h"
      55                 : #include "nsIObserverService.h"
      56                 : #include "nsIChannelPolicy.h"
      57                 : #include "nsIProgressEventSink.h"
      58                 : #include "nsIChannel.h"
      59                 : 
      60                 : #ifdef LOADER_THREADSAFE
      61                 : #include "prlock.h"
      62                 : #endif
      63                 : 
      64                 : class imgRequest;
      65                 : class imgRequestProxy;
      66                 : class imgIRequest;
      67                 : class imgIDecoderObserver;
      68                 : class nsILoadGroup;
      69                 : 
      70                 : class imgCacheEntry
      71                 : {
      72                 : public:
      73                 :   imgCacheEntry(imgRequest *request, bool aForcePrincipalCheck);
      74                 :   ~imgCacheEntry();
      75                 : 
      76              63 :   nsrefcnt AddRef()
      77                 :   {
      78              63 :     NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
      79              63 :     NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), "imgCacheEntry addref isn't thread-safe!");
      80              63 :     ++mRefCnt;
      81              63 :     NS_LOG_ADDREF(this, mRefCnt, "imgCacheEntry", sizeof(*this));
      82              63 :     return mRefCnt;
      83                 :   }
      84                 :  
      85              63 :   nsrefcnt Release()
      86                 :   {
      87              63 :     NS_PRECONDITION(0 != mRefCnt, "dup release");
      88              63 :     NS_ABORT_IF_FALSE(_mOwningThread.GetThread() == PR_GetCurrentThread(), "imgCacheEntry release isn't thread-safe!");
      89              63 :     --mRefCnt;
      90              63 :     NS_LOG_RELEASE(this, mRefCnt, "imgCacheEntry");
      91              63 :     if (mRefCnt == 0) {
      92               8 :       mRefCnt = 1; /* stabilize */
      93               8 :       delete this;
      94               8 :       return 0;
      95                 :     }
      96              55 :     return mRefCnt;                              
      97                 :   }
      98                 : 
      99              20 :   PRUint32 GetDataSize() const
     100                 :   {
     101              20 :     return mDataSize;
     102                 :   }
     103               8 :   void SetDataSize(PRUint32 aDataSize)
     104                 :   {
     105               8 :     PRInt32 oldsize = mDataSize;
     106               8 :     mDataSize = aDataSize;
     107               8 :     UpdateCache(mDataSize - oldsize);
     108               8 :   }
     109                 : 
     110               0 :   PRInt32 GetTouchedTime() const
     111                 :   {
     112               0 :     return mTouchedTime;
     113                 :   }
     114                 :   void SetTouchedTime(PRInt32 time)
     115                 :   {
     116                 :     mTouchedTime = time;
     117                 :     Touch(/* updateTime = */ false);
     118                 :   }
     119                 : 
     120              11 :   PRInt32 GetExpiryTime() const
     121                 :   {
     122              11 :     return mExpiryTime;
     123                 :   }
     124               4 :   void SetExpiryTime(PRInt32 aExpiryTime)
     125                 :   {
     126               4 :     mExpiryTime = aExpiryTime;
     127               4 :     Touch();
     128               4 :   }
     129                 : 
     130               0 :   bool GetMustValidate() const
     131                 :   {
     132               0 :     return mMustValidate;
     133                 :   }
     134               0 :   void SetMustValidate(bool aValidate)
     135                 :   {
     136               0 :     mMustValidate = aValidate;
     137               0 :     Touch();
     138               0 :   }
     139                 : 
     140              30 :   already_AddRefed<imgRequest> GetRequest() const
     141                 :   {
     142              30 :     imgRequest *req = mRequest;
     143              30 :     NS_ADDREF(req);
     144              30 :     return req;
     145                 :   }
     146                 : 
     147              29 :   bool Evicted() const
     148                 :   {
     149              29 :     return mEvicted;
     150                 :   }
     151                 : 
     152              30 :   nsExpirationState *GetExpirationState()
     153                 :   {
     154              30 :     return &mExpirationState;
     155                 :   }
     156                 : 
     157              48 :   bool HasNoProxies() const
     158                 :   {
     159              48 :     return mHasNoProxies;
     160                 :   }
     161                 : 
     162               7 :   bool ForcePrincipalCheck() const
     163                 :   {
     164               7 :     return mForcePrincipalCheck;
     165                 :   }
     166                 : 
     167                 : private: // methods
     168                 :   friend class imgLoader;
     169                 :   friend class imgCacheQueue;
     170                 :   void Touch(bool updateTime = true);
     171                 :   void UpdateCache(PRInt32 diff = 0);
     172              16 :   void SetEvicted(bool evict)
     173                 :   {
     174              16 :     mEvicted = evict;
     175              16 :   }
     176                 :   void SetHasNoProxies(bool hasNoProxies);
     177                 : 
     178                 :   // Private, unimplemented copy constructor.
     179                 :   imgCacheEntry(const imgCacheEntry &);
     180                 : 
     181                 : private: // data
     182                 :   nsAutoRefCnt mRefCnt;
     183                 :   NS_DECL_OWNINGTHREAD
     184                 : 
     185                 :   nsRefPtr<imgRequest> mRequest;
     186                 :   PRUint32 mDataSize;
     187                 :   PRInt32 mTouchedTime;
     188                 :   PRInt32 mExpiryTime;
     189                 :   nsExpirationState mExpirationState;
     190                 :   bool mMustValidate : 1;
     191                 :   bool mEvicted : 1;
     192                 :   bool mHasNoProxies : 1;
     193                 :   bool mForcePrincipalCheck : 1;
     194                 : };
     195                 : 
     196                 : #include <vector>
     197                 : 
     198                 : #define NS_IMGLOADER_CID \
     199                 : { /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */         \
     200                 :      0x9f6a0d2e,                                     \
     201                 :      0x1dd1,                                         \
     202                 :      0x11b2,                                         \
     203                 :     {0xa5, 0xb8, 0x95, 0x1f, 0x13, 0xc8, 0x46, 0xf7} \
     204                 : }
     205                 : 
     206                 : class imgCacheQueue
     207            2974 : {
     208                 : public: 
     209                 :   imgCacheQueue();
     210                 :   void Remove(imgCacheEntry *);
     211                 :   void Push(imgCacheEntry *);
     212                 :   void MarkDirty();
     213                 :   bool IsDirty();
     214                 :   already_AddRefed<imgCacheEntry> Pop();
     215                 :   void Refresh();
     216                 :   PRUint32 GetSize() const;
     217                 :   void UpdateSize(PRInt32 diff);
     218                 :   PRUint32 GetNumElements() const;
     219                 :   typedef std::vector<nsRefPtr<imgCacheEntry> > queueContainer;  
     220                 :   typedef queueContainer::iterator iterator;
     221                 :   typedef queueContainer::const_iterator const_iterator;
     222                 : 
     223                 :   iterator begin();
     224                 :   const_iterator begin() const;
     225                 :   iterator end();
     226                 :   const_iterator end() const;
     227                 : 
     228                 : private:
     229                 :   queueContainer mQueue;
     230                 :   bool mDirty;
     231                 :   PRUint32 mSize;
     232                 : };
     233                 : 
     234                 : class imgMemoryReporter;
     235                 : 
     236                 : class imgLoader : public imgILoader,
     237                 :                   public nsIContentSniffer,
     238                 :                   public imgICache,
     239                 :                   public nsSupportsWeakReference,
     240                 :                   public nsIObserver
     241                 : {
     242                 : public:
     243                 :   NS_DECL_ISUPPORTS
     244                 :   NS_DECL_IMGILOADER
     245                 :   NS_DECL_NSICONTENTSNIFFER
     246                 :   NS_DECL_IMGICACHE
     247                 :   NS_DECL_NSIOBSERVER
     248                 : 
     249                 :   imgLoader();
     250                 :   virtual ~imgLoader();
     251                 : 
     252                 :   nsresult Init();
     253                 : 
     254                 :   static nsresult GetMimeTypeFromContent(const char* aContents, PRUint32 aLength, nsACString& aContentType);
     255                 : 
     256                 :   static void Shutdown(); // for use by the factory
     257                 : 
     258                 :   static nsresult ClearChromeImageCache();
     259                 :   static nsresult ClearImageCache();
     260                 :   static void MinimizeCaches();
     261                 : 
     262                 :   static nsresult InitCache();
     263                 : 
     264                 :   static bool RemoveFromCache(nsIURI *aKey);
     265                 :   static bool RemoveFromCache(imgCacheEntry *entry);
     266                 : 
     267                 :   static bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
     268                 : 
     269                 :   // Returns true if we should prefer evicting cache entry |two| over cache
     270                 :   // entry |one|.
     271                 :   // This mixes units in the worst way, but provides reasonable results.
     272               0 :   inline static bool CompareCacheEntries(const nsRefPtr<imgCacheEntry> &one,
     273                 :                                          const nsRefPtr<imgCacheEntry> &two)
     274                 :   {
     275               0 :     if (!one)
     276               0 :       return false;
     277               0 :     if (!two)
     278               0 :       return true;
     279                 : 
     280               0 :     const double sizeweight = 1.0 - sCacheTimeWeight;
     281                 : 
     282                 :     // We want large, old images to be evicted first (depending on their
     283                 :     // relative weights). Since a larger time is actually newer, we subtract
     284                 :     // time's weight, so an older image has a larger weight.
     285               0 :     double oneweight = double(one->GetDataSize()) * sizeweight -
     286               0 :                        double(one->GetTouchedTime()) * sCacheTimeWeight;
     287               0 :     double twoweight = double(two->GetDataSize()) * sizeweight -
     288               0 :                        double(two->GetTouchedTime()) * sCacheTimeWeight;
     289                 : 
     290               0 :     return oneweight < twoweight;
     291                 :   }
     292                 : 
     293                 :   static void VerifyCacheSizes();
     294                 : 
     295                 :   // The image loader maintains a hash table of all imgCacheEntries. However,
     296                 :   // only some of them will be evicted from the cache: those who have no
     297                 :   // imgRequestProxies watching their imgRequests. 
     298                 :   //
     299                 :   // Once an imgRequest has no imgRequestProxies, it should notify us by
     300                 :   // calling HasNoObservers(), and null out its cache entry pointer.
     301                 :   // 
     302                 :   // Upon having a proxy start observing again, it should notify us by calling
     303                 :   // HasObservers(). The request's cache entry will be re-set before this
     304                 :   // happens, by calling imgRequest::SetCacheEntry() when an entry with no
     305                 :   // observers is re-requested.
     306                 :   static bool SetHasNoProxies(nsIURI *key, imgCacheEntry *entry);
     307                 :   static bool SetHasProxies(nsIURI *key);
     308                 : 
     309                 : private: // methods
     310                 : 
     311                 : 
     312                 :   bool ValidateEntry(imgCacheEntry *aEntry, nsIURI *aKey,
     313                 :                        nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, 
     314                 :                        nsILoadGroup *aLoadGroup,
     315                 :                        imgIDecoderObserver *aObserver, nsISupports *aCX,
     316                 :                        nsLoadFlags aLoadFlags, bool aCanMakeNewChannel,
     317                 :                        imgIRequest *aExistingRequest,
     318                 :                        imgIRequest **aProxyRequest,
     319                 :                        nsIChannelPolicy *aPolicy,
     320                 :                        nsIPrincipal* aLoadingPrincipal,
     321                 :                        PRInt32 aCORSMode);
     322                 :   bool ValidateRequestWithNewChannel(imgRequest *request, nsIURI *aURI,
     323                 :                                        nsIURI *aInitialDocumentURI,
     324                 :                                        nsIURI *aReferrerURI,
     325                 :                                        nsILoadGroup *aLoadGroup,
     326                 :                                        imgIDecoderObserver *aObserver,
     327                 :                                        nsISupports *aCX, nsLoadFlags aLoadFlags,
     328                 :                                        imgIRequest *aExistingRequest,
     329                 :                                        imgIRequest **aProxyRequest,
     330                 :                                        nsIChannelPolicy *aPolicy,
     331                 :                                        nsIPrincipal* aLoadingPrincipal,
     332                 :                                        PRInt32 aCORSMode);
     333                 : 
     334                 :   nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup,
     335                 :                                     imgIDecoderObserver *aObserver,
     336                 :                                     nsLoadFlags aLoadFlags, imgIRequest *aRequestProxy,
     337                 :                                     imgIRequest **_retval);
     338                 : 
     339                 :   void ReadAcceptHeaderPref();
     340                 : 
     341                 : 
     342                 :   typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
     343                 : 
     344                 :   static nsresult EvictEntries(imgCacheTable &aCacheToClear);
     345                 :   static nsresult EvictEntries(imgCacheQueue &aQueueToClear);
     346                 : 
     347                 :   static imgCacheTable &GetCache(nsIURI *aURI);
     348                 :   static imgCacheQueue &GetCacheQueue(nsIURI *aURI);
     349                 :   static void CacheEntriesChanged(nsIURI *aURI, PRInt32 sizediff = 0);
     350                 :   static void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue);
     351                 : 
     352                 : private: // data
     353                 :   friend class imgCacheEntry;
     354                 :   friend class imgMemoryReporter;
     355                 : 
     356                 :   static imgCacheTable sCache;
     357                 :   static imgCacheQueue sCacheQueue;
     358                 : 
     359                 :   static imgCacheTable sChromeCache;
     360                 :   static imgCacheQueue sChromeCacheQueue;
     361                 :   static PRFloat64 sCacheTimeWeight;
     362                 :   static PRUint32 sCacheMaxSize;
     363                 : 
     364                 :   nsCString mAcceptHeader;
     365                 : };
     366                 : 
     367                 : 
     368                 : 
     369                 : /**
     370                 :  * proxy stream listener class used to handle multipart/x-mixed-replace
     371                 :  */
     372                 : 
     373                 : #include "nsCOMPtr.h"
     374                 : #include "nsIStreamListener.h"
     375                 : 
     376                 : class ProxyListener : public nsIStreamListener
     377                 : {
     378                 : public:
     379                 :   ProxyListener(nsIStreamListener *dest);
     380                 :   virtual ~ProxyListener();
     381                 : 
     382                 :   /* additional members */
     383                 :   NS_DECL_ISUPPORTS
     384                 :   NS_DECL_NSISTREAMLISTENER
     385                 :   NS_DECL_NSIREQUESTOBSERVER
     386                 : 
     387                 : private:
     388                 :   nsCOMPtr<nsIStreamListener> mDestListener;
     389                 : };
     390                 : 
     391                 : /**
     392                 :  * A class that implements nsIProgressEventSink and forwards all calls to it to
     393                 :  * the original notification callbacks of the channel. Also implements
     394                 :  * nsIInterfaceRequestor and gives out itself for nsIProgressEventSink calls,
     395                 :  * and forwards everything else to the channel's notification callbacks.
     396                 :  */
     397                 : class nsProgressNotificationProxy MOZ_FINAL
     398                 :   : public nsIProgressEventSink
     399                 :   , public nsIChannelEventSink
     400                 :   , public nsIInterfaceRequestor
     401                 : {
     402                 :   public:
     403               4 :     nsProgressNotificationProxy(nsIChannel* channel,
     404                 :                                 imgIRequest* proxy)
     405               4 :         : mImageRequest(proxy) {
     406               4 :       channel->GetNotificationCallbacks(getter_AddRefs(mOriginalCallbacks));
     407               4 :     }
     408                 : 
     409                 :     NS_DECL_ISUPPORTS
     410                 :     NS_DECL_NSIPROGRESSEVENTSINK
     411                 :     NS_DECL_NSICHANNELEVENTSINK
     412                 :     NS_DECL_NSIINTERFACEREQUESTOR
     413                 :   private:
     414               4 :     ~nsProgressNotificationProxy() {}
     415                 : 
     416                 :     nsCOMPtr<nsIInterfaceRequestor> mOriginalCallbacks;
     417                 :     nsCOMPtr<nsIRequest> mImageRequest;
     418                 : };
     419                 : 
     420                 : /**
     421                 :  * validate checker
     422                 :  */
     423                 : 
     424                 : #include "nsCOMArray.h"
     425                 : 
     426                 : class imgCacheValidator : public nsIStreamListener,
     427                 :                           public nsIChannelEventSink,
     428                 :                           public nsIInterfaceRequestor,
     429                 :                           public nsIAsyncVerifyRedirectCallback
     430                 : {
     431                 : public:
     432                 :   imgCacheValidator(nsProgressNotificationProxy* progress, imgRequest *request,
     433                 :                     void *aContext, bool forcePrincipalCheckForCacheEntry);
     434                 :   virtual ~imgCacheValidator();
     435                 : 
     436                 :   void AddProxy(imgRequestProxy *aProxy);
     437                 : 
     438                 :   NS_DECL_ISUPPORTS
     439                 :   NS_DECL_NSISTREAMLISTENER
     440                 :   NS_DECL_NSIREQUESTOBSERVER
     441                 :   NS_DECL_NSICHANNELEVENTSINK
     442                 :   NS_DECL_NSIINTERFACEREQUESTOR
     443                 :   NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
     444                 : 
     445                 : private:
     446                 :   nsCOMPtr<nsIStreamListener> mDestListener;
     447                 :   nsRefPtr<nsProgressNotificationProxy> mProgressProxy;
     448                 :   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
     449                 :   nsCOMPtr<nsIChannel> mRedirectChannel;
     450                 : 
     451                 :   nsRefPtr<imgRequest> mRequest;
     452                 :   nsCOMArray<imgIRequest> mProxies;
     453                 : 
     454                 :   nsRefPtr<imgRequest> mNewRequest;
     455                 :   nsRefPtr<imgCacheEntry> mNewEntry;
     456                 : 
     457                 :   void *mContext;
     458                 : 
     459                 :   static imgLoader sImgLoader;
     460                 : };
     461                 : 
     462                 : #endif  // imgLoader_h__

Generated by: LCOV version 1.7