/image/src/imgLoader.h

http://github.com/zpao/v8monkey · C Header · 462 lines · 316 code · 76 blank · 70 comment · 7 complexity · 98fedd8c42858378a6da41900c5057cc MD5 · raw file

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