2013-01-17 16:45:11 -08:00
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 04:12:37 -07:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
2007-03-22 10:30:00 -07:00
2012-01-02 12:23:41 -08:00
# include "mozilla/Attributes.h"
# include "mozilla/Preferences.h"
2012-10-12 05:43:01 -07:00
# include "mozilla/ClearOnShutdown.h"
2012-01-02 12:23:41 -08:00
2011-07-08 10:55:03 -07:00
# include "ImageLogging.h"
2013-09-28 11:28:42 -07:00
# include "nsPrintfCString.h"
2007-03-22 10:30:00 -07:00
# include "imgLoader.h"
2010-08-13 21:09:48 -07:00
# include "imgRequestProxy.h"
2010-05-21 21:10:14 -07:00
2007-03-22 10:30:00 -07:00
# include "nsCOMPtr.h"
2011-07-14 11:47:34 -07:00
# include "nsContentUtils.h"
# include "nsCrossSiteListenerProxy.h"
2007-03-22 10:30:00 -07:00
# include "nsNetUtil.h"
2013-01-08 13:40:47 -08:00
# include "nsMimeTypes.h"
2011-06-24 07:22:33 -07:00
# include "nsStreamUtils.h"
2007-03-22 10:30:00 -07:00
# include "nsIHttpChannel.h"
# include "nsICachingChannel.h"
2009-07-28 09:13:48 -07:00
# include "nsIInterfaceRequestor.h"
# include "nsIProgressEventSink.h"
2009-08-13 04:20:41 -07:00
# include "nsIChannelEventSink.h"
2010-08-04 19:15:55 -07:00
# include "nsIAsyncVerifyRedirectCallback.h"
2008-09-04 16:00:42 -07:00
# include "nsIFileURL.h"
2007-03-22 10:30:00 -07:00
# include "nsCRT.h"
2010-12-20 08:21:59 -08:00
# include "nsIDocument.h"
2014-06-03 13:37:46 -07:00
# include "nsINetworkPredictor.h"
2007-03-22 10:30:00 -07:00
2009-01-04 21:52:22 -08:00
# include "nsIApplicationCache.h"
# include "nsIApplicationCacheContainer.h"
2010-05-21 21:10:14 -07:00
# include "nsIMemoryReporter.h"
2013-09-07 06:01:08 -07:00
# include "Image.h"
# include "DiscardTracker.h"
2010-05-21 21:10:14 -07:00
2007-03-22 10:30:00 -07:00
// we want to explore making the document own the load group
// so we can associate the document URI with the load group.
// until this point, we have an evil hack:
2013-03-29 13:14:19 -07:00
# include "nsIHttpChannelInternal.h"
2012-06-25 21:20:12 -07:00
# include "nsILoadContext.h"
2013-04-09 10:38:48 -07:00
# include "nsILoadGroupChild.h"
2007-03-22 10:30:00 -07:00
2011-06-11 19:30:15 -07:00
using namespace mozilla ;
2012-01-06 08:02:27 -08:00
using namespace mozilla : : image ;
2010-08-13 21:09:49 -07:00
2013-12-07 21:38:32 -08:00
MOZ_DEFINE_MALLOC_SIZE_OF ( ImagesMallocSizeOf )
2012-03-01 16:05:32 -08:00
2013-12-07 21:39:47 -08:00
class imgMemoryReporter MOZ_FINAL : public nsIMemoryReporter
2010-05-21 21:10:14 -07:00
{
2014-06-23 11:49:08 -07:00
~ imgMemoryReporter ( ) { }
2010-05-21 21:10:14 -07:00
public :
2013-12-07 21:39:47 -08:00
NS_DECL_ISUPPORTS
2011-06-05 18:22:45 -07:00
2014-05-15 16:11:57 -07:00
NS_IMETHOD CollectReports ( nsIMemoryReporterCallback * aHandleReport ,
2014-05-20 23:06:54 -07:00
nsISupports * aData , bool aAnonymize )
2010-05-21 21:10:14 -07:00
{
2014-05-15 16:11:57 -07:00
nsresult rv ;
ImageSizes chrome ;
ImageSizes content ;
2014-09-05 14:36:11 -07:00
ImageSizes uncached ;
2012-06-25 21:20:12 -07:00
2012-09-06 07:11:28 -07:00
for ( uint32_t i = 0 ; i < mKnownLoaders . Length ( ) ; i + + ) {
2014-05-15 16:11:57 -07:00
mKnownLoaders [ i ] - > mChromeCache . EnumerateRead ( EntryImageSizes , & chrome ) ;
mKnownLoaders [ i ] - > mCache . EnumerateRead ( EntryImageSizes , & content ) ;
2014-09-05 14:36:11 -07:00
MutexAutoLock lock ( mKnownLoaders [ i ] - > mUncachedImagesMutex ) ;
mKnownLoaders [ i ] - > mUncachedImages . EnumerateEntries ( EntryUncachedImageSizes , & uncached ) ;
2012-06-25 21:20:12 -07:00
}
2012-03-01 16:05:32 -08:00
2014-05-20 23:06:54 -07:00
// Note that we only need to anonymize content image URIs.
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , chrome . mRasterUsedImageInfo ,
" images/chrome/raster/used " ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , chrome . mRasterUnusedImageInfo ,
" images/chrome/raster/unused " ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , chrome . mVectorUsedImageDocInfo ,
" images/chrome/vector/used/documents " ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , chrome . mVectorUnusedImageDocInfo ,
" images/chrome/vector/unused/documents " ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , content . mRasterUsedImageInfo ,
2014-05-20 23:06:54 -07:00
" images/content/raster/used " , aAnonymize ) ;
2014-05-15 16:11:57 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , content . mRasterUnusedImageInfo ,
2014-05-20 23:06:54 -07:00
" images/content/raster/unused " , aAnonymize ) ;
2014-05-15 16:11:57 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , content . mVectorUsedImageDocInfo ,
2014-05-20 23:06:54 -07:00
" images/content/vector/used/documents " , aAnonymize ) ;
2014-05-15 16:11:57 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-05-15 16:11:57 -07:00
rv = ReportInfoArray ( aHandleReport , aData , content . mVectorUnusedImageDocInfo ,
2014-05-20 23:06:54 -07:00
" images/content/vector/unused/documents " , aAnonymize ) ;
2014-05-15 16:11:57 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2014-05-08 02:53:00 -07:00
2014-09-05 14:36:11 -07:00
// The uncached images can contain both content and chrome images, so anonymize it.
rv = ReportInfoArray ( aHandleReport , aData , uncached . mRasterUsedImageInfo ,
" images/uncached/raster/used " , aAnonymize ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = ReportInfoArray ( aHandleReport , aData , uncached . mRasterUnusedImageInfo ,
" images/uncached/raster/unused " , aAnonymize ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = ReportInfoArray ( aHandleReport , aData , uncached . mVectorUsedImageDocInfo ,
" images/uncached/vector/used/documents " , aAnonymize ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = ReportInfoArray ( aHandleReport , aData , uncached . mVectorUnusedImageDocInfo ,
" images/uncached/vector/unused/documents " , aAnonymize ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2010-05-21 21:10:14 -07:00
return NS_OK ;
}
2013-09-19 15:52:30 -07:00
static int64_t ImagesContentUsedUncompressedDistinguishedAmount ( )
2010-05-21 21:10:14 -07:00
{
2012-03-01 16:05:32 -08:00
size_t n = 0 ;
2012-09-06 07:11:28 -07:00
for ( uint32_t i = 0 ; i < imgLoader : : sMemReporter - > mKnownLoaders . Length ( ) ; i + + ) {
2012-06-25 21:20:12 -07:00
imgLoader : : sMemReporter - > mKnownLoaders [ i ] - > mCache . EnumerateRead ( EntryUsedUncompressedSize , & n ) ;
}
2012-03-01 16:05:32 -08:00
return n ;
2010-05-21 21:10:14 -07:00
}
2012-06-25 21:20:12 -07:00
void RegisterLoader ( imgLoader * aLoader )
{
mKnownLoaders . AppendElement ( aLoader ) ;
}
void UnregisterLoader ( imgLoader * aLoader )
{
mKnownLoaders . RemoveElement ( aLoader ) ;
}
2012-03-01 16:05:32 -08:00
private :
2012-06-25 21:20:12 -07:00
nsTArray < imgLoader * > mKnownLoaders ;
2014-05-15 16:11:57 -07:00
struct RasterSizes
{
size_t mRaw ;
size_t mUncompressedHeap ;
size_t mUncompressedNonheap ;
RasterSizes ( )
: mRaw ( 0 )
, mUncompressedHeap ( 0 )
, mUncompressedNonheap ( 0 )
{ }
void add ( const RasterSizes & aOther )
{
mRaw + = aOther . mRaw ;
mUncompressedHeap + = aOther . mUncompressedHeap ;
mUncompressedNonheap + = aOther . mUncompressedNonheap ;
}
bool isNotable ( ) const
{
const size_t NotableThreshold = 16 * 1024 ;
size_t total = mRaw + mUncompressedHeap + mUncompressedNonheap ;
return total > = NotableThreshold ;
}
} ;
struct VectorDocSizes
{
2014-05-08 02:53:00 -07:00
size_t mSize ;
2014-05-15 16:11:57 -07:00
VectorDocSizes ( )
: mSize ( 0 )
{ }
void add ( const VectorDocSizes & aOther )
{
mSize + = aOther . mSize ;
}
bool isNotable ( ) const
{
const size_t NotableThreshold = 16 * 1024 ;
size_t total = mSize ;
return total > = NotableThreshold ;
}
} ;
template < typename ImageSizes >
struct ImageInfo
{
ImageSizes mSizes ;
2014-05-08 05:31:55 -07:00
nsCString mURI ;
2014-05-08 02:53:00 -07:00
} ;
2014-05-15 16:11:57 -07:00
struct ImageSizes
{
nsTArray < ImageInfo < RasterSizes > > mRasterUsedImageInfo ;
nsTArray < ImageInfo < RasterSizes > > mRasterUnusedImageInfo ;
nsTArray < ImageInfo < VectorDocSizes > > mVectorUsedImageDocInfo ;
nsTArray < ImageInfo < VectorDocSizes > > mVectorUnusedImageDocInfo ;
2010-05-21 21:10:14 -07:00
} ;
2014-05-15 16:11:57 -07:00
// Definitions specialized for raster and vector images are below.
template < typename Sizes >
nsresult ReportSizes ( nsIMemoryReporterCallback * aHandleReport ,
nsISupports * aData ,
const nsACString & aPathPrefix ,
const nsACString & aLocation ,
Sizes aSizes ) ;
// This is used to report all images of a single kind, e.g. all
// "chrome/raster/used" images.
template < typename Sizes >
nsresult ReportInfoArray ( nsIMemoryReporterCallback * aHandleReport ,
nsISupports * aData ,
const nsTArray < ImageInfo < Sizes > > & aInfoArray ,
2014-05-20 23:06:54 -07:00
const char * aPathPartStr , bool aAnonymize = false )
2014-05-15 16:11:57 -07:00
{
nsresult rv ;
Sizes totalSizes ;
Sizes nonNotableSizes ;
nsCString pathPart ( aPathPartStr ) ;
nsCString explicitPathPrefix ( aPathPartStr ) ;
explicitPathPrefix . Insert ( " explicit/ " , 0 ) ;
// Report notable images, and compute total and non-notable aggregate sizes.
for ( uint32_t i = 0 ; i < aInfoArray . Length ( ) ; i + + ) {
ImageInfo < Sizes > info = aInfoArray [ i ] ;
2014-05-20 23:06:54 -07:00
if ( aAnonymize ) {
info . mURI . Truncate ( ) ;
info . mURI . AppendPrintf ( " <anonymized-%u> " , i ) ;
} else {
// info.mURI can be a data: URI, and thus extremely long. Truncate if
// necessary.
static const size_t max = 256 ;
if ( info . mURI . Length ( ) > max ) {
info . mURI . Truncate ( max ) ;
info . mURI . AppendLiteral ( " (truncated) " ) ;
}
info . mURI . ReplaceChar ( ' / ' , ' \\ ' ) ;
2014-05-15 16:11:57 -07:00
}
totalSizes . add ( info . mSizes ) ;
if ( ! info . mSizes . isNotable ( ) ) {
nonNotableSizes . add ( info . mSizes ) ;
} else {
// Report the notable image.
rv = ReportSizes ( aHandleReport , aData , explicitPathPrefix ,
info . mURI , info . mSizes ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
}
// Report non-notable images in aggregate.
rv = ReportSizes ( aHandleReport , aData , explicitPathPrefix ,
NS_LITERAL_CSTRING ( " <non-notable images> " ) ,
nonNotableSizes ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Report image totals in aggregate, without the "explicit/" prefix.
rv = ReportSizes ( aHandleReport , aData , pathPart , EmptyCString ( ) ,
totalSizes ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
static PLDHashOperator EntryImageSizes ( const nsACString & ,
imgCacheEntry * aEntry ,
void * aUserArg )
2010-05-21 21:10:14 -07:00
{
2014-05-15 16:11:57 -07:00
nsRefPtr < imgRequest > req = aEntry - > GetRequest ( ) ;
2010-10-06 08:37:12 -07:00
Image * image = static_cast < Image * > ( req - > mImage . get ( ) ) ;
2012-03-01 16:05:32 -08:00
if ( image ) {
2014-05-15 16:11:57 -07:00
ImageSizes * sizes = static_cast < ImageSizes * > ( aUserArg ) ;
nsRefPtr < ImageURL > imageURL ( image - > GetURI ( ) ) ;
nsAutoCString spec ;
imageURL - > GetSpec ( spec ) ;
ImageInfo < RasterSizes > rasterInfo ;
rasterInfo . mSizes . mRaw =
2012-03-01 16:05:32 -08:00
image - > HeapSizeOfSourceWithComputedFallback ( ImagesMallocSizeOf ) ;
2014-05-15 16:11:57 -07:00
rasterInfo . mSizes . mUncompressedHeap =
2012-03-01 16:05:32 -08:00
image - > HeapSizeOfDecodedWithComputedFallback ( ImagesMallocSizeOf ) ;
2014-05-15 16:11:57 -07:00
rasterInfo . mSizes . mUncompressedNonheap = image - > NonHeapSizeOfDecoded ( ) ;
rasterInfo . mURI = spec . get ( ) ;
if ( ! aEntry - > HasNoProxies ( ) ) {
sizes - > mRasterUsedImageInfo . AppendElement ( rasterInfo ) ;
2012-03-01 16:05:32 -08:00
} else {
2014-05-15 16:11:57 -07:00
sizes - > mRasterUnusedImageInfo . AppendElement ( rasterInfo ) ;
2012-03-01 16:05:32 -08:00
}
2014-05-15 16:11:57 -07:00
ImageInfo < VectorDocSizes > vectorInfo ;
vectorInfo . mSizes . mSize =
image - > HeapSizeOfVectorImageDocument ( & vectorInfo . mURI ) ;
if ( ! vectorInfo . mURI . IsEmpty ( ) ) {
if ( ! aEntry - > HasNoProxies ( ) ) {
sizes - > mVectorUsedImageDocInfo . AppendElement ( vectorInfo ) ;
} else {
sizes - > mVectorUnusedImageDocInfo . AppendElement ( vectorInfo ) ;
}
2014-05-08 02:53:00 -07:00
}
2010-05-21 21:10:14 -07:00
}
return PL_DHASH_NEXT ;
}
2014-09-05 14:36:11 -07:00
static PLDHashOperator EntryUncachedImageSizes ( nsPtrHashKey < imgRequest > * aEntry ,
void * aUserArg )
{
nsRefPtr < imgRequest > req = aEntry - > GetKey ( ) ;
Image * image = static_cast < Image * > ( req - > mImage . get ( ) ) ;
if ( image ) {
ImageSizes * sizes = static_cast < ImageSizes * > ( aUserArg ) ;
nsRefPtr < ImageURL > imageURL ( image - > GetURI ( ) ) ;
nsAutoCString spec ;
imageURL - > GetSpec ( spec ) ;
ImageInfo < RasterSizes > rasterInfo ;
rasterInfo . mSizes . mRaw =
image - > HeapSizeOfSourceWithComputedFallback ( ImagesMallocSizeOf ) ;
rasterInfo . mSizes . mUncompressedHeap =
image - > HeapSizeOfDecodedWithComputedFallback ( ImagesMallocSizeOf ) ;
rasterInfo . mSizes . mUncompressedNonheap = image - > NonHeapSizeOfDecoded ( ) ;
rasterInfo . mURI = spec . get ( ) ;
if ( req - > HasConsumers ( ) ) {
sizes - > mRasterUsedImageInfo . AppendElement ( rasterInfo ) ;
} else {
sizes - > mRasterUnusedImageInfo . AppendElement ( rasterInfo ) ;
}
ImageInfo < VectorDocSizes > vectorInfo ;
vectorInfo . mSizes . mSize =
image - > HeapSizeOfVectorImageDocument ( & vectorInfo . mURI ) ;
if ( ! vectorInfo . mURI . IsEmpty ( ) ) {
if ( req - > HasConsumers ( ) ) {
sizes - > mVectorUsedImageDocInfo . AppendElement ( vectorInfo ) ;
} else {
sizes - > mVectorUnusedImageDocInfo . AppendElement ( vectorInfo ) ;
}
}
}
return PL_DHASH_NEXT ;
}
2012-03-01 16:05:32 -08:00
static PLDHashOperator EntryUsedUncompressedSize ( const nsACString & ,
2014-05-15 16:11:57 -07:00
imgCacheEntry * aEntry ,
void * aUserArg )
2011-06-16 11:34:09 -07:00
{
2014-05-15 16:11:57 -07:00
if ( ! aEntry - > HasNoProxies ( ) ) {
size_t * n = static_cast < size_t * > ( aUserArg ) ;
nsRefPtr < imgRequest > req = aEntry - > GetRequest ( ) ;
2012-03-01 16:05:32 -08:00
Image * image = static_cast < Image * > ( req - > mImage . get ( ) ) ;
if ( image ) {
2014-05-15 16:11:57 -07:00
// Both this and EntryImageSizes measure
// images/content/raster/used/uncompressed memory. This function's
// measurement is secondary -- the result doesn't go in the "explicit"
// tree -- so we use moz_malloc_size_of instead of ImagesMallocSizeOf
// to prevent DMD from seeing it reported twice.
2012-12-18 14:50:59 -08:00
* n + = image - > HeapSizeOfDecodedWithComputedFallback ( moz_malloc_size_of ) ;
2012-03-01 16:05:32 -08:00
* n + = image - > NonHeapSizeOfDecoded ( ) ;
}
2011-06-16 11:34:09 -07:00
}
2010-05-21 21:10:14 -07:00
2012-03-01 16:05:32 -08:00
return PL_DHASH_NEXT ;
}
2010-05-21 21:10:14 -07:00
} ;
2014-05-15 16:11:57 -07:00
// Specialisation of this method for raster images.
template < >
nsresult imgMemoryReporter : : ReportSizes (
nsIMemoryReporterCallback * aHandleReport , nsISupports * aData ,
const nsACString & aPathPrefix , const nsACString & aLocation ,
RasterSizes aSizes )
{
# define REPORT(_pathPrefix, _pathSuffix, _location, _kind, _amount, _desc) \
do { \
if ( _amount > 0 ) { \
nsCString path ( _pathPrefix ) ; \
path . Append ( " / " ) ; \
if ( ! _location . IsEmpty ( ) ) { \
path . Append ( " image( " ) ; \
path . Append ( _location ) ; \
path . Append ( " )/ " ) ; \
} \
path . Append ( _pathSuffix ) ; \
nsresult rv ; \
rv = aHandleReport - > Callback ( EmptyCString ( ) , path , _kind , UNITS_BYTES , \
_amount , NS_LITERAL_CSTRING ( _desc ) , aData ) ; \
NS_ENSURE_SUCCESS ( rv , rv ) ; \
} \
} while ( 0 )
REPORT ( aPathPrefix , " raw " , aLocation , KIND_HEAP ,
aSizes . mRaw , " Compressed image data. " ) ;
REPORT ( aPathPrefix , " uncompressed-heap " , aLocation , KIND_HEAP ,
aSizes . mUncompressedHeap , " Uncompressed image data. " ) ;
REPORT ( aPathPrefix , " uncompressed-nonheap " , aLocation , KIND_NONHEAP ,
aSizes . mUncompressedNonheap , " Uncompressed image data. " ) ;
# undef REPORT
return NS_OK ;
}
// Specialisation of this method for vector images.
template < >
nsresult imgMemoryReporter : : ReportSizes (
nsIMemoryReporterCallback * aHandleReport , nsISupports * aData ,
const nsACString & aPathPrefix , const nsACString & aLocation ,
VectorDocSizes aSizes )
{
# define REPORT(_pathPrefix, _location, _amount, _desc) \
do { \
if ( _amount > 0 ) { \
nsCString path ( _pathPrefix ) ; \
if ( ! _location . IsEmpty ( ) ) { \
path . Append ( " /document( " ) ; \
path . Append ( _location ) ; \
path . Append ( " ) " ) ; \
} \
nsresult rv ; \
rv = aHandleReport - > Callback ( EmptyCString ( ) , path , KIND_HEAP , \
UNITS_BYTES , _amount , \
NS_LITERAL_CSTRING ( _desc ) , aData ) ; \
NS_ENSURE_SUCCESS ( rv , rv ) ; \
} \
} while ( 0 )
REPORT ( aPathPrefix , aLocation , aSizes . mSize ,
" Parsed vector image documents. " ) ;
# undef REPORT
return NS_OK ;
}
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( imgMemoryReporter , nsIMemoryReporter )
2013-12-07 21:39:47 -08:00
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( nsProgressNotificationProxy ,
nsIProgressEventSink ,
nsIChannelEventSink ,
nsIInterfaceRequestor )
2009-07-28 09:13:48 -07:00
NS_IMETHODIMP
nsProgressNotificationProxy : : OnProgress ( nsIRequest * request ,
nsISupports * ctxt ,
2012-08-22 08:56:38 -07:00
uint64_t progress ,
uint64_t progressMax )
2011-07-01 10:03:30 -07:00
{
2009-07-28 09:13:48 -07:00
nsCOMPtr < nsILoadGroup > loadGroup ;
2010-11-21 11:21:57 -08:00
request - > GetLoadGroup ( getter_AddRefs ( loadGroup ) ) ;
2009-07-28 09:13:48 -07:00
nsCOMPtr < nsIProgressEventSink > target ;
NS_QueryNotificationCallbacks ( mOriginalCallbacks ,
loadGroup ,
NS_GET_IID ( nsIProgressEventSink ) ,
getter_AddRefs ( target ) ) ;
if ( ! target )
return NS_OK ;
return target - > OnProgress ( mImageRequest , ctxt , progress , progressMax ) ;
}
NS_IMETHODIMP
nsProgressNotificationProxy : : OnStatus ( nsIRequest * request ,
nsISupports * ctxt ,
nsresult status ,
2014-01-04 07:02:17 -08:00
const char16_t * statusArg )
2011-07-01 10:03:30 -07:00
{
2009-07-28 09:13:48 -07:00
nsCOMPtr < nsILoadGroup > loadGroup ;
2010-11-21 11:21:57 -08:00
request - > GetLoadGroup ( getter_AddRefs ( loadGroup ) ) ;
2009-07-28 09:13:48 -07:00
nsCOMPtr < nsIProgressEventSink > target ;
NS_QueryNotificationCallbacks ( mOriginalCallbacks ,
loadGroup ,
NS_GET_IID ( nsIProgressEventSink ) ,
getter_AddRefs ( target ) ) ;
if ( ! target )
return NS_OK ;
return target - > OnStatus ( mImageRequest , ctxt , status , statusArg ) ;
}
2009-08-13 04:20:41 -07:00
NS_IMETHODIMP
2010-08-04 19:15:55 -07:00
nsProgressNotificationProxy : : AsyncOnChannelRedirect ( nsIChannel * oldChannel ,
nsIChannel * newChannel ,
2012-08-22 08:56:38 -07:00
uint32_t flags ,
2011-07-01 10:03:30 -07:00
nsIAsyncVerifyRedirectCallback * cb )
{
2009-08-13 04:20:41 -07:00
// Tell the original original callbacks about it too
nsCOMPtr < nsILoadGroup > loadGroup ;
2010-11-21 11:21:57 -08:00
newChannel - > GetLoadGroup ( getter_AddRefs ( loadGroup ) ) ;
2009-08-13 04:20:41 -07:00
nsCOMPtr < nsIChannelEventSink > target ;
NS_QueryNotificationCallbacks ( mOriginalCallbacks ,
loadGroup ,
NS_GET_IID ( nsIChannelEventSink ) ,
getter_AddRefs ( target ) ) ;
2010-08-04 19:15:55 -07:00
if ( ! target ) {
cb - > OnRedirectVerifyCallback ( NS_OK ) ;
return NS_OK ;
}
// Delegate to |target| if set, reusing |cb|
return target - > AsyncOnChannelRedirect ( oldChannel , newChannel , flags , cb ) ;
2009-08-13 04:20:41 -07:00
}
2009-07-28 09:13:48 -07:00
NS_IMETHODIMP
nsProgressNotificationProxy : : GetInterface ( const nsIID & iid ,
2011-07-01 10:03:30 -07:00
void * * result )
{
2009-07-28 09:13:48 -07:00
if ( iid . Equals ( NS_GET_IID ( nsIProgressEventSink ) ) ) {
* result = static_cast < nsIProgressEventSink * > ( this ) ;
2009-07-28 10:46:04 -07:00
NS_ADDREF_THIS ( ) ;
2009-07-28 09:13:48 -07:00
return NS_OK ;
}
2009-08-13 04:20:41 -07:00
if ( iid . Equals ( NS_GET_IID ( nsIChannelEventSink ) ) ) {
* result = static_cast < nsIChannelEventSink * > ( this ) ;
NS_ADDREF_THIS ( ) ;
return NS_OK ;
}
2009-07-28 09:13:48 -07:00
if ( mOriginalCallbacks )
return mOriginalCallbacks - > GetInterface ( iid , result ) ;
return NS_NOINTERFACE ;
}
2012-06-25 21:20:12 -07:00
static void NewRequestAndEntry ( bool aForcePrincipalCheckForCacheEntry , imgLoader * aLoader ,
2011-10-01 09:14:40 -07:00
imgRequest * * aRequest , imgCacheEntry * * aEntry )
2008-09-04 09:36:27 -07:00
{
2012-06-25 21:20:12 -07:00
nsRefPtr < imgRequest > request = new imgRequest ( aLoader ) ;
nsRefPtr < imgCacheEntry > entry = new imgCacheEntry ( aLoader , request , aForcePrincipalCheckForCacheEntry ) ;
2014-09-05 14:36:11 -07:00
aLoader - > AddToUncachedImages ( request ) ;
2011-10-01 09:14:40 -07:00
request . forget ( aRequest ) ;
entry . forget ( aEntry ) ;
2008-09-04 16:00:42 -07:00
}
2008-09-04 09:36:27 -07:00
2011-09-28 23:19:26 -07:00
static bool ShouldRevalidateEntry ( imgCacheEntry * aEntry ,
2007-03-22 10:30:00 -07:00
nsLoadFlags aFlags ,
2011-09-28 23:19:26 -07:00
bool aHasExpired )
2007-03-22 10:30:00 -07:00
{
2011-09-28 23:19:26 -07:00
bool bValidateEntry = false ;
2007-03-22 10:30:00 -07:00
2008-09-04 16:00:42 -07:00
if ( aFlags & nsIRequest : : LOAD_BYPASS_CACHE )
2011-10-17 07:59:28 -07:00
return false ;
2007-03-22 10:30:00 -07:00
if ( aFlags & nsIRequest : : VALIDATE_ALWAYS ) {
2011-10-17 07:59:28 -07:00
bValidateEntry = true ;
2007-03-22 10:30:00 -07:00
}
2011-07-01 10:03:35 -07:00
else if ( aEntry - > GetMustValidate ( ) ) {
2011-10-17 07:59:28 -07:00
bValidateEntry = true ;
2011-07-01 10:03:35 -07:00
}
2007-03-22 10:30:00 -07:00
//
// The cache entry has expired... Determine whether the stale cache
// entry can be used without validation...
//
else if ( aHasExpired ) {
//
// VALIDATE_NEVER and VALIDATE_ONCE_PER_SESSION allow stale cache
// entries to be used unless they have been explicitly marked to
// indicate that revalidation is necessary.
//
2013-03-29 13:14:19 -07:00
if ( aFlags & ( nsIRequest : : VALIDATE_NEVER |
nsIRequest : : VALIDATE_ONCE_PER_SESSION ) )
2007-03-22 10:30:00 -07:00
{
2011-10-17 07:59:28 -07:00
bValidateEntry = false ;
2007-03-22 10:30:00 -07:00
}
//
// LOAD_FROM_CACHE allows a stale cache entry to be used... Otherwise,
// the entry must be revalidated.
//
else if ( ! ( aFlags & nsIRequest : : LOAD_FROM_CACHE ) ) {
2011-10-17 07:59:28 -07:00
bValidateEntry = true ;
2007-03-22 10:30:00 -07:00
}
}
return bValidateEntry ;
}
2011-07-14 11:47:34 -07:00
// Returns true if this request is compatible with the given CORS mode on the
// given loading principal, and false if the request may not be reused due
// to CORS.
static bool
2011-09-20 14:00:42 -07:00
ValidateCORSAndPrincipal ( imgRequest * request , bool forcePrincipalCheck ,
2012-08-22 08:56:38 -07:00
int32_t corsmode , nsIPrincipal * loadingPrincipal )
2011-07-14 11:47:34 -07:00
{
// If the entry's CORS mode doesn't match, or the CORS mode matches but the
// document principal isn't the same, we can't use this request.
if ( request - > GetCORSMode ( ) ! = corsmode ) {
return false ;
2011-09-20 14:00:42 -07:00
} else if ( request - > GetCORSMode ( ) ! = imgIRequest : : CORS_NONE | |
forcePrincipalCheck ) {
2011-07-14 11:47:34 -07:00
nsCOMPtr < nsIPrincipal > otherprincipal = request - > GetLoadingPrincipal ( ) ;
// If we previously had a principal, but we don't now, we can't use this
// request.
if ( otherprincipal & & ! loadingPrincipal ) {
return false ;
}
if ( otherprincipal & & loadingPrincipal ) {
2011-09-28 23:19:26 -07:00
bool equals = false ;
2011-07-14 11:47:34 -07:00
otherprincipal - > Equals ( loadingPrincipal , & equals ) ;
2011-07-17 10:40:24 -07:00
return equals ;
2011-07-14 11:47:34 -07:00
}
}
return true ;
}
2007-03-22 10:30:00 -07:00
static nsresult NewImageChannel ( nsIChannel * * aResult ,
2011-09-20 14:00:42 -07:00
// If aForcePrincipalCheckForCacheEntry is
// true, then we will force a principal check
// even when not using CORS before assuming we
// have a cache hit on a cache entry that we
// create for this channel. This is an out
// param that should be set to true if this
// channel ends up depending on
// aLoadingPrincipal and false otherwise.
bool * aForcePrincipalCheckForCacheEntry ,
2007-03-22 10:30:00 -07:00
nsIURI * aURI ,
nsIURI * aInitialDocumentURI ,
nsIURI * aReferringURI ,
nsILoadGroup * aLoadGroup ,
2009-07-15 00:22:40 -07:00
const nsCString & aAcceptHeader ,
2010-05-20 13:08:02 -07:00
nsLoadFlags aLoadFlags ,
2011-09-20 14:00:42 -07:00
nsIChannelPolicy * aPolicy ,
nsIPrincipal * aLoadingPrincipal )
2007-03-22 10:30:00 -07:00
{
nsresult rv ;
nsCOMPtr < nsIHttpChannel > newHttpChannel ;
2013-03-29 13:14:19 -07:00
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsIInterfaceRequestor > callbacks ;
if ( aLoadGroup ) {
// Get the notification callbacks from the load group for the new channel.
//
// XXX: This is not exactly correct, because the network request could be
// referenced by multiple windows... However, the new channel needs
// something. So, using the 'first' notification callbacks is better
// than nothing...
//
aLoadGroup - > GetNotificationCallbacks ( getter_AddRefs ( callbacks ) ) ;
}
2013-08-23 12:51:00 -07:00
// Pass in a nullptr loadgroup because this is the underlying network
// request. This request may be referenced by several proxy image requests
// (possibly in different documents).
2007-03-22 10:30:00 -07:00
// If all of the proxy requests are canceled then this request should be
// canceled too.
//
2014-06-27 13:57:36 -07:00
aLoadFlags | = nsIChannel : : LOAD_CLASSIFY_URI ;
2007-03-22 10:30:00 -07:00
rv = NS_NewChannel ( aResult ,
2013-03-29 13:14:19 -07:00
aURI , // URI
2012-07-30 07:20:58 -07:00
nullptr , // Cached IOService
nullptr , // LoadGroup
2007-03-22 10:30:00 -07:00
callbacks , // Notification Callbacks
2010-05-20 13:08:02 -07:00
aLoadFlags ,
aPolicy ) ;
2007-03-22 10:30:00 -07:00
if ( NS_FAILED ( rv ) )
return rv ;
2011-09-20 14:00:42 -07:00
* aForcePrincipalCheckForCacheEntry = false ;
2007-03-22 10:30:00 -07:00
// Initialize HTTP-specific attributes
newHttpChannel = do_QueryInterface ( * aResult ) ;
if ( newHttpChannel ) {
newHttpChannel - > SetRequestHeader ( NS_LITERAL_CSTRING ( " Accept " ) ,
2009-07-15 00:22:40 -07:00
aAcceptHeader ,
2011-10-17 07:59:28 -07:00
false ) ;
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsIHttpChannelInternal > httpChannelInternal = do_QueryInterface ( newHttpChannel ) ;
NS_ENSURE_TRUE ( httpChannelInternal , NS_ERROR_UNEXPECTED ) ;
httpChannelInternal - > SetDocumentURI ( aInitialDocumentURI ) ;
newHttpChannel - > SetReferrer ( aReferringURI ) ;
}
// Image channels are loaded by default with reduced priority.
nsCOMPtr < nsISupportsPriority > p = do_QueryInterface ( * aResult ) ;
if ( p ) {
2012-08-22 08:56:38 -07:00
uint32_t priority = nsISupportsPriority : : PRIORITY_LOW ;
2007-03-22 10:30:00 -07:00
if ( aLoadFlags & nsIRequest : : LOAD_BACKGROUND )
+ + priority ; // further reduce priority for background loads
p - > AdjustPriority ( priority ) ;
}
2011-09-28 23:19:26 -07:00
bool setOwner = nsContentUtils : : SetUpChannelOwner ( aLoadingPrincipal ,
2014-07-09 23:56:38 -07:00
* aResult , aURI , false ,
false , false ) ;
2011-09-20 14:00:42 -07:00
* aForcePrincipalCheckForCacheEntry = setOwner ;
2014-01-29 19:35:40 -08:00
// Create a new loadgroup for this new channel, using the old group as
// the parent. The indirection keeps the channel insulated from cancels,
// but does allow a way for this revalidation to be associated with at
// least one base load group for scheduling/caching purposes.
nsCOMPtr < nsILoadGroup > loadGroup = do_CreateInstance ( NS_LOADGROUP_CONTRACTID ) ;
nsCOMPtr < nsILoadGroupChild > childLoadGroup = do_QueryInterface ( loadGroup ) ;
if ( childLoadGroup ) {
childLoadGroup - > SetParentLoadGroup ( aLoadGroup ) ;
}
( * aResult ) - > SetLoadGroup ( loadGroup ) ;
2007-03-22 10:30:00 -07:00
return NS_OK ;
}
2012-08-22 08:56:38 -07:00
static uint32_t SecondsFromPRTime ( PRTime prTime )
2008-09-04 16:00:42 -07:00
{
2012-08-22 08:56:38 -07:00
return uint32_t ( int64_t ( prTime ) / int64_t ( PR_USEC_PER_SEC ) ) ;
2008-09-04 16:00:42 -07:00
}
2012-06-25 21:20:12 -07:00
imgCacheEntry : : imgCacheEntry ( imgLoader * loader , imgRequest * request , bool forcePrincipalCheck )
: mLoader ( loader ) ,
mRequest ( request ) ,
2008-09-04 16:00:42 -07:00
mDataSize ( 0 ) ,
mTouchedTime ( SecondsFromPRTime ( PR_Now ( ) ) ) ,
mExpiryTime ( 0 ) ,
2011-10-17 07:59:28 -07:00
mMustValidate ( false ) ,
2011-07-01 10:03:38 -07:00
// We start off as evicted so we don't try to update the cache. PutIntoCache
// will set this to false.
2011-10-17 07:59:28 -07:00
mEvicted ( true ) ,
mHasNoProxies ( true ) ,
2011-09-20 14:00:42 -07:00
mForcePrincipalCheck ( forcePrincipalCheck )
2008-09-04 16:00:42 -07:00
{ }
2009-01-30 18:17:47 -08:00
imgCacheEntry : : ~ imgCacheEntry ( )
{
2012-10-29 16:32:10 -07:00
LOG_FUNC ( GetImgLog ( ) , " imgCacheEntry::~imgCacheEntry() " ) ;
2009-01-30 18:17:47 -08:00
}
2011-09-28 23:19:26 -07:00
void imgCacheEntry : : Touch ( bool updateTime /* = true */ )
2008-09-04 16:00:42 -07:00
{
2012-10-29 16:32:10 -07:00
LOG_SCOPE ( GetImgLog ( ) , " imgCacheEntry::Touch " ) ;
2008-09-04 16:00:42 -07:00
if ( updateTime )
mTouchedTime = SecondsFromPRTime ( PR_Now ( ) ) ;
2009-09-12 15:44:18 -07:00
UpdateCache ( ) ;
}
2012-08-22 08:56:38 -07:00
void imgCacheEntry : : UpdateCache ( int32_t diff /* = 0 */ )
2009-09-12 15:44:18 -07:00
{
2009-01-30 18:17:47 -08:00
// Don't update the cache if we've been removed from it or it doesn't care
// about our size or usage.
if ( ! Evicted ( ) & & HasNoProxies ( ) ) {
2013-09-28 11:28:42 -07:00
nsRefPtr < ImageURL > uri ;
2011-09-07 16:35:54 -07:00
mRequest - > GetURI ( getter_AddRefs ( uri ) ) ;
2012-06-25 21:20:12 -07:00
mLoader - > CacheEntriesChanged ( uri , diff ) ;
2008-09-04 16:00:42 -07:00
}
}
2011-09-28 23:19:26 -07:00
void imgCacheEntry : : SetHasNoProxies ( bool hasNoProxies )
2009-01-30 18:17:47 -08:00
{
# if defined(PR_LOGGING)
2013-09-28 11:28:42 -07:00
nsRefPtr < ImageURL > uri ;
2011-09-07 16:35:54 -07:00
mRequest - > GetURI ( getter_AddRefs ( uri ) ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2009-01-30 18:17:47 -08:00
if ( uri )
uri - > GetSpec ( spec ) ;
if ( hasNoProxies )
2012-10-29 16:32:10 -07:00
LOG_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgCacheEntry::SetHasNoProxies true " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
else
2012-10-29 16:32:10 -07:00
LOG_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgCacheEntry::SetHasNoProxies false " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
# endif
mHasNoProxies = hasNoProxies ;
}
2008-09-04 16:00:42 -07:00
imgCacheQueue : : imgCacheQueue ( )
2011-10-17 07:59:28 -07:00
: mDirty ( false ) ,
2008-09-04 16:00:42 -07:00
mSize ( 0 )
{ }
2012-08-22 08:56:38 -07:00
void imgCacheQueue : : UpdateSize ( int32_t diff )
2008-09-04 16:00:42 -07:00
{
mSize + = diff ;
}
2012-08-22 08:56:38 -07:00
uint32_t imgCacheQueue : : GetSize ( ) const
2008-09-04 16:00:42 -07:00
{
return mSize ;
}
# include <algorithm>
2008-09-11 04:34:17 -07:00
using namespace std ;
2008-09-04 16:00:42 -07:00
void imgCacheQueue : : Remove ( imgCacheEntry * entry )
{
queueContainer : : iterator it = find ( mQueue . begin ( ) , mQueue . end ( ) , entry ) ;
if ( it ! = mQueue . end ( ) ) {
mSize - = ( * it ) - > GetDataSize ( ) ;
mQueue . erase ( it ) ;
MarkDirty ( ) ;
}
}
void imgCacheQueue : : Push ( imgCacheEntry * entry )
{
mSize + = entry - > GetDataSize ( ) ;
nsRefPtr < imgCacheEntry > refptr ( entry ) ;
mQueue . push_back ( refptr ) ;
MarkDirty ( ) ;
}
already_AddRefed < imgCacheEntry > imgCacheQueue : : Pop ( )
{
if ( mQueue . empty ( ) )
2012-07-30 07:20:58 -07:00
return nullptr ;
2008-09-04 16:00:42 -07:00
if ( IsDirty ( ) )
Refresh ( ) ;
nsRefPtr < imgCacheEntry > entry = mQueue [ 0 ] ;
std : : pop_heap ( mQueue . begin ( ) , mQueue . end ( ) , imgLoader : : CompareCacheEntries ) ;
mQueue . pop_back ( ) ;
mSize - = entry - > GetDataSize ( ) ;
2013-04-22 04:15:59 -07:00
return entry . forget ( ) ;
2008-09-04 16:00:42 -07:00
}
void imgCacheQueue : : Refresh ( )
{
std : : make_heap ( mQueue . begin ( ) , mQueue . end ( ) , imgLoader : : CompareCacheEntries ) ;
2011-10-17 07:59:28 -07:00
mDirty = false ;
2008-09-04 16:00:42 -07:00
}
void imgCacheQueue : : MarkDirty ( )
{
2011-10-17 07:59:28 -07:00
mDirty = true ;
2008-09-04 16:00:42 -07:00
}
2011-09-28 23:19:26 -07:00
bool imgCacheQueue : : IsDirty ( )
2008-09-04 16:00:42 -07:00
{
return mDirty ;
}
2012-08-22 08:56:38 -07:00
uint32_t imgCacheQueue : : GetNumElements ( ) const
2008-09-04 16:00:42 -07:00
{
return mQueue . size ( ) ;
}
imgCacheQueue : : iterator imgCacheQueue : : begin ( )
{
return mQueue . begin ( ) ;
}
imgCacheQueue : : const_iterator imgCacheQueue : : begin ( ) const
{
return mQueue . begin ( ) ;
}
imgCacheQueue : : iterator imgCacheQueue : : end ( )
{
return mQueue . end ( ) ;
}
imgCacheQueue : : const_iterator imgCacheQueue : : end ( ) const
{
return mQueue . end ( ) ;
}
nsresult imgLoader : : CreateNewProxyForRequest ( imgRequest * aRequest , nsILoadGroup * aLoadGroup ,
2012-10-12 09:11:22 -07:00
imgINotificationObserver * aObserver ,
2012-10-12 05:43:01 -07:00
nsLoadFlags aLoadFlags , imgRequestProxy * * _retval )
2008-09-04 16:00:42 -07:00
{
2012-10-29 16:32:10 -07:00
LOG_SCOPE_WITH_PARAM ( GetImgLog ( ) , " imgLoader::CreateNewProxyForRequest " , " imgRequest " , aRequest ) ;
2008-09-04 16:00:42 -07:00
/* XXX If we move decoding onto separate threads, we should save off the
calling thread here and pass it off to | proxyRequest | so that it call
proxy calls to | aObserver | .
*/
2012-11-03 20:04:07 -07:00
imgRequestProxy * proxyRequest = new imgRequestProxy ( ) ;
2008-09-04 16:00:42 -07:00
NS_ADDREF ( proxyRequest ) ;
/* It is important to call |SetLoadFlags()| before calling |Init()| because
| Init ( ) | adds the request to the loadgroup .
*/
proxyRequest - > SetLoadFlags ( aLoadFlags ) ;
2013-09-28 11:28:42 -07:00
nsRefPtr < ImageURL > uri ;
2010-05-10 20:27:41 -07:00
aRequest - > GetURI ( getter_AddRefs ( uri ) ) ;
2008-09-04 16:00:42 -07:00
// init adds itself to imgRequest's list of observers
2012-12-19 13:28:54 -08:00
nsresult rv = proxyRequest - > Init ( aRequest , aLoadGroup , uri , aObserver ) ;
2008-09-04 16:00:42 -07:00
if ( NS_FAILED ( rv ) ) {
NS_RELEASE ( proxyRequest ) ;
return rv ;
}
// transfer reference to caller
2012-10-12 05:43:01 -07:00
* _retval = proxyRequest ;
2008-09-04 16:00:42 -07:00
return NS_OK ;
}
2012-01-02 12:23:41 -08:00
class imgCacheObserver MOZ_FINAL : public nsIObserver
2008-09-04 16:00:42 -07:00
{
2014-06-23 11:49:08 -07:00
~ imgCacheObserver ( ) { }
2008-09-04 16:00:42 -07:00
public :
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
} ;
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( imgCacheObserver , nsIObserver )
2008-09-04 16:00:42 -07:00
NS_IMETHODIMP
2014-01-04 07:02:17 -08:00
imgCacheObserver : : Observe ( nsISupports * aSubject , const char * aTopic , const char16_t * aSomeData )
2008-09-04 16:00:42 -07:00
{
2014-08-28 17:20:27 -07:00
if ( strcmp ( aTopic , " memory-pressure " ) = = 0 | |
strcmp ( aTopic , " app-theme-changed " ) = = 0 ) {
2011-06-30 14:13:56 -07:00
DiscardTracker : : DiscardAll ( ) ;
2008-09-04 16:00:42 -07:00
}
return NS_OK ;
}
2012-01-02 12:23:41 -08:00
class imgCacheExpirationTracker MOZ_FINAL
: public nsExpirationTracker < imgCacheEntry , 3 >
2008-09-04 16:00:42 -07:00
{
enum { TIMEOUT_SECONDS = 10 } ;
public :
imgCacheExpirationTracker ( ) ;
protected :
void NotifyExpired ( imgCacheEntry * entry ) ;
} ;
imgCacheExpirationTracker : : imgCacheExpirationTracker ( )
: nsExpirationTracker < imgCacheEntry , 3 > ( TIMEOUT_SECONDS * 1000 )
{ }
void imgCacheExpirationTracker : : NotifyExpired ( imgCacheEntry * entry )
{
2009-02-25 11:09:44 -08:00
// Hold on to a reference to this entry, because the expiration tracker
// mechanism doesn't.
nsRefPtr < imgCacheEntry > kungFuDeathGrip ( entry ) ;
2009-01-30 18:17:47 -08:00
# if defined(PR_LOGGING)
nsRefPtr < imgRequest > req ( entry - > GetRequest ( ) ) ;
if ( req ) {
2013-09-28 11:28:42 -07:00
nsRefPtr < ImageURL > uri ;
2011-09-07 16:35:54 -07:00
req - > GetURI ( getter_AddRefs ( uri ) ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2009-01-30 18:17:47 -08:00
uri - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
LOG_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgCacheExpirationTracker::NotifyExpired " , " entry " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
}
# endif
2008-09-04 16:00:42 -07:00
// We can be called multiple times on the same entry. Don't do work multiple
// times.
if ( ! entry - > Evicted ( ) )
2012-06-25 21:20:12 -07:00
entry - > Loader ( ) - > RemoveFromCache ( entry ) ;
2008-09-04 16:00:42 -07:00
2012-06-25 21:20:12 -07:00
entry - > Loader ( ) - > VerifyCacheSizes ( ) ;
2008-09-04 16:00:42 -07:00
}
imgCacheObserver * gCacheObserver ;
2012-08-09 00:09:42 -07:00
double imgLoader : : sCacheTimeWeight ;
2012-08-22 08:56:38 -07:00
uint32_t imgLoader : : sCacheMaxSize ;
2012-06-25 21:20:12 -07:00
imgMemoryReporter * imgLoader : : sMemReporter ;
2008-09-04 16:00:42 -07:00
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( imgLoader , imgILoader , nsIContentSniffer , imgICache , nsISupportsWeakReference , nsIObserver )
2008-09-04 16:00:42 -07:00
2014-04-08 15:51:33 -07:00
static imgLoader * gSingleton = nullptr ;
static imgLoader * gPBSingleton = nullptr ;
imgLoader *
imgLoader : : Singleton ( )
{
if ( ! gSingleton )
gSingleton = imgLoader : : Create ( ) ;
return gSingleton ;
}
imgLoader *
imgLoader : : PBSingleton ( )
{
if ( ! gPBSingleton ) {
gPBSingleton = imgLoader : : Create ( ) ;
gPBSingleton - > RespectPrivacyNotifications ( ) ;
}
return gPBSingleton ;
}
2008-09-04 16:00:42 -07:00
imgLoader : : imgLoader ( )
2014-09-05 14:36:11 -07:00
: mUncachedImagesMutex ( " imgLoader::UncachedImages " ) , mRespectPrivacy ( false )
2008-09-04 16:00:42 -07:00
{
2012-06-25 21:20:12 -07:00
sMemReporter - > AddRef ( ) ;
sMemReporter - > RegisterLoader ( this ) ;
2008-09-04 16:00:42 -07:00
}
2012-10-12 05:43:01 -07:00
already_AddRefed < imgLoader >
imgLoader : : GetInstance ( )
{
static StaticRefPtr < imgLoader > singleton ;
if ( ! singleton ) {
singleton = imgLoader : : Create ( ) ;
if ( ! singleton )
return nullptr ;
ClearOnShutdown ( & singleton ) ;
}
nsRefPtr < imgLoader > loader = singleton . get ( ) ;
return loader . forget ( ) ;
}
2014-09-05 14:36:11 -07:00
static PLDHashOperator ClearLoaderPointer ( nsPtrHashKey < imgRequest > * aEntry ,
void * aUserArg )
{
nsRefPtr < imgRequest > req = aEntry - > GetKey ( ) ;
req - > ClearLoader ( ) ;
return PL_DHASH_NEXT ;
}
2008-09-04 16:00:42 -07:00
imgLoader : : ~ imgLoader ( )
{
2012-06-25 21:20:12 -07:00
ClearChromeImageCache ( ) ;
ClearImageCache ( ) ;
2014-09-05 14:36:11 -07:00
{
// If there are any of our imgRequest's left they are in the uncached
// images set, so clear their pointer to us.
MutexAutoLock lock ( mUncachedImagesMutex ) ;
mUncachedImages . EnumerateEntries ( ClearLoaderPointer , nullptr ) ;
}
2012-06-25 21:20:12 -07:00
sMemReporter - > UnregisterLoader ( this ) ;
sMemReporter - > Release ( ) ;
2008-09-04 16:00:42 -07:00
}
void imgLoader : : VerifyCacheSizes ( )
{
2010-04-28 23:27:00 -07:00
# ifdef DEBUG
2012-06-25 21:20:12 -07:00
if ( ! mCacheTracker )
2008-09-04 16:00:42 -07:00
return ;
2012-06-25 21:20:12 -07:00
uint32_t cachesize = mCache . Count ( ) + mChromeCache . Count ( ) ;
uint32_t queuesize = mCacheQueue . GetNumElements ( ) + mChromeCacheQueue . GetNumElements ( ) ;
2012-08-22 08:56:38 -07:00
uint32_t trackersize = 0 ;
2012-06-25 21:20:12 -07:00
for ( nsExpirationTracker < imgCacheEntry , 3 > : : Iterator it ( mCacheTracker ) ; it . Next ( ) ; )
2008-09-04 16:00:42 -07:00
trackersize + + ;
2009-01-30 18:17:47 -08:00
NS_ABORT_IF_FALSE ( queuesize = = trackersize , " Queue and tracker sizes out of sync! " ) ;
NS_ABORT_IF_FALSE ( queuesize < = cachesize , " Queue has more elements than cache! " ) ;
2010-04-28 23:27:00 -07:00
# endif
2008-09-04 16:00:42 -07:00
}
imgLoader : : imgCacheTable & imgLoader : : GetCache ( nsIURI * aURI )
{
2013-09-28 11:28:42 -07:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Cannot use nsIURI off main thread! " ) ;
2011-09-28 23:19:26 -07:00
bool chrome = false ;
2008-09-04 16:00:42 -07:00
aURI - > SchemeIs ( " chrome " , & chrome ) ;
2013-09-28 11:28:42 -07:00
return chrome ? mChromeCache : mCache ;
2008-09-04 16:00:42 -07:00
}
imgCacheQueue & imgLoader : : GetCacheQueue ( nsIURI * aURI )
{
2013-09-28 11:28:42 -07:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Cannot use nsIURI off main thread! " ) ;
2011-09-28 23:19:26 -07:00
bool chrome = false ;
2008-09-04 16:00:42 -07:00
aURI - > SchemeIs ( " chrome " , & chrome ) ;
2013-09-28 11:28:42 -07:00
return chrome ? mChromeCacheQueue : mCacheQueue ;
}
imgLoader : : imgCacheTable & imgLoader : : GetCache ( ImageURL * aURI )
{
bool chrome = false ;
aURI - > SchemeIs ( " chrome " , & chrome ) ;
return chrome ? mChromeCache : mCache ;
}
imgCacheQueue & imgLoader : : GetCacheQueue ( ImageURL * aURI )
{
bool chrome = false ;
aURI - > SchemeIs ( " chrome " , & chrome ) ;
return chrome ? mChromeCacheQueue : mCacheQueue ;
2008-09-04 16:00:42 -07:00
}
2012-06-25 21:20:12 -07:00
void imgLoader : : GlobalInit ( )
2008-09-04 16:00:42 -07:00
{
gCacheObserver = new imgCacheObserver ( ) ;
NS_ADDREF ( gCacheObserver ) ;
2012-06-25 21:20:12 -07:00
nsCOMPtr < nsIObserverService > os = mozilla : : services : : GetObserverService ( ) ;
2014-08-28 17:20:27 -07:00
if ( os ) {
2012-06-25 21:20:12 -07:00
os - > AddObserver ( gCacheObserver , " memory-pressure " , false ) ;
2014-08-28 17:20:27 -07:00
os - > AddObserver ( gCacheObserver , " app-theme-changed " , false ) ;
}
2008-09-04 16:00:42 -07:00
2012-08-22 08:56:38 -07:00
int32_t timeweight ;
2012-06-25 21:20:12 -07:00
nsresult rv = Preferences : : GetInt ( " image.cache.timeweight " , & timeweight ) ;
2008-09-04 16:00:42 -07:00
if ( NS_SUCCEEDED ( rv ) )
sCacheTimeWeight = timeweight / 1000.0 ;
else
sCacheTimeWeight = 0.5 ;
2012-08-22 08:56:38 -07:00
int32_t cachesize ;
2011-06-11 19:30:15 -07:00
rv = Preferences : : GetInt ( " image.cache.size " , & cachesize ) ;
2008-09-04 16:00:42 -07:00
if ( NS_SUCCEEDED ( rv ) )
2014-09-18 13:15:52 -07:00
sCacheMaxSize = cachesize > 0 ? cachesize : 0 ;
2008-09-04 16:00:42 -07:00
else
sCacheMaxSize = 5 * 1024 * 1024 ;
2009-07-15 00:22:40 -07:00
2012-06-25 21:20:12 -07:00
sMemReporter = new imgMemoryReporter ( ) ;
2013-11-06 21:35:30 -08:00
RegisterStrongMemoryReporter ( sMemReporter ) ;
2013-09-19 15:52:30 -07:00
RegisterImagesContentUsedUncompressedDistinguishedAmount ( imgMemoryReporter : : ImagesContentUsedUncompressedDistinguishedAmount ) ;
2012-06-25 21:20:12 -07:00
}
nsresult imgLoader : : InitCache ( )
{
nsCOMPtr < nsIObserverService > os = mozilla : : services : : GetObserverService ( ) ;
if ( ! os )
return NS_ERROR_FAILURE ;
os - > AddObserver ( this , " memory-pressure " , false ) ;
2014-08-28 17:20:27 -07:00
os - > AddObserver ( this , " app-theme-changed " , false ) ;
2012-06-25 21:20:12 -07:00
os - > AddObserver ( this , " chrome-flush-skin-caches " , false ) ;
os - > AddObserver ( this , " chrome-flush-caches " , false ) ;
os - > AddObserver ( this , " last-pb-context-exited " , false ) ;
os - > AddObserver ( this , " profile-before-change " , false ) ;
os - > AddObserver ( this , " xpcom-shutdown " , false ) ;
mCacheTracker = new imgCacheExpirationTracker ( ) ;
2013-09-02 01:41:57 -07:00
return NS_OK ;
2008-09-04 16:00:42 -07:00
}
2009-07-15 00:22:40 -07:00
nsresult imgLoader : : Init ( )
{
2012-06-25 21:20:12 -07:00
InitCache ( ) ;
2011-06-11 19:30:15 -07:00
ReadAcceptHeaderPref ( ) ;
2009-07-15 00:22:40 -07:00
2011-06-11 19:30:15 -07:00
Preferences : : AddWeakObserver ( this , " image.http.accept " ) ;
2009-07-15 00:22:40 -07:00
2012-06-25 21:20:12 -07:00
return NS_OK ;
}
2010-07-11 18:01:53 -07:00
2012-06-25 21:20:12 -07:00
NS_IMETHODIMP
imgLoader : : RespectPrivacyNotifications ( )
{
mRespectPrivacy = true ;
2009-07-15 00:22:40 -07:00
return NS_OK ;
}
NS_IMETHODIMP
2014-01-04 07:02:17 -08:00
imgLoader : : Observe ( nsISupports * aSubject , const char * aTopic , const char16_t * aData )
2009-07-15 00:22:40 -07:00
{
2010-07-11 18:01:53 -07:00
// We listen for pref change notifications...
if ( ! strcmp ( aTopic , NS_PREFBRANCH_PREFCHANGE_TOPIC_ID ) ) {
2014-06-27 01:08:13 -07:00
if ( ! NS_strcmp ( aData , MOZ_UTF16 ( " image.http.accept " ) ) ) {
2011-06-11 19:30:15 -07:00
ReadAcceptHeaderPref ( ) ;
2010-07-11 18:01:53 -07:00
}
2009-07-15 00:22:40 -07:00
2012-06-25 21:20:12 -07:00
} else if ( strcmp ( aTopic , " memory-pressure " ) = = 0 ) {
MinimizeCaches ( ) ;
2014-08-28 17:20:27 -07:00
} else if ( strcmp ( aTopic , " app-theme-changed " ) = = 0 ) {
ClearImageCache ( ) ;
MinimizeCaches ( ) ;
2012-06-25 21:20:12 -07:00
} else if ( strcmp ( aTopic , " chrome-flush-skin-caches " ) = = 0 | |
strcmp ( aTopic , " chrome-flush-caches " ) = = 0 ) {
MinimizeCaches ( ) ;
ClearChromeImageCache ( ) ;
} else if ( strcmp ( aTopic , " last-pb-context-exited " ) = = 0 ) {
if ( mRespectPrivacy ) {
2010-07-11 18:01:53 -07:00
ClearImageCache ( ) ;
2012-06-25 21:20:12 -07:00
ClearChromeImageCache ( ) ;
}
} else if ( strcmp ( aTopic , " profile-before-change " ) = = 0 | |
strcmp ( aTopic , " xpcom-shutdown " ) = = 0 ) {
mCacheTracker = nullptr ;
2009-07-15 00:22:40 -07:00
}
2010-07-11 18:01:53 -07:00
// (Nothing else should bring us here)
else {
NS_ABORT_IF_FALSE ( 0 , " Invalid topic received " ) ;
}
2009-07-15 00:22:40 -07:00
return NS_OK ;
}
2011-06-11 19:30:15 -07:00
void imgLoader : : ReadAcceptHeaderPref ( )
2009-07-15 00:22:40 -07:00
{
2011-06-11 19:30:15 -07:00
nsAdoptingCString accept = Preferences : : GetCString ( " image.http.accept " ) ;
if ( accept )
2009-07-15 00:22:40 -07:00
mAcceptHeader = accept ;
else
2013-01-08 13:40:47 -08:00
mAcceptHeader = IMAGE_PNG " , " IMAGE_WILDCARD " ;q=0.8, " ANY_WILDCARD " ;q=0.5 " ;
2009-07-15 00:22:40 -07:00
}
2008-09-04 16:00:42 -07:00
/* void clearCache (in boolean chrome); */
2011-09-28 23:19:26 -07:00
NS_IMETHODIMP imgLoader : : ClearCache ( bool chrome )
2008-09-04 16:00:42 -07:00
{
if ( chrome )
return ClearChromeImageCache ( ) ;
else
return ClearImageCache ( ) ;
}
/* void removeEntry(in nsIURI uri); */
NS_IMETHODIMP imgLoader : : RemoveEntry ( nsIURI * uri )
{
if ( RemoveFromCache ( uri ) )
return NS_OK ;
return NS_ERROR_NOT_AVAILABLE ;
}
/* imgIRequest findEntry(in nsIURI uri); */
NS_IMETHODIMP imgLoader : : FindEntryProperties ( nsIURI * uri , nsIProperties * * _retval )
{
nsRefPtr < imgCacheEntry > entry ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2008-09-04 16:00:42 -07:00
imgCacheTable & cache = GetCache ( uri ) ;
uri - > GetSpec ( spec ) ;
2012-07-30 07:20:58 -07:00
* _retval = nullptr ;
2008-09-04 16:00:42 -07:00
if ( cache . Get ( spec , getter_AddRefs ( entry ) ) & & entry ) {
2012-06-25 21:20:12 -07:00
if ( mCacheTracker & & entry - > HasNoProxies ( ) )
mCacheTracker - > MarkUsed ( entry ) ;
2009-01-30 18:17:47 -08:00
2013-07-10 02:56:21 -07:00
nsRefPtr < imgRequest > request = entry - > GetRequest ( ) ;
2008-09-04 16:00:42 -07:00
if ( request ) {
* _retval = request - > Properties ( ) ;
NS_ADDREF ( * _retval ) ;
}
}
return NS_OK ;
}
void imgLoader : : Shutdown ( )
{
2014-04-08 15:51:33 -07:00
NS_IF_RELEASE ( gSingleton ) ;
NS_IF_RELEASE ( gPBSingleton ) ;
2012-06-25 21:20:12 -07:00
NS_RELEASE ( gCacheObserver ) ;
2008-09-04 16:00:42 -07:00
}
nsresult imgLoader : : ClearChromeImageCache ( )
{
2012-06-25 21:20:12 -07:00
return EvictEntries ( mChromeCache ) ;
2008-09-04 16:00:42 -07:00
}
nsresult imgLoader : : ClearImageCache ( )
{
2012-06-25 21:20:12 -07:00
return EvictEntries ( mCache ) ;
2009-05-07 13:55:06 -07:00
}
void imgLoader : : MinimizeCaches ( )
{
2012-06-25 21:20:12 -07:00
EvictEntries ( mCacheQueue ) ;
EvictEntries ( mChromeCacheQueue ) ;
2008-09-04 16:00:42 -07:00
}
2011-09-28 23:19:26 -07:00
bool imgLoader : : PutIntoCache ( nsIURI * key , imgCacheEntry * entry )
2008-09-04 16:00:42 -07:00
{
imgCacheTable & cache = GetCache ( key ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2008-09-04 16:00:42 -07:00
key - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::PutIntoCache " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
2008-09-04 16:00:42 -07:00
// Check to see if this request already exists in the cache and is being
// loaded on a different thread. If so, don't allow this entry to be added to
// the cache.
nsRefPtr < imgCacheEntry > tmpCacheEntry ;
if ( cache . Get ( spec , getter_AddRefs ( tmpCacheEntry ) ) & & tmpCacheEntry ) {
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2012-07-30 07:20:58 -07:00
( " [this=%p] imgLoader::PutIntoCache -- Element already in the cache " , nullptr ) ) ;
2013-07-10 02:56:21 -07:00
nsRefPtr < imgRequest > tmpRequest = tmpCacheEntry - > GetRequest ( ) ;
2008-09-04 16:00:42 -07:00
2008-09-30 14:47:47 -07:00
// If it already exists, and we're putting the same key into the cache, we
// should remove the old version.
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2012-07-30 07:20:58 -07:00
( " [this=%p] imgLoader::PutIntoCache -- Replacing cached element " , nullptr ) ) ;
2008-09-04 16:00:42 -07:00
2008-09-30 14:47:47 -07:00
RemoveFromCache ( key ) ;
} else {
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2012-07-30 07:20:58 -07:00
( " [this=%p] imgLoader::PutIntoCache -- Element NOT already in the cache " , nullptr ) ) ;
2008-09-04 16:00:42 -07:00
}
2012-05-18 10:30:49 -07:00
cache . Put ( spec , entry ) ;
2008-09-04 16:00:42 -07:00
2009-03-17 14:07:16 -07:00
// We can be called to resurrect an evicted entry.
if ( entry - > Evicted ( ) )
2011-10-17 07:59:28 -07:00
entry - > SetEvicted ( false ) ;
2009-03-17 14:07:16 -07:00
// If we're resurrecting an entry with no proxies, put it back in the
// tracker and queue.
if ( entry - > HasNoProxies ( ) ) {
nsresult addrv = NS_OK ;
2012-06-25 21:20:12 -07:00
if ( mCacheTracker )
addrv = mCacheTracker - > AddObject ( entry ) ;
2009-03-17 14:07:16 -07:00
if ( NS_SUCCEEDED ( addrv ) ) {
imgCacheQueue & queue = GetCacheQueue ( key ) ;
queue . Push ( entry ) ;
}
}
2013-07-10 02:56:21 -07:00
nsRefPtr < imgRequest > request = entry - > GetRequest ( ) ;
2011-10-17 07:59:28 -07:00
request - > SetIsInCache ( true ) ;
2014-09-05 14:36:11 -07:00
RemoveFromUncachedImages ( request ) ;
2009-03-17 14:07:16 -07:00
2011-10-17 07:59:28 -07:00
return true ;
2009-01-30 18:17:47 -08:00
}
2014-09-10 19:47:00 -07:00
bool imgLoader : : SetHasNoProxies ( imgRequest * aRequest , imgCacheEntry * aEntry )
2009-01-30 18:17:47 -08:00
{
2014-09-10 19:47:00 -07:00
nsRefPtr < ImageURL > uri ;
aRequest - > GetURI ( getter_AddRefs ( uri ) ) ;
2009-01-30 18:17:47 -08:00
# if defined(PR_LOGGING)
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2014-09-10 19:47:00 -07:00
uri - > GetSpec ( spec ) ;
2009-01-30 18:17:47 -08:00
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::SetHasNoProxies " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
# endif
2014-09-10 19:47:00 -07:00
aEntry - > SetHasNoProxies ( true ) ;
if ( aEntry - > Evicted ( ) )
2011-10-17 07:59:28 -07:00
return false ;
2009-01-30 18:17:47 -08:00
2014-09-10 19:47:00 -07:00
imgCacheQueue & queue = GetCacheQueue ( uri ) ;
2009-01-30 18:17:47 -08:00
nsresult addrv = NS_OK ;
2008-09-04 16:00:42 -07:00
2012-06-25 21:20:12 -07:00
if ( mCacheTracker )
2014-09-10 19:47:00 -07:00
addrv = mCacheTracker - > AddObject ( aEntry ) ;
2009-01-30 18:17:47 -08:00
if ( NS_SUCCEEDED ( addrv ) ) {
2014-09-10 19:47:00 -07:00
queue . Push ( aEntry ) ;
2009-01-30 18:17:47 -08:00
}
2008-09-04 16:00:42 -07:00
2014-09-10 19:47:00 -07:00
imgCacheTable & cache = GetCache ( uri ) ;
2008-09-04 16:00:42 -07:00
CheckCacheLimits ( cache , queue ) ;
2011-10-17 07:59:28 -07:00
return true ;
2008-09-04 16:00:42 -07:00
}
2014-09-10 19:47:00 -07:00
bool imgLoader : : SetHasProxies ( imgRequest * aRequest )
2009-01-30 18:17:47 -08:00
{
VerifyCacheSizes ( ) ;
2014-09-10 19:47:00 -07:00
nsRefPtr < ImageURL > uri ;
aRequest - > GetURI ( getter_AddRefs ( uri ) ) ;
imgCacheTable & cache = GetCache ( uri ) ;
2009-01-30 18:17:47 -08:00
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2014-09-10 19:47:00 -07:00
uri - > GetSpec ( spec ) ;
2009-01-30 18:17:47 -08:00
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::SetHasProxies " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
nsRefPtr < imgCacheEntry > entry ;
2014-09-10 19:47:00 -07:00
if ( cache . Get ( spec , getter_AddRefs ( entry ) ) & & entry ) {
// Make sure the cache entry is for the right request
nsRefPtr < imgRequest > entryRequest = entry - > GetRequest ( ) ;
if ( entryRequest = = aRequest & & entry - > HasNoProxies ( ) ) {
imgCacheQueue & queue = GetCacheQueue ( uri ) ;
queue . Remove ( entry ) ;
2009-01-30 18:17:47 -08:00
2014-09-10 19:47:00 -07:00
if ( mCacheTracker )
mCacheTracker - > RemoveObject ( entry ) ;
2009-01-30 18:17:47 -08:00
2014-09-10 19:47:00 -07:00
entry - > SetHasNoProxies ( false ) ;
2009-01-30 18:17:47 -08:00
2014-09-10 19:47:00 -07:00
return true ;
}
2009-01-30 18:17:47 -08:00
}
2011-10-17 07:59:28 -07:00
return false ;
2009-01-30 18:17:47 -08:00
}
2013-09-28 11:28:42 -07:00
void imgLoader : : CacheEntriesChanged ( ImageURL * uri , int32_t sizediff /* = 0 */ )
2008-09-04 16:00:42 -07:00
{
imgCacheQueue & queue = GetCacheQueue ( uri ) ;
queue . MarkDirty ( ) ;
queue . UpdateSize ( sizediff ) ;
}
void imgLoader : : CheckCacheLimits ( imgCacheTable & cache , imgCacheQueue & queue )
{
if ( queue . GetNumElements ( ) = = 0 )
2013-03-29 13:14:19 -07:00
NS_ASSERTION ( queue . GetSize ( ) = = 0 ,
2008-09-04 16:00:42 -07:00
" imgLoader::CheckCacheLimits -- incorrect cache size " ) ;
2014-07-18 18:47:39 -07:00
// Remove entries from the cache until we're back at our desired max size.
while ( queue . GetSize ( ) > sCacheMaxSize ) {
2008-09-04 16:00:42 -07:00
// Remove the first entry in the queue.
nsRefPtr < imgCacheEntry > entry ( queue . Pop ( ) ) ;
NS_ASSERTION ( entry , " imgLoader::CheckCacheLimits -- NULL entry pointer " ) ;
2009-01-30 18:17:47 -08:00
# if defined(PR_LOGGING)
nsRefPtr < imgRequest > req ( entry - > GetRequest ( ) ) ;
if ( req ) {
2013-09-28 11:28:42 -07:00
nsRefPtr < ImageURL > uri ;
2011-09-07 16:35:54 -07:00
req - > GetURI ( getter_AddRefs ( uri ) ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2009-01-30 18:17:47 -08:00
uri - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::CheckCacheLimits " , " entry " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
}
# endif
2008-09-04 16:00:42 -07:00
if ( entry )
RemoveFromCache ( entry ) ;
}
}
2011-09-28 23:19:26 -07:00
bool imgLoader : : ValidateRequestWithNewChannel ( imgRequest * request ,
2008-09-04 16:00:42 -07:00
nsIURI * aURI ,
nsIURI * aInitialDocumentURI ,
nsIURI * aReferrerURI ,
nsILoadGroup * aLoadGroup ,
2012-10-12 09:11:22 -07:00
imgINotificationObserver * aObserver ,
2008-09-04 16:00:42 -07:00
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
2012-10-12 05:43:01 -07:00
imgRequestProxy * * aProxyRequest ,
2011-07-14 11:47:32 -07:00
nsIChannelPolicy * aPolicy ,
2011-07-14 11:47:34 -07:00
nsIPrincipal * aLoadingPrincipal ,
2012-08-22 08:56:38 -07:00
int32_t aCORSMode )
2008-09-04 16:00:42 -07:00
{
// now we need to insert a new channel request object inbetween the real
// request and the proxy that basically delays loading the image until it
// gets a 304 or figures out that this needs to be a new request
nsresult rv ;
2009-01-30 18:17:47 -08:00
// If we're currently in the middle of validating this request, just hand
// back a proxy to it; the required work will be done for us.
2008-09-04 16:00:42 -07:00
if ( request - > mValidator ) {
2012-10-12 05:43:01 -07:00
rv = CreateNewProxyForRequest ( request , aLoadGroup , aObserver ,
aLoadFlags , aProxyRequest ) ;
2010-05-25 07:34:04 -07:00
if ( NS_FAILED ( rv ) ) {
2011-10-17 07:59:28 -07:00
return false ;
2010-05-25 07:34:04 -07:00
}
2008-09-04 16:00:42 -07:00
2010-08-02 12:44:49 -07:00
if ( * aProxyRequest ) {
imgRequestProxy * proxy = static_cast < imgRequestProxy * > ( * aProxyRequest ) ;
// We will send notifications from imgCacheValidator::OnStartRequest().
// In the mean time, we must defer notifications because we are added to
// the imgRequest's proxy list, and we can get extra notifications
// resulting from methods such as RequestDecode(). See bug 579122.
2011-10-17 07:59:28 -07:00
proxy - > SetNotificationsDeferred ( true ) ;
2010-08-02 12:44:49 -07:00
// Attach the proxy without notifying
request - > mValidator - > AddProxy ( proxy ) ;
}
2008-09-04 16:00:42 -07:00
return NS_SUCCEEDED ( rv ) ;
} else {
2011-07-01 10:03:42 -07:00
// We will rely on Necko to cache this request when it's possible, and to
// tell imgCacheValidator::OnStartRequest whether the request came from its
// cache.
2008-09-04 16:00:42 -07:00
nsCOMPtr < nsIChannel > newChannel ;
2011-09-20 14:00:42 -07:00
bool forcePrincipalCheck ;
2008-09-04 16:00:42 -07:00
rv = NewImageChannel ( getter_AddRefs ( newChannel ) ,
2011-09-20 14:00:42 -07:00
& forcePrincipalCheck ,
2008-09-04 16:00:42 -07:00
aURI ,
aInitialDocumentURI ,
aReferrerURI ,
aLoadGroup ,
2009-07-15 00:22:40 -07:00
mAcceptHeader ,
2010-05-20 13:08:02 -07:00
aLoadFlags ,
2011-09-20 14:00:42 -07:00
aPolicy ,
aLoadingPrincipal ) ;
2008-09-04 16:00:42 -07:00
if ( NS_FAILED ( rv ) ) {
2011-10-17 07:59:28 -07:00
return false ;
2008-09-04 16:00:42 -07:00
}
2012-10-12 05:43:01 -07:00
nsRefPtr < imgRequestProxy > req ;
2008-09-04 16:00:42 -07:00
rv = CreateNewProxyForRequest ( request , aLoadGroup , aObserver ,
2012-11-03 20:04:07 -07:00
aLoadFlags , getter_AddRefs ( req ) ) ;
2008-09-04 16:00:42 -07:00
if ( NS_FAILED ( rv ) ) {
2011-10-17 07:59:28 -07:00
return false ;
2008-09-04 16:00:42 -07:00
}
2009-07-28 09:13:48 -07:00
// Make sure that OnStatus/OnProgress calls have the right request set...
2011-07-01 10:03:38 -07:00
nsRefPtr < nsProgressNotificationProxy > progressproxy =
new nsProgressNotificationProxy ( newChannel , req ) ;
if ( ! progressproxy )
2011-10-17 07:59:28 -07:00
return false ;
2009-07-28 09:13:48 -07:00
2011-09-20 14:00:42 -07:00
nsRefPtr < imgCacheValidator > hvc =
2012-06-25 21:20:12 -07:00
new imgCacheValidator ( progressproxy , this , request , aCX , forcePrincipalCheck ) ;
2011-07-14 11:47:34 -07:00
2013-09-28 11:28:42 -07:00
// Casting needed here to get past multiple inheritance.
nsCOMPtr < nsIStreamListener > listener =
do_QueryInterface ( static_cast < nsIThreadRetargetableStreamListener * > ( hvc ) ) ;
NS_ENSURE_TRUE ( listener , false ) ;
2011-07-14 11:47:34 -07:00
2012-03-01 21:13:54 -08:00
// We must set the notification callbacks before setting up the
// CORS listener, because that's also interested inthe
// notification callbacks.
newChannel - > SetNotificationCallbacks ( hvc ) ;
2011-07-14 11:47:34 -07:00
if ( aCORSMode ! = imgIRequest : : CORS_NONE ) {
2011-09-28 23:19:26 -07:00
bool withCredentials = aCORSMode = = imgIRequest : : CORS_USE_CREDENTIALS ;
2012-09-18 19:16:23 -07:00
nsRefPtr < nsCORSListenerProxy > corsproxy =
2013-09-28 11:28:42 -07:00
new nsCORSListenerProxy ( listener , aLoadingPrincipal , withCredentials ) ;
2012-09-18 19:16:23 -07:00
rv = corsproxy - > Init ( newChannel ) ;
2011-07-14 11:47:34 -07:00
if ( NS_FAILED ( rv ) ) {
2011-10-17 07:59:28 -07:00
return false ;
2011-07-14 11:47:34 -07:00
}
listener = corsproxy ;
2008-09-04 16:00:42 -07:00
}
request - > mValidator = hvc ;
2010-08-02 12:44:49 -07:00
imgRequestProxy * proxy = static_cast < imgRequestProxy * >
( static_cast < imgIRequest * > ( req . get ( ) ) ) ;
// We will send notifications from imgCacheValidator::OnStartRequest().
// In the mean time, we must defer notifications because we are added to
// the imgRequest's proxy list, and we can get extra notifications
// resulting from methods such as RequestDecode(). See bug 579122.
2011-10-17 07:59:28 -07:00
proxy - > SetNotificationsDeferred ( true ) ;
2010-08-02 12:44:49 -07:00
// Add the proxy without notifying
hvc - > AddProxy ( proxy ) ;
2008-09-04 16:00:42 -07:00
2014-06-03 13:37:46 -07:00
mozilla : : net : : PredictorLearn ( aURI , aInitialDocumentURI ,
nsINetworkPredictor : : LEARN_LOAD_SUBRESOURCE , aLoadGroup ) ;
2013-10-25 14:56:58 -07:00
2012-07-30 07:20:58 -07:00
rv = newChannel - > AsyncOpen ( listener , nullptr ) ;
2008-09-04 16:00:42 -07:00
if ( NS_SUCCEEDED ( rv ) )
NS_ADDREF ( * aProxyRequest = req . get ( ) ) ;
return NS_SUCCEEDED ( rv ) ;
}
}
2011-09-28 23:19:26 -07:00
bool imgLoader : : ValidateEntry ( imgCacheEntry * aEntry ,
2008-09-04 16:00:42 -07:00
nsIURI * aURI ,
nsIURI * aInitialDocumentURI ,
nsIURI * aReferrerURI ,
nsILoadGroup * aLoadGroup ,
2012-10-12 09:11:22 -07:00
imgINotificationObserver * aObserver ,
2008-09-04 16:00:42 -07:00
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
2011-09-28 23:19:26 -07:00
bool aCanMakeNewChannel ,
2012-10-12 05:43:01 -07:00
imgRequestProxy * * aProxyRequest ,
2011-07-14 11:47:32 -07:00
nsIChannelPolicy * aPolicy ,
2011-07-14 11:47:34 -07:00
nsIPrincipal * aLoadingPrincipal ,
2012-08-22 08:56:38 -07:00
int32_t aCORSMode )
2008-09-04 16:00:42 -07:00
{
2012-10-29 16:32:10 -07:00
LOG_SCOPE ( GetImgLog ( ) , " imgLoader::ValidateEntry " ) ;
2008-09-04 16:00:42 -07:00
2011-09-28 23:19:26 -07:00
bool hasExpired ;
2012-08-22 08:56:38 -07:00
uint32_t expirationTime = aEntry - > GetExpiryTime ( ) ;
2008-09-04 16:00:42 -07:00
if ( expirationTime < = SecondsFromPRTime ( PR_Now ( ) ) ) {
2011-10-17 07:59:28 -07:00
hasExpired = true ;
2008-09-04 16:00:42 -07:00
} else {
2011-10-17 07:59:28 -07:00
hasExpired = false ;
2008-09-04 16:00:42 -07:00
}
nsresult rv ;
// Special treatment for file URLs - aEntry has expired if file has changed
nsCOMPtr < nsIFileURL > fileUrl ( do_QueryInterface ( aURI ) ) ;
if ( fileUrl ) {
2012-08-22 08:56:38 -07:00
uint32_t lastModTime = aEntry - > GetTouchedTime ( ) ;
2008-09-04 16:00:42 -07:00
nsCOMPtr < nsIFile > theFile ;
rv = fileUrl - > GetFile ( getter_AddRefs ( theFile ) ) ;
if ( NS_SUCCEEDED ( rv ) ) {
2012-08-30 00:10:35 -07:00
PRTime fileLastMod ;
2008-09-04 16:00:42 -07:00
rv = theFile - > GetLastModifiedTime ( & fileLastMod ) ;
if ( NS_SUCCEEDED ( rv ) ) {
// nsIFile uses millisec, NSPR usec
fileLastMod * = 1000 ;
hasExpired = SecondsFromPRTime ( ( PRTime ) fileLastMod ) > lastModTime ;
}
}
}
nsRefPtr < imgRequest > request ( aEntry - > GetRequest ( ) ) ;
if ( ! request )
2011-10-17 07:59:28 -07:00
return false ;
2008-09-04 16:00:42 -07:00
2011-09-20 14:00:42 -07:00
if ( ! ValidateCORSAndPrincipal ( request , aEntry - > ForcePrincipalCheck ( ) ,
aCORSMode , aLoadingPrincipal ) )
2011-10-17 07:59:28 -07:00
return false ;
2011-07-14 11:47:34 -07:00
2012-11-20 16:58:32 -08:00
// Never validate data URIs.
nsAutoCString scheme ;
aURI - > GetScheme ( scheme ) ;
if ( scheme . EqualsLiteral ( " data " ) )
return true ;
2011-09-28 23:19:26 -07:00
bool validateRequest = false ;
2008-09-04 16:00:42 -07:00
// If the request's loadId is the same as the aCX, then it is ok to use
// this one because it has already been validated for this context.
//
2012-07-30 07:20:58 -07:00
// XXX: nullptr seems to be a 'special' key value that indicates that NO
2008-09-04 16:00:42 -07:00
// validation is required.
//
void * key = ( void * ) aCX ;
if ( request - > mLoadId ! = key ) {
2009-11-12 15:00:30 -08:00
// If we would need to revalidate this entry, but we're being told to
// bypass the cache, we don't allow this entry to be used.
if ( aLoadFlags & nsIRequest : : LOAD_BYPASS_CACHE )
2011-10-17 07:59:28 -07:00
return false ;
2009-11-12 15:00:30 -08:00
2008-09-04 16:00:42 -07:00
// Determine whether the cache aEntry must be revalidated...
validateRequest = ShouldRevalidateEntry ( aEntry , aLoadFlags , hasExpired ) ;
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2013-03-29 13:14:19 -07:00
( " imgLoader::ValidateEntry validating cache entry. "
2008-09-04 16:00:42 -07:00
" validateRequest = %d " , validateRequest ) ) ;
}
# if defined(PR_LOGGING)
else if ( ! key ) {
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2008-09-04 16:00:42 -07:00
aURI - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2013-03-29 13:14:19 -07:00
( " imgLoader::ValidateEntry BYPASSING cache validation for %s "
2008-09-04 16:00:42 -07:00
" because of NULL LoadID " , spec . get ( ) ) ) ;
}
# endif
2009-01-04 21:52:22 -08:00
// We can't use a cached request if it comes from a different
// application cache than this load is expecting.
nsCOMPtr < nsIApplicationCacheContainer > appCacheContainer ;
nsCOMPtr < nsIApplicationCache > requestAppCache ;
nsCOMPtr < nsIApplicationCache > groupAppCache ;
if ( ( appCacheContainer = do_GetInterface ( request - > mRequest ) ) )
appCacheContainer - > GetApplicationCache ( getter_AddRefs ( requestAppCache ) ) ;
if ( ( appCacheContainer = do_QueryInterface ( aLoadGroup ) ) )
appCacheContainer - > GetApplicationCache ( getter_AddRefs ( groupAppCache ) ) ;
if ( requestAppCache ! = groupAppCache ) {
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2009-01-04 21:52:22 -08:00
( " imgLoader::ValidateEntry - Unable to use cached imgRequest "
" [request=%p] because of mismatched application caches \n " ,
address_of ( request ) ) ) ;
2011-10-17 07:59:28 -07:00
return false ;
2009-01-04 21:52:22 -08:00
}
2008-09-04 16:00:42 -07:00
if ( validateRequest & & aCanMakeNewChannel ) {
2012-10-29 16:32:10 -07:00
LOG_SCOPE ( GetImgLog ( ) , " imgLoader::ValidateRequest |cache hit| must validate " ) ;
2008-09-04 16:00:42 -07:00
return ValidateRequestWithNewChannel ( request , aURI , aInitialDocumentURI ,
aReferrerURI , aLoadGroup , aObserver ,
2012-11-03 20:04:07 -07:00
aCX , aLoadFlags , aProxyRequest , aPolicy ,
2011-07-14 11:47:34 -07:00
aLoadingPrincipal , aCORSMode ) ;
}
2008-09-04 16:00:42 -07:00
return ! validateRequest ;
}
2011-09-28 23:19:26 -07:00
bool imgLoader : : RemoveFromCache ( nsIURI * aKey )
2008-09-04 16:00:42 -07:00
{
2013-09-28 11:28:42 -07:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Cannot use nsIURI off main thread! " ) ;
2011-10-17 07:59:28 -07:00
if ( ! aKey ) return false ;
2008-09-04 16:00:42 -07:00
imgCacheTable & cache = GetCache ( aKey ) ;
imgCacheQueue & queue = GetCacheQueue ( aKey ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2008-09-04 16:00:42 -07:00
aKey - > GetSpec ( spec ) ;
2013-09-28 11:28:42 -07:00
return RemoveFromCache ( spec , cache , queue ) ;
}
bool imgLoader : : RemoveFromCache ( ImageURL * aKey )
{
if ( ! aKey ) return false ;
imgCacheTable & cache = GetCache ( aKey ) ;
imgCacheQueue & queue = GetCacheQueue ( aKey ) ;
nsAutoCString spec ;
aKey - > GetSpec ( spec ) ;
return RemoveFromCache ( spec , cache , queue ) ;
}
bool imgLoader : : RemoveFromCache ( nsCString & spec ,
imgCacheTable & cache ,
imgCacheQueue & queue )
{
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::RemoveFromCache " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
2008-09-04 16:00:42 -07:00
nsRefPtr < imgCacheEntry > entry ;
if ( cache . Get ( spec , getter_AddRefs ( entry ) ) & & entry ) {
cache . Remove ( spec ) ;
2009-01-30 18:17:47 -08:00
NS_ABORT_IF_FALSE ( ! entry - > Evicted ( ) , " Evicting an already-evicted cache entry! " ) ;
// Entries with no proxies are in the tracker.
if ( entry - > HasNoProxies ( ) ) {
2012-06-25 21:20:12 -07:00
if ( mCacheTracker )
mCacheTracker - > RemoveObject ( entry ) ;
2009-01-30 18:17:47 -08:00
queue . Remove ( entry ) ;
}
2011-10-17 07:59:28 -07:00
entry - > SetEvicted ( true ) ;
2009-01-30 18:17:47 -08:00
2013-07-10 02:56:21 -07:00
nsRefPtr < imgRequest > request = entry - > GetRequest ( ) ;
2011-10-17 07:59:28 -07:00
request - > SetIsInCache ( false ) ;
2014-09-05 14:36:11 -07:00
AddToUncachedImages ( request ) ;
2009-03-17 14:07:16 -07:00
2011-10-17 07:59:28 -07:00
return true ;
2008-09-04 16:00:42 -07:00
}
else
2011-10-17 07:59:28 -07:00
return false ;
2008-09-04 16:00:42 -07:00
}
2011-09-28 23:19:26 -07:00
bool imgLoader : : RemoveFromCache ( imgCacheEntry * entry )
2008-09-04 16:00:42 -07:00
{
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC ( GetImgLog ( ) , " imgLoader::RemoveFromCache entry " ) ;
2009-01-30 18:17:47 -08:00
2013-07-10 02:56:21 -07:00
nsRefPtr < imgRequest > request = entry - > GetRequest ( ) ;
2008-09-04 16:00:42 -07:00
if ( request ) {
2013-09-28 11:28:42 -07:00
nsRefPtr < ImageURL > key ;
2011-09-07 16:35:54 -07:00
if ( NS_SUCCEEDED ( request - > GetURI ( getter_AddRefs ( key ) ) ) & & key ) {
2009-01-30 18:17:47 -08:00
imgCacheTable & cache = GetCache ( key ) ;
imgCacheQueue & queue = GetCacheQueue ( key ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2009-01-30 18:17:47 -08:00
key - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::RemoveFromCache " , " entry's uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
cache . Remove ( spec ) ;
if ( entry - > HasNoProxies ( ) ) {
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC ( GetImgLog ( ) , " imgLoader::RemoveFromCache removing from tracker " ) ;
2012-06-25 21:20:12 -07:00
if ( mCacheTracker )
mCacheTracker - > RemoveObject ( entry ) ;
2009-01-30 18:17:47 -08:00
queue . Remove ( entry ) ;
}
2011-10-17 07:59:28 -07:00
entry - > SetEvicted ( true ) ;
request - > SetIsInCache ( false ) ;
2014-09-05 14:36:11 -07:00
AddToUncachedImages ( request ) ;
2009-01-30 18:17:47 -08:00
2011-10-17 07:59:28 -07:00
return true ;
2009-01-30 18:17:47 -08:00
}
2008-09-04 16:00:42 -07:00
}
2011-10-17 07:59:28 -07:00
return false ;
2009-01-30 18:17:47 -08:00
}
2013-03-29 13:14:19 -07:00
static PLDHashOperator EnumEvictEntries ( const nsACString & ,
2009-01-30 18:17:47 -08:00
nsRefPtr < imgCacheEntry > & aData ,
void * data )
{
2013-03-29 13:14:19 -07:00
nsTArray < nsRefPtr < imgCacheEntry > > * entries =
2009-01-30 18:17:47 -08:00
reinterpret_cast < nsTArray < nsRefPtr < imgCacheEntry > > * > ( data ) ;
entries - > AppendElement ( aData ) ;
return PL_DHASH_NEXT ;
2008-09-04 16:00:42 -07:00
}
2009-05-07 13:55:06 -07:00
nsresult imgLoader : : EvictEntries ( imgCacheTable & aCacheToClear )
2008-09-04 16:00:42 -07:00
{
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC ( GetImgLog ( ) , " imgLoader::EvictEntries table " ) ;
2008-09-04 16:00:42 -07:00
// We have to make a temporary, since RemoveFromCache removes the element
// from the queue, invalidating iterators.
nsTArray < nsRefPtr < imgCacheEntry > > entries ;
2009-01-30 18:17:47 -08:00
aCacheToClear . Enumerate ( EnumEvictEntries , & entries ) ;
2012-08-22 08:56:38 -07:00
for ( uint32_t i = 0 ; i < entries . Length ( ) ; + + i )
2008-09-04 16:00:42 -07:00
if ( ! RemoveFromCache ( entries [ i ] ) )
return NS_ERROR_FAILURE ;
return NS_OK ;
}
2009-05-07 13:55:06 -07:00
nsresult imgLoader : : EvictEntries ( imgCacheQueue & aQueueToClear )
{
2012-10-29 16:32:10 -07:00
LOG_STATIC_FUNC ( GetImgLog ( ) , " imgLoader::EvictEntries queue " ) ;
2009-05-07 13:55:06 -07:00
// We have to make a temporary, since RemoveFromCache removes the element
// from the queue, invalidating iterators.
nsTArray < nsRefPtr < imgCacheEntry > > entries ( aQueueToClear . GetNumElements ( ) ) ;
for ( imgCacheQueue : : const_iterator i = aQueueToClear . begin ( ) ; i ! = aQueueToClear . end ( ) ; + + i )
entries . AppendElement ( * i ) ;
2012-08-22 08:56:38 -07:00
for ( uint32_t i = 0 ; i < entries . Length ( ) ; + + i )
2009-05-07 13:55:06 -07:00
if ( ! RemoveFromCache ( entries [ i ] ) )
return NS_ERROR_FAILURE ;
return NS_OK ;
}
2014-09-05 14:36:11 -07:00
void imgLoader : : AddToUncachedImages ( imgRequest * aRequest )
{
MutexAutoLock lock ( mUncachedImagesMutex ) ;
mUncachedImages . PutEntry ( aRequest ) ;
}
void imgLoader : : RemoveFromUncachedImages ( imgRequest * aRequest )
{
MutexAutoLock lock ( mUncachedImagesMutex ) ;
mUncachedImages . RemoveEntry ( aRequest ) ;
}
2008-09-04 16:00:42 -07:00
# define LOAD_FLAGS_CACHE_MASK (nsIRequest::LOAD_BYPASS_CACHE | \
nsIRequest : : LOAD_FROM_CACHE )
# define LOAD_FLAGS_VALIDATE_MASK (nsIRequest::VALIDATE_ALWAYS | \
nsIRequest : : VALIDATE_NEVER | \
nsIRequest : : VALIDATE_ONCE_PER_SESSION )
2012-10-12 05:43:01 -07:00
NS_IMETHODIMP imgLoader : : LoadImageXPCOM ( nsIURI * aURI ,
2007-03-22 10:30:00 -07:00
nsIURI * aInitialDocumentURI ,
nsIURI * aReferrerURI ,
2011-07-14 11:47:32 -07:00
nsIPrincipal * aLoadingPrincipal ,
2007-03-22 10:30:00 -07:00
nsILoadGroup * aLoadGroup ,
2012-10-12 09:11:22 -07:00
imgINotificationObserver * aObserver ,
2007-03-22 10:30:00 -07:00
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
2008-09-04 16:00:42 -07:00
nsISupports * aCacheKey ,
2010-05-20 13:08:02 -07:00
nsIChannelPolicy * aPolicy ,
2007-03-22 10:30:00 -07:00
imgIRequest * * _retval )
{
2012-10-12 05:43:01 -07:00
imgRequestProxy * proxy ;
nsresult result = LoadImage ( aURI ,
aInitialDocumentURI ,
aReferrerURI ,
aLoadingPrincipal ,
aLoadGroup ,
aObserver ,
aCX ,
aLoadFlags ,
aCacheKey ,
aPolicy ,
2013-10-15 18:35:44 -07:00
EmptyString ( ) ,
2012-10-12 05:43:01 -07:00
& proxy ) ;
* _retval = proxy ;
return result ;
}
/* imgIRequest loadImage(in nsIURI aURI, in nsIURI aInitialDocumentURL, in nsIURI aReferrerURI, in nsIPrincipal aLoadingPrincipal, in nsILoadGroup aLoadGroup, in imgINotificationObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in nsIChannelPolicy channelPolicy); */
nsresult imgLoader : : LoadImage ( nsIURI * aURI ,
nsIURI * aInitialDocumentURI ,
nsIURI * aReferrerURI ,
nsIPrincipal * aLoadingPrincipal ,
nsILoadGroup * aLoadGroup ,
imgINotificationObserver * aObserver ,
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
nsISupports * aCacheKey ,
nsIChannelPolicy * aPolicy ,
2013-10-15 18:35:44 -07:00
const nsAString & initiatorType ,
2012-10-12 05:43:01 -07:00
imgRequestProxy * * _retval )
{
VerifyCacheSizes ( ) ;
2007-03-22 10:30:00 -07:00
2008-09-04 16:00:42 -07:00
NS_ASSERTION ( aURI , " imgLoader::LoadImage -- NULL URI pointer " ) ;
2008-09-04 09:36:27 -07:00
2007-03-22 10:30:00 -07:00
if ( ! aURI )
return NS_ERROR_NULL_POINTER ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2008-09-04 16:00:42 -07:00
aURI - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
LOG_SCOPE_WITH_PARAM ( GetImgLog ( ) , " imgLoader::LoadImage " , " aURI " , spec . get ( ) ) ;
2007-03-22 10:30:00 -07:00
2012-07-30 07:20:58 -07:00
* _retval = nullptr ;
2008-09-04 16:00:42 -07:00
nsRefPtr < imgRequest > request ;
2007-03-22 10:30:00 -07:00
nsresult rv ;
nsLoadFlags requestFlags = nsIRequest : : LOAD_NORMAL ;
2012-06-25 21:20:12 -07:00
# ifdef DEBUG
bool isPrivate = false ;
2012-11-03 20:04:07 -07:00
if ( aLoadGroup ) {
2012-06-25 21:20:12 -07:00
nsCOMPtr < nsIInterfaceRequestor > callbacks ;
aLoadGroup - > GetNotificationCallbacks ( getter_AddRefs ( callbacks ) ) ;
if ( callbacks ) {
nsCOMPtr < nsILoadContext > loadContext = do_GetInterface ( callbacks ) ;
isPrivate = loadContext & & loadContext - > UsePrivateBrowsing ( ) ;
}
}
MOZ_ASSERT ( isPrivate = = mRespectPrivacy ) ;
# endif
2007-03-22 10:30:00 -07:00
// Get the default load flags from the loadgroup (if possible)...
if ( aLoadGroup ) {
aLoadGroup - > GetLoadFlags ( & requestFlags ) ;
}
//
// Merge the default load flags with those passed in via aLoadFlags.
// Currently, *only* the caching, validation and background load flags
// are merged...
//
2008-09-04 16:00:42 -07:00
// The flags in aLoadFlags take precedence over the default flags!
2007-03-22 10:30:00 -07:00
//
if ( aLoadFlags & LOAD_FLAGS_CACHE_MASK ) {
// Override the default caching flags...
requestFlags = ( requestFlags & ~ LOAD_FLAGS_CACHE_MASK ) |
( aLoadFlags & LOAD_FLAGS_CACHE_MASK ) ;
}
if ( aLoadFlags & LOAD_FLAGS_VALIDATE_MASK ) {
// Override the default validation flags...
requestFlags = ( requestFlags & ~ LOAD_FLAGS_VALIDATE_MASK ) |
( aLoadFlags & LOAD_FLAGS_VALIDATE_MASK ) ;
}
if ( aLoadFlags & nsIRequest : : LOAD_BACKGROUND ) {
// Propagate background loading...
requestFlags | = nsIRequest : : LOAD_BACKGROUND ;
}
2012-08-22 08:56:38 -07:00
int32_t corsmode = imgIRequest : : CORS_NONE ;
2011-07-14 11:47:34 -07:00
if ( aLoadFlags & imgILoader : : LOAD_CORS_ANONYMOUS ) {
corsmode = imgIRequest : : CORS_ANONYMOUS ;
} else if ( aLoadFlags & imgILoader : : LOAD_CORS_USE_CREDENTIALS ) {
corsmode = imgIRequest : : CORS_USE_CREDENTIALS ;
}
2008-09-04 16:00:42 -07:00
nsRefPtr < imgCacheEntry > entry ;
2007-03-22 10:30:00 -07:00
2009-11-12 15:00:30 -08:00
// Look in the cache for our URI, and then validate it.
// XXX For now ignore aCacheKey. We will need it in the future
// for correctly dealing with image load requests that are a result
// of post data.
imgCacheTable & cache = GetCache ( aURI ) ;
2008-12-11 16:47:47 -08:00
2009-11-12 15:00:30 -08:00
if ( cache . Get ( spec , getter_AddRefs ( entry ) ) & & entry ) {
2010-05-20 13:08:02 -07:00
if ( ValidateEntry ( entry , aURI , aInitialDocumentURI , aReferrerURI ,
2011-10-17 07:59:28 -07:00
aLoadGroup , aObserver , aCX , requestFlags , true ,
2012-11-03 20:04:07 -07:00
_retval , aPolicy , aLoadingPrincipal , corsmode ) ) {
2013-07-10 02:56:21 -07:00
request = entry - > GetRequest ( ) ;
2008-09-04 16:00:42 -07:00
2009-11-12 15:00:30 -08:00
// If this entry has no proxies, its request has no reference to the entry.
if ( entry - > HasNoProxies ( ) ) {
2012-10-29 16:32:10 -07:00
LOG_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::LoadImage() adding proxyless entry " , " uri " , spec . get ( ) ) ;
2009-11-12 15:00:30 -08:00
NS_ABORT_IF_FALSE ( ! request - > HasCacheEntry ( ) , " Proxyless entry's request has cache entry! " ) ;
request - > SetCacheEntry ( entry ) ;
2009-01-30 18:17:47 -08:00
2012-06-25 21:20:12 -07:00
if ( mCacheTracker )
mCacheTracker - > MarkUsed ( entry ) ;
2013-03-29 13:14:19 -07:00
}
2009-01-30 18:17:47 -08:00
2009-11-12 15:00:30 -08:00
entry - > Touch ( ) ;
2009-01-30 18:17:47 -08:00
2008-09-04 16:00:42 -07:00
# ifdef DEBUG_joe
2013-08-23 12:51:00 -07:00
printf ( " CACHEGET: %d %s %d \n " , time ( nullptr ) , spec . get ( ) , entry - > SizeOfData ( ) ) ;
2008-09-04 16:00:42 -07:00
# endif
2009-11-12 15:00:30 -08:00
}
else {
// We can't use this entry. We'll try to load it off the network, and if
// successful, overwrite the old entry in the cache with a new one.
2012-07-30 07:20:58 -07:00
entry = nullptr ;
2007-03-22 10:30:00 -07:00
}
}
2009-07-28 09:13:48 -07:00
// Keep the channel in this scope, so we can adjust its notificationCallbacks
// later when we create the proxy.
nsCOMPtr < nsIChannel > newChannel ;
2008-09-04 16:00:42 -07:00
// If we didn't get a cache hit, we need to load from the network.
if ( ! request ) {
2012-10-29 16:32:10 -07:00
LOG_SCOPE ( GetImgLog ( ) , " imgLoader::LoadImage |cache miss| " ) ;
2007-03-22 10:30:00 -07:00
2011-09-20 14:00:42 -07:00
bool forcePrincipalCheck ;
2007-03-22 10:30:00 -07:00
rv = NewImageChannel ( getter_AddRefs ( newChannel ) ,
2011-09-20 14:00:42 -07:00
& forcePrincipalCheck ,
2007-03-22 10:30:00 -07:00
aURI ,
aInitialDocumentURI ,
aReferrerURI ,
aLoadGroup ,
2009-07-15 00:22:40 -07:00
mAcceptHeader ,
2010-05-20 13:08:02 -07:00
requestFlags ,
2011-09-20 14:00:42 -07:00
aPolicy ,
aLoadingPrincipal ) ;
2007-03-22 10:30:00 -07:00
if ( NS_FAILED ( rv ) )
return NS_ERROR_FAILURE ;
2012-10-03 15:43:26 -07:00
MOZ_ASSERT ( NS_UsePrivateBrowsing ( newChannel ) = = mRespectPrivacy ) ;
2012-06-25 21:20:12 -07:00
NewRequestAndEntry ( forcePrincipalCheck , this , getter_AddRefs ( request ) , getter_AddRefs ( entry ) ) ;
2007-03-22 10:30:00 -07:00
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2008-09-04 16:00:42 -07:00
( " [this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p] \n " , this , request . get ( ) ) ) ;
2007-03-22 10:30:00 -07:00
2014-01-29 19:35:40 -08:00
nsCOMPtr < nsILoadGroup > channelLoadGroup ;
newChannel - > GetLoadGroup ( getter_AddRefs ( channelLoadGroup ) ) ;
request - > Init ( aURI , aURI , channelLoadGroup , newChannel , entry , aCX ,
2011-07-14 11:47:34 -07:00
aLoadingPrincipal , corsmode ) ;
2007-03-22 10:30:00 -07:00
2013-10-15 18:35:44 -07:00
// Add the initiator type for this image load
nsCOMPtr < nsITimedChannel > timedChannel = do_QueryInterface ( newChannel ) ;
if ( timedChannel ) {
timedChannel - > SetInitiatorType ( initiatorType ) ;
}
2011-08-24 13:44:35 -07:00
// Pass the inner window ID of the loading document, if possible.
2010-12-20 08:21:59 -08:00
nsCOMPtr < nsIDocument > doc = do_QueryInterface ( aCX ) ;
if ( doc ) {
2011-08-24 13:44:35 -07:00
request - > SetInnerWindowID ( doc - > InnerWindowID ( ) ) ;
2010-12-20 08:21:59 -08:00
}
2007-03-22 10:30:00 -07:00
// create the proxy listener
2011-07-14 11:47:34 -07:00
nsCOMPtr < nsIStreamListener > pl = new ProxyListener ( request . get ( ) ) ;
// See if we need to insert a CORS proxy between the proxy listener and the
// request.
nsCOMPtr < nsIStreamListener > listener = pl ;
if ( corsmode ! = imgIRequest : : CORS_NONE ) {
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2012-03-02 20:44:55 -08:00
( " [this=%p] imgLoader::LoadImage -- Setting up a CORS load " ,
this ) ) ;
2011-09-28 23:19:26 -07:00
bool withCredentials = corsmode = = imgIRequest : : CORS_USE_CREDENTIALS ;
2011-07-14 11:47:34 -07:00
2012-09-18 19:16:23 -07:00
nsRefPtr < nsCORSListenerProxy > corsproxy =
new nsCORSListenerProxy ( pl , aLoadingPrincipal , withCredentials ) ;
rv = corsproxy - > Init ( newChannel ) ;
2011-07-14 11:47:34 -07:00
if ( NS_FAILED ( rv ) ) {
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2012-03-02 20:44:55 -08:00
( " [this=%p] imgLoader::LoadImage -- nsCORSListenerProxy "
" creation failed: 0x%x \n " , this , rv ) ) ;
request - > CancelAndAbort ( rv ) ;
2011-07-14 11:47:34 -07:00
return NS_ERROR_FAILURE ;
}
2007-03-22 10:30:00 -07:00
2011-07-14 11:47:34 -07:00
listener = corsproxy ;
}
2007-03-22 10:30:00 -07:00
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2007-03-22 10:30:00 -07:00
( " [this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen() \n " , this ) ) ;
2014-06-03 13:37:46 -07:00
mozilla : : net : : PredictorLearn ( aURI , aInitialDocumentURI ,
nsINetworkPredictor : : LEARN_LOAD_SUBRESOURCE , aLoadGroup ) ;
2013-10-25 14:56:58 -07:00
2012-07-30 07:20:58 -07:00
nsresult openRes = newChannel - > AsyncOpen ( listener , nullptr ) ;
2007-03-22 10:30:00 -07:00
if ( NS_FAILED ( openRes ) ) {
2012-10-29 16:32:10 -07:00
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
2007-03-22 10:30:00 -07:00
( " [this=%p] imgLoader::LoadImage -- AsyncOpen() failed: 0x%x \n " ,
this , openRes ) ) ;
2008-12-22 14:20:46 -08:00
request - > CancelAndAbort ( openRes ) ;
2007-03-22 10:30:00 -07:00
return openRes ;
}
2008-09-04 16:00:42 -07:00
// Try to add the new request into the cache.
2009-03-17 14:07:16 -07:00
PutIntoCache ( aURI , entry ) ;
2007-03-22 10:30:00 -07:00
} else {
2013-03-29 13:14:19 -07:00
LOG_MSG_WITH_PARAM ( GetImgLog ( ) ,
2007-03-22 10:30:00 -07:00
" imgLoader::LoadImage |cache hit| " , " request " , request ) ;
}
2009-11-12 15:00:30 -08:00
2008-09-04 16:00:42 -07:00
// If we didn't get a proxy when validating the cache entry, we need to create one.
if ( ! * _retval ) {
2009-11-12 15:00:30 -08:00
// ValidateEntry() has three return values: "Is valid," "might be valid --
// validating over network", and "not valid." If we don't have a _retval,
// we know ValidateEntry is not validating over the network, so it's safe
// to SetLoadId here because we know this request is valid for this context.
//
// Note, however, that this doesn't guarantee the behaviour we want (one
// URL maps to the same image on a page) if we load the same image in a
// different tab (see bug 528003), because its load id will get re-set, and
// that'll cause us to validate over the network.
request - > SetLoadId ( aCX ) ;
2007-03-22 10:30:00 -07:00
2012-10-29 16:32:10 -07:00
LOG_MSG ( GetImgLog ( ) , " imgLoader::LoadImage " , " creating proxy request. " ) ;
2008-09-04 16:00:42 -07:00
rv = CreateNewProxyForRequest ( request , aLoadGroup , aObserver ,
2012-11-03 20:04:07 -07:00
requestFlags , _retval ) ;
2010-05-25 07:34:04 -07:00
if ( NS_FAILED ( rv ) ) {
return rv ;
}
2012-10-12 05:43:01 -07:00
imgRequestProxy * proxy = * _retval ;
2007-03-22 10:30:00 -07:00
2009-07-28 09:13:48 -07:00
// Make sure that OnStatus/OnProgress calls have the right request set, if
// we did create a channel here.
if ( newChannel ) {
nsCOMPtr < nsIInterfaceRequestor > requestor (
new nsProgressNotificationProxy ( newChannel , proxy ) ) ;
if ( ! requestor )
return NS_ERROR_OUT_OF_MEMORY ;
newChannel - > SetNotificationCallbacks ( requestor ) ;
}
2008-09-04 16:00:42 -07:00
// Note that it's OK to add here even if the request is done. If it is,
2010-05-10 20:27:41 -07:00
// it'll send a OnStopRequest() to the proxy in imgRequestProxy::Notify and
// the proxy will be removed from the loadgroup.
2008-09-04 16:00:42 -07:00
proxy - > AddToLoadGroup ( ) ;
2008-09-04 08:23:16 -07:00
2010-07-28 14:52:14 -07:00
// If we're loading off the network, explicitly don't notify our proxy,
// because necko (or things called from necko, such as imgCacheValidator)
// are going to call our notifications asynchronously, and we can't make it
// further asynchronous because observers might rely on imagelib completing
// its work between the channel's OnStartRequest and OnStopRequest.
if ( ! newChannel )
proxy - > NotifyListener ( ) ;
2008-09-04 16:00:42 -07:00
return rv ;
2007-03-22 10:30:00 -07:00
}
2008-09-04 16:00:42 -07:00
NS_ASSERTION ( * _retval , " imgLoader::LoadImage -- no return value " ) ;
2007-03-22 10:30:00 -07:00
2008-09-04 16:00:42 -07:00
return NS_OK ;
2007-03-22 10:30:00 -07:00
}
2012-10-12 05:43:01 -07:00
/* imgIRequest loadImageWithChannelXPCOM(in nsIChannel channel, in imgINotificationObserver aObserver, in nsISupports cx, out nsIStreamListener); */
NS_IMETHODIMP imgLoader : : LoadImageWithChannelXPCOM ( nsIChannel * channel , imgINotificationObserver * aObserver , nsISupports * aCX , nsIStreamListener * * listener , imgIRequest * * _retval )
{
nsresult result ;
imgRequestProxy * proxy ;
result = LoadImageWithChannel ( channel ,
aObserver ,
aCX ,
listener ,
& proxy ) ;
* _retval = proxy ;
return result ;
}
nsresult imgLoader : : LoadImageWithChannel ( nsIChannel * channel , imgINotificationObserver * aObserver , nsISupports * aCX , nsIStreamListener * * listener , imgRequestProxy * * _retval )
2007-03-22 10:30:00 -07:00
{
NS_ASSERTION ( channel , " imgLoader::LoadImageWithChannel -- NULL channel pointer " ) ;
2012-10-03 15:43:26 -07:00
MOZ_ASSERT ( NS_UsePrivateBrowsing ( channel ) = = mRespectPrivacy ) ;
2012-06-25 21:20:12 -07:00
2008-09-04 16:00:42 -07:00
nsRefPtr < imgRequest > request ;
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsIURI > uri ;
channel - > GetURI ( getter_AddRefs ( uri ) ) ;
nsLoadFlags requestFlags = nsIRequest : : LOAD_NORMAL ;
channel - > GetLoadFlags ( & requestFlags ) ;
2008-09-04 16:00:42 -07:00
nsRefPtr < imgCacheEntry > entry ;
2007-03-22 10:30:00 -07:00
2008-09-04 16:00:42 -07:00
if ( requestFlags & nsIRequest : : LOAD_BYPASS_CACHE ) {
RemoveFromCache ( uri ) ;
} else {
// Look in the cache for our URI, and then validate it.
// XXX For now ignore aCacheKey. We will need it in the future
// for correctly dealing with image load requests that are a result
// of post data.
imgCacheTable & cache = GetCache ( uri ) ;
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2008-09-04 16:00:42 -07:00
uri - > GetSpec ( spec ) ;
if ( cache . Get ( spec , getter_AddRefs ( entry ) ) & & entry ) {
// We don't want to kick off another network load. So we ask
// ValidateEntry to only do validation without creating a new proxy. If
// it says that the entry isn't valid any more, we'll only use the entry
// we're getting if the channel is loading from the cache anyways.
//
// XXX -- should this be changed? it's pretty much verbatim from the old
// code, but seems nonsensical.
2012-07-30 07:20:58 -07:00
if ( ValidateEntry ( entry , uri , nullptr , nullptr , nullptr , aObserver , aCX ,
requestFlags , false , nullptr , nullptr , nullptr ,
2012-11-03 20:04:07 -07:00
imgIRequest : : CORS_NONE ) ) {
2013-07-10 02:56:21 -07:00
request = entry - > GetRequest ( ) ;
2007-03-22 10:30:00 -07:00
} else {
2008-09-04 16:00:42 -07:00
nsCOMPtr < nsICachingChannel > cacheChan ( do_QueryInterface ( channel ) ) ;
2011-09-28 23:19:26 -07:00
bool bUseCacheCopy ;
2008-09-04 16:00:42 -07:00
if ( cacheChan )
cacheChan - > IsFromCache ( & bUseCacheCopy ) ;
else
2011-10-17 07:59:28 -07:00
bUseCacheCopy = false ;
2008-09-04 16:00:42 -07:00
2013-07-10 02:56:21 -07:00
if ( ! bUseCacheCopy ) {
2012-07-30 07:20:58 -07:00
entry = nullptr ;
2013-07-10 02:56:21 -07:00
} else {
request = entry - > GetRequest ( ) ;
2008-09-04 16:00:42 -07:00
}
2007-03-22 10:30:00 -07:00
}
2009-01-30 18:17:47 -08:00
if ( request & & entry ) {
// If this entry has no proxies, its request has no reference to the entry.
if ( entry - > HasNoProxies ( ) ) {
2012-10-29 16:32:10 -07:00
LOG_FUNC_WITH_PARAM ( GetImgLog ( ) , " imgLoader::LoadImageWithChannel() adding proxyless entry " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
NS_ABORT_IF_FALSE ( ! request - > HasCacheEntry ( ) , " Proxyless entry's request has cache entry! " ) ;
request - > SetCacheEntry ( entry ) ;
2012-06-25 21:20:12 -07:00
if ( mCacheTracker )
mCacheTracker - > MarkUsed ( entry ) ;
2013-03-29 13:14:19 -07:00
}
2009-01-30 18:17:47 -08:00
}
2007-03-22 10:30:00 -07:00
}
}
nsCOMPtr < nsILoadGroup > loadGroup ;
channel - > GetLoadGroup ( getter_AddRefs ( loadGroup ) ) ;
2011-06-09 12:03:41 -07:00
// Filter out any load flags not from nsIRequest
requestFlags & = nsIRequest : : LOAD_REQUESTMASK ;
2010-07-28 14:52:14 -07:00
2011-04-07 21:55:25 -07:00
nsresult rv = NS_OK ;
2007-03-22 10:30:00 -07:00
if ( request ) {
// we have this in our cache already.. cancel the current (document) load
2009-02-16 03:27:22 -08:00
channel - > Cancel ( NS_ERROR_PARSED_DATA_CACHED ) ; // this should fire an OnStopRequest
2007-03-22 10:30:00 -07:00
2012-07-30 07:20:58 -07:00
* listener = nullptr ; // give them back a null nsIStreamListener
2010-07-28 14:52:14 -07:00
rv = CreateNewProxyForRequest ( request , loadGroup , aObserver ,
2012-11-03 20:04:07 -07:00
requestFlags , _retval ) ;
2010-07-28 14:52:14 -07:00
static_cast < imgRequestProxy * > ( * _retval ) - > NotifyListener ( ) ;
2007-03-22 10:30:00 -07:00
} else {
2011-09-20 14:00:42 -07:00
// Default to doing a principal check because we don't know who
// started that load and whether their principal ended up being
// inherited on the channel.
2012-06-25 21:20:12 -07:00
NewRequestAndEntry ( true , this , getter_AddRefs ( request ) , getter_AddRefs ( entry ) ) ;
2007-03-22 10:30:00 -07:00
2008-12-22 14:20:46 -08:00
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsIURI > originalURI ;
channel - > GetOriginalURI ( getter_AddRefs ( originalURI ) ) ;
2011-07-14 11:47:32 -07:00
// No principal specified here, because we're not passed one.
request - > Init ( originalURI , uri , channel , channel , entry ,
2012-07-30 07:20:58 -07:00
aCX , nullptr , imgIRequest : : CORS_NONE ) ;
2007-03-22 10:30:00 -07:00
2008-09-04 16:00:42 -07:00
ProxyListener * pl = new ProxyListener ( static_cast < nsIStreamListener * > ( request . get ( ) ) ) ;
2007-03-22 10:30:00 -07:00
NS_ADDREF ( pl ) ;
2007-07-08 00:08:04 -07:00
* listener = static_cast < nsIStreamListener * > ( pl ) ;
2007-03-22 10:30:00 -07:00
NS_ADDREF ( * listener ) ;
NS_RELEASE ( pl ) ;
2008-09-04 16:00:42 -07:00
// Try to add the new request into the cache.
2011-07-01 10:03:32 -07:00
PutIntoCache ( originalURI , entry ) ;
2007-03-22 10:30:00 -07:00
2010-07-28 14:52:14 -07:00
rv = CreateNewProxyForRequest ( request , loadGroup , aObserver ,
2012-11-03 20:04:07 -07:00
requestFlags , _retval ) ;
2007-03-22 10:30:00 -07:00
2010-07-28 14:52:14 -07:00
// Explicitly don't notify our proxy, because we're loading off the
// network, and necko (or things called from necko, such as
// imgCacheValidator) are going to call our notifications asynchronously,
// and we can't make it further asynchronous because observers might rely
// on imagelib completing its work between the channel's OnStartRequest and
// OnStopRequest.
}
2007-03-22 10:30:00 -07:00
return rv ;
}
2012-10-03 13:17:47 -07:00
bool imgLoader : : SupportImageWithMimeType ( const char * aMimeType )
2007-03-22 10:30:00 -07:00
{
2012-09-01 19:35:17 -07:00
nsAutoCString mimeType ( aMimeType ) ;
2007-03-22 10:30:00 -07:00
ToLowerCase ( mimeType ) ;
2012-10-03 13:17:47 -07:00
return Image : : GetDecoderType ( mimeType . get ( ) ) ! = Image : : eDecoderType_unknown ;
2007-03-22 10:30:00 -07:00
}
NS_IMETHODIMP imgLoader : : GetMIMETypeFromContent ( nsIRequest * aRequest ,
2012-08-22 08:56:38 -07:00
const uint8_t * aContents ,
uint32_t aLength ,
2007-03-22 10:30:00 -07:00
nsACString & aContentType )
{
return GetMimeTypeFromContent ( ( const char * ) aContents , aLength , aContentType ) ;
}
/* static */
2012-08-22 08:56:38 -07:00
nsresult imgLoader : : GetMimeTypeFromContent ( const char * aContents , uint32_t aLength , nsACString & aContentType )
2007-03-22 10:30:00 -07:00
{
/* Is it a GIF? */
2009-04-05 17:30:03 -07:00
if ( aLength > = 6 & & ( ! nsCRT : : strncmp ( aContents , " GIF87a " , 6 ) | |
! nsCRT : : strncmp ( aContents , " GIF89a " , 6 ) ) )
{
2013-01-08 13:40:47 -08:00
aContentType . AssignLiteral ( IMAGE_GIF ) ;
2007-03-22 10:30:00 -07:00
}
/* or a PNG? */
2009-04-05 17:30:03 -07:00
else if ( aLength > = 8 & & ( ( unsigned char ) aContents [ 0 ] = = 0x89 & &
2007-03-22 10:30:00 -07:00
( unsigned char ) aContents [ 1 ] = = 0x50 & &
( unsigned char ) aContents [ 2 ] = = 0x4E & &
2009-04-05 17:30:03 -07:00
( unsigned char ) aContents [ 3 ] = = 0x47 & &
( unsigned char ) aContents [ 4 ] = = 0x0D & &
( unsigned char ) aContents [ 5 ] = = 0x0A & &
( unsigned char ) aContents [ 6 ] = = 0x1A & &
( unsigned char ) aContents [ 7 ] = = 0x0A ) )
2013-03-29 13:14:19 -07:00
{
2013-01-08 13:40:47 -08:00
aContentType . AssignLiteral ( IMAGE_PNG ) ;
2007-03-22 10:30:00 -07:00
}
/* maybe a JPEG (JFIF)? */
/* JFIF files start with SOI APP0 but older files can start with SOI DQT
* so we test for SOI followed by any marker , i . e . FF D8 FF
* this will also work for SPIFF JPEG files if they appear in the future .
*
* ( JFIF is 0XFF 0XD8 0XFF 0XE0 < skip 2 > 0X4A 0X46 0X49 0X46 0X00 )
*/
else if ( aLength > = 3 & &
( ( unsigned char ) aContents [ 0 ] ) = = 0xFF & &
( ( unsigned char ) aContents [ 1 ] ) = = 0xD8 & &
( ( unsigned char ) aContents [ 2 ] ) = = 0xFF )
{
2013-01-08 13:40:47 -08:00
aContentType . AssignLiteral ( IMAGE_JPEG ) ;
2007-03-22 10:30:00 -07:00
}
/* or how about ART? */
/* ART begins with JG (4A 47). Major version offset 2.
2013-08-23 12:51:00 -07:00
* Minor version offset 3. Offset 4 must be nullptr .
2007-03-22 10:30:00 -07:00
*/
else if ( aLength > = 5 & &
( ( unsigned char ) aContents [ 0 ] ) = = 0x4a & &
( ( unsigned char ) aContents [ 1 ] ) = = 0x47 & &
( ( unsigned char ) aContents [ 4 ] ) = = 0x00 )
{
2013-01-08 13:40:47 -08:00
aContentType . AssignLiteral ( IMAGE_ART ) ;
2007-03-22 10:30:00 -07:00
}
else if ( aLength > = 2 & & ! nsCRT : : strncmp ( aContents , " BM " , 2 ) ) {
2013-01-08 13:40:47 -08:00
aContentType . AssignLiteral ( IMAGE_BMP ) ;
2007-03-22 10:30:00 -07:00
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
// CURs begin with 2-byte 0 followed by 2-byte 2.
else if ( aLength > = 4 & & ( ! memcmp ( aContents , " \000 \000 \001 \000 " , 4 ) | |
! memcmp ( aContents , " \000 \000 \002 \000 " , 4 ) ) ) {
2013-01-08 13:40:47 -08:00
aContentType . AssignLiteral ( IMAGE_ICO ) ;
2007-03-22 10:30:00 -07:00
}
else {
/* none of the above? I give up */
return NS_ERROR_NOT_AVAILABLE ;
}
return NS_OK ;
}
/**
* proxy stream listener class used to handle multipart / x - mixed - replace
*/
# include "nsIRequest.h"
# include "nsIStreamConverterService.h"
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( ProxyListener ,
nsIStreamListener ,
nsIThreadRetargetableStreamListener ,
nsIRequestObserver )
2007-03-22 10:30:00 -07:00
ProxyListener : : ProxyListener ( nsIStreamListener * dest ) :
mDestListener ( dest )
{
/* member initializers and constructor code */
}
ProxyListener : : ~ ProxyListener ( )
{
/* destructor code */
}
/** nsIRequestObserver methods **/
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP ProxyListener : : OnStartRequest ( nsIRequest * aRequest , nsISupports * ctxt )
{
if ( ! mDestListener )
return NS_ERROR_FAILURE ;
nsCOMPtr < nsIChannel > channel ( do_QueryInterface ( aRequest ) ) ;
if ( channel ) {
2012-09-01 19:35:17 -07:00
nsAutoCString contentType ;
2007-03-22 10:30:00 -07:00
nsresult rv = channel - > GetContentType ( contentType ) ;
if ( ! contentType . IsEmpty ( ) ) {
/* If multipart/x-mixed-replace content, we'll insert a MIME decoder
in the pipeline to handle the content and pass it along to our
original listener .
*/
if ( NS_LITERAL_CSTRING ( " multipart/x-mixed-replace " ) . Equals ( contentType ) ) {
nsCOMPtr < nsIStreamConverterService > convServ ( do_GetService ( " @mozilla.org/streamConverters;1 " , & rv ) ) ;
if ( NS_SUCCEEDED ( rv ) ) {
nsCOMPtr < nsIStreamListener > toListener ( mDestListener ) ;
nsCOMPtr < nsIStreamListener > fromListener ;
rv = convServ - > AsyncConvertData ( " multipart/x-mixed-replace " ,
" */* " ,
toListener ,
2012-07-30 07:20:58 -07:00
nullptr ,
2007-03-22 10:30:00 -07:00
getter_AddRefs ( fromListener ) ) ;
if ( NS_SUCCEEDED ( rv ) )
mDestListener = fromListener ;
}
}
}
}
return mDestListener - > OnStartRequest ( aRequest , ctxt ) ;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
NS_IMETHODIMP ProxyListener : : OnStopRequest ( nsIRequest * aRequest , nsISupports * ctxt , nsresult status )
{
if ( ! mDestListener )
return NS_ERROR_FAILURE ;
return mDestListener - > OnStopRequest ( aRequest , ctxt , status ) ;
}
/** nsIStreamListener methods **/
2012-09-05 19:41:02 -07:00
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long long sourceOffset, in unsigned long count); */
NS_IMETHODIMP
ProxyListener : : OnDataAvailable ( nsIRequest * aRequest , nsISupports * ctxt ,
nsIInputStream * inStr , uint64_t sourceOffset ,
uint32_t count )
2007-03-22 10:30:00 -07:00
{
if ( ! mDestListener )
return NS_ERROR_FAILURE ;
return mDestListener - > OnDataAvailable ( aRequest , ctxt , inStr , sourceOffset , count ) ;
}
2013-09-28 11:28:42 -07:00
/** nsThreadRetargetableStreamListener methods **/
NS_IMETHODIMP
ProxyListener : : CheckListenerChain ( )
{
NS_ASSERTION ( NS_IsMainThread ( ) , " Should be on the main thread! " ) ;
nsresult rv = NS_OK ;
nsCOMPtr < nsIThreadRetargetableStreamListener > retargetableListener =
do_QueryInterface ( mDestListener , & rv ) ;
if ( retargetableListener ) {
rv = retargetableListener - > CheckListenerChain ( ) ;
}
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
( " ProxyListener::CheckListenerChain %s [this=%p listener=%p rv=%x] " ,
( NS_SUCCEEDED ( rv ) ? " success " : " failure " ) ,
this , ( nsIStreamListener * ) mDestListener , rv ) ) ;
return rv ;
}
2007-03-22 10:30:00 -07:00
/**
* http validate class . check a channel for a 304
*/
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( imgCacheValidator , nsIStreamListener , nsIRequestObserver ,
nsIThreadRetargetableStreamListener ,
nsIChannelEventSink , nsIInterfaceRequestor ,
nsIAsyncVerifyRedirectCallback )
2007-03-22 10:30:00 -07:00
2011-07-01 10:03:38 -07:00
imgCacheValidator : : imgCacheValidator ( nsProgressNotificationProxy * progress ,
2012-06-25 21:20:12 -07:00
imgLoader * loader , imgRequest * request ,
void * aContext , bool forcePrincipalCheckForCacheEntry )
2011-07-01 10:03:38 -07:00
: mProgressProxy ( progress ) ,
mRequest ( request ) ,
2012-06-25 21:20:12 -07:00
mContext ( aContext ) ,
mImgLoader ( loader )
2011-07-01 10:03:38 -07:00
{
2012-06-25 21:20:12 -07:00
NewRequestAndEntry ( forcePrincipalCheckForCacheEntry , loader , getter_AddRefs ( mNewRequest ) ,
getter_AddRefs ( mNewEntry ) ) ;
2011-07-01 10:03:38 -07:00
}
2007-03-22 10:30:00 -07:00
imgCacheValidator : : ~ imgCacheValidator ( )
{
if ( mRequest ) {
2012-07-30 07:20:58 -07:00
mRequest - > mValidator = nullptr ;
2007-03-22 10:30:00 -07:00
}
}
void imgCacheValidator : : AddProxy ( imgRequestProxy * aProxy )
{
// aProxy needs to be in the loadgroup since we're validating from
// the network.
aProxy - > AddToLoadGroup ( ) ;
mProxies . AppendObject ( aProxy ) ;
}
/** nsIRequestObserver methods **/
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgCacheValidator : : OnStartRequest ( nsIRequest * aRequest , nsISupports * ctxt )
{
2011-07-01 10:03:42 -07:00
// If this request is coming from cache and has the same URI as our
// imgRequest, the request all our proxies are pointing at is valid, and all
// we have to do is tell them to notify their listeners.
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsICachingChannel > cacheChan ( do_QueryInterface ( aRequest ) ) ;
2011-07-01 10:03:42 -07:00
nsCOMPtr < nsIChannel > channel ( do_QueryInterface ( aRequest ) ) ;
2012-11-08 10:54:00 -08:00
if ( cacheChan & & channel & & ! mRequest - > CacheChanged ( aRequest ) ) {
2011-09-28 23:19:26 -07:00
bool isFromCache = false ;
2011-07-01 10:03:42 -07:00
cacheChan - > IsFromCache ( & isFromCache ) ;
2011-06-30 18:58:34 -07:00
2011-07-01 10:03:42 -07:00
nsCOMPtr < nsIURI > channelURI ;
2011-09-28 23:19:26 -07:00
bool sameURI = false ;
2011-07-01 10:03:42 -07:00
channel - > GetURI ( getter_AddRefs ( channelURI ) ) ;
if ( channelURI )
channelURI - > Equals ( mRequest - > mCurrentURI , & sameURI ) ;
if ( isFromCache & & sameURI ) {
2012-08-22 08:56:38 -07:00
uint32_t count = mProxies . Count ( ) ;
for ( int32_t i = count - 1 ; i > = 0 ; i - - ) {
2007-07-08 00:08:04 -07:00
imgRequestProxy * proxy = static_cast < imgRequestProxy * > ( mProxies [ i ] ) ;
2010-07-28 14:52:14 -07:00
2010-08-02 12:44:49 -07:00
// Proxies waiting on cache validation should be deferring notifications.
// Undefer them.
NS_ABORT_IF_FALSE ( proxy - > NotificationsDeferred ( ) ,
" Proxies waiting on cache validation should be "
" deferring notifications! " ) ;
2011-10-17 07:59:28 -07:00
proxy - > SetNotificationsDeferred ( false ) ;
2010-08-02 12:44:49 -07:00
2010-07-28 14:52:14 -07:00
// Notify synchronously, because we're already in OnStartRequest, an
// asynchronously-called function.
proxy - > SyncNotifyListener ( ) ;
2007-03-22 10:30:00 -07:00
}
2011-07-01 10:03:42 -07:00
// We don't need to load this any more.
aRequest - > Cancel ( NS_BINDING_ABORTED ) ;
2007-03-22 10:30:00 -07:00
mRequest - > SetLoadId ( mContext ) ;
2012-07-30 07:20:58 -07:00
mRequest - > mValidator = nullptr ;
2007-03-22 10:30:00 -07:00
2012-07-30 07:20:58 -07:00
mRequest = nullptr ;
2007-03-22 10:30:00 -07:00
2012-07-30 07:20:58 -07:00
mNewRequest = nullptr ;
mNewEntry = nullptr ;
2011-07-01 10:03:38 -07:00
2007-03-22 10:30:00 -07:00
return NS_OK ;
}
}
2008-09-04 16:00:42 -07:00
2009-01-30 18:17:47 -08:00
// We can't load out of cache. We have to create a whole new request for the
// data that's coming in off the channel.
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsIURI > uri ;
2013-09-28 11:28:42 -07:00
{
nsRefPtr < ImageURL > imageURL ;
mRequest - > GetURI ( getter_AddRefs ( imageURL ) ) ;
uri = imageURL - > ToIURI ( ) ;
}
2009-01-30 18:17:47 -08:00
# if defined(PR_LOGGING)
2012-09-01 19:35:17 -07:00
nsAutoCString spec ;
2009-01-30 18:17:47 -08:00
uri - > GetSpec ( spec ) ;
2012-10-29 16:32:10 -07:00
LOG_MSG_WITH_PARAM ( GetImgLog ( ) , " imgCacheValidator::OnStartRequest creating new request " , " uri " , spec . get ( ) ) ;
2009-01-30 18:17:47 -08:00
# endif
2012-08-22 08:56:38 -07:00
int32_t corsmode = mRequest - > GetCORSMode ( ) ;
2011-07-14 11:47:32 -07:00
nsCOMPtr < nsIPrincipal > loadingPrincipal = mRequest - > GetLoadingPrincipal ( ) ;
2007-03-22 10:30:00 -07:00
// Doom the old request's cache entry
mRequest - > RemoveFromCache ( ) ;
2012-07-30 07:20:58 -07:00
mRequest - > mValidator = nullptr ;
mRequest = nullptr ;
2007-03-22 10:30:00 -07:00
2008-12-22 14:20:46 -08:00
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
2007-03-22 10:30:00 -07:00
nsCOMPtr < nsIURI > originalURI ;
channel - > GetOriginalURI ( getter_AddRefs ( originalURI ) ) ;
2012-02-13 14:36:14 -08:00
mNewRequest - > Init ( originalURI , uri , aRequest , channel , mNewEntry ,
2011-09-19 12:57:21 -07:00
mContext , loadingPrincipal ,
2011-07-14 11:47:34 -07:00
corsmode ) ;
2007-03-22 10:30:00 -07:00
2011-07-14 11:47:34 -07:00
mDestListener = new ProxyListener ( mNewRequest ) ;
2007-03-22 10:30:00 -07:00
2009-01-30 18:17:47 -08:00
// Try to add the new request into the cache. Note that the entry must be in
// the cache before the proxies' ownership changes, because adding a proxy
// changes the caching behaviour for imgRequests.
2012-06-25 21:20:12 -07:00
mImgLoader - > PutIntoCache ( originalURI , mNewEntry ) ;
2009-01-30 18:17:47 -08:00
2012-08-22 08:56:38 -07:00
uint32_t count = mProxies . Count ( ) ;
for ( int32_t i = count - 1 ; i > = 0 ; i - - ) {
2007-07-08 00:08:04 -07:00
imgRequestProxy * proxy = static_cast < imgRequestProxy * > ( mProxies [ i ] ) ;
2011-07-01 10:03:38 -07:00
proxy - > ChangeOwner ( mNewRequest ) ;
2010-07-28 14:52:14 -07:00
// Notify synchronously, because we're already in OnStartRequest, an
// asynchronously-called function.
2012-10-22 09:44:53 -07:00
proxy - > SetNotificationsDeferred ( false ) ;
2010-07-28 14:52:14 -07:00
proxy - > SyncNotifyListener ( ) ;
2007-03-22 10:30:00 -07:00
}
2012-07-30 07:20:58 -07:00
mNewRequest = nullptr ;
mNewEntry = nullptr ;
2007-03-22 10:30:00 -07:00
return mDestListener - > OnStartRequest ( aRequest , ctxt ) ;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
NS_IMETHODIMP imgCacheValidator : : OnStopRequest ( nsIRequest * aRequest , nsISupports * ctxt , nsresult status )
{
if ( ! mDestListener )
return NS_OK ;
return mDestListener - > OnStopRequest ( aRequest , ctxt , status ) ;
}
/** nsIStreamListener methods **/
2012-09-05 19:41:02 -07:00
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long long sourceOffset, in unsigned long count); */
NS_IMETHODIMP
imgCacheValidator : : OnDataAvailable ( nsIRequest * aRequest , nsISupports * ctxt ,
nsIInputStream * inStr ,
uint64_t sourceOffset , uint32_t count )
2007-03-22 10:30:00 -07:00
{
if ( ! mDestListener ) {
// XXX see bug 113959
2012-08-22 08:56:38 -07:00
uint32_t _retval ;
2012-07-30 07:20:58 -07:00
inStr - > ReadSegments ( NS_DiscardSegment , nullptr , count , & _retval ) ;
2007-03-22 10:30:00 -07:00
return NS_OK ;
}
return mDestListener - > OnDataAvailable ( aRequest , ctxt , inStr , sourceOffset , count ) ;
}
2011-07-01 10:03:38 -07:00
2013-09-28 11:28:42 -07:00
/** nsIThreadRetargetableStreamListener methods **/
NS_IMETHODIMP
imgCacheValidator : : CheckListenerChain ( )
{
NS_ASSERTION ( NS_IsMainThread ( ) , " Should be on the main thread! " ) ;
nsresult rv = NS_OK ;
nsCOMPtr < nsIThreadRetargetableStreamListener > retargetableListener =
do_QueryInterface ( mDestListener , & rv ) ;
if ( retargetableListener ) {
rv = retargetableListener - > CheckListenerChain ( ) ;
}
PR_LOG ( GetImgLog ( ) , PR_LOG_DEBUG ,
( " [this=%p] imgCacheValidator::CheckListenerChain -- rv %d=%s " ,
this , NS_SUCCEEDED ( rv ) ? " succeeded " : " failed " , rv ) ) ;
return rv ;
}
2011-07-01 10:03:38 -07:00
/** nsIInterfaceRequestor methods **/
NS_IMETHODIMP imgCacheValidator : : GetInterface ( const nsIID & aIID , void * * aResult )
{
if ( aIID . Equals ( NS_GET_IID ( nsIChannelEventSink ) ) )
return QueryInterface ( aIID , aResult ) ;
return mProgressProxy - > GetInterface ( aIID , aResult ) ;
}
// These functions are materially the same as the same functions in imgRequest.
// We duplicate them because we're verifying whether cache loads are necessary,
// not unconditionally loading.
/** nsIChannelEventSink methods **/
NS_IMETHODIMP imgCacheValidator : : AsyncOnChannelRedirect ( nsIChannel * oldChannel ,
2012-08-22 08:56:38 -07:00
nsIChannel * newChannel , uint32_t flags ,
2011-07-01 10:03:38 -07:00
nsIAsyncVerifyRedirectCallback * callback )
{
// Note all cache information we get from the old channel.
mNewRequest - > SetCacheValidation ( mNewEntry , oldChannel ) ;
// Prepare for callback
mRedirectCallback = callback ;
mRedirectChannel = newChannel ;
return mProgressProxy - > AsyncOnChannelRedirect ( oldChannel , newChannel , flags , this ) ;
}
NS_IMETHODIMP imgCacheValidator : : OnRedirectVerifyCallback ( nsresult aResult )
{
// If we've already been told to abort, just do so.
if ( NS_FAILED ( aResult ) ) {
mRedirectCallback - > OnRedirectVerifyCallback ( aResult ) ;
2012-07-30 07:20:58 -07:00
mRedirectCallback = nullptr ;
mRedirectChannel = nullptr ;
2011-07-01 10:03:38 -07:00
return NS_OK ;
}
// make sure we have a protocol that returns data rather than opens
// an external application, e.g. mailto:
nsCOMPtr < nsIURI > uri ;
mRedirectChannel - > GetURI ( getter_AddRefs ( uri ) ) ;
2011-09-28 23:19:26 -07:00
bool doesNotReturnData = false ;
2011-07-01 10:03:38 -07:00
NS_URIChainHasFlags ( uri , nsIProtocolHandler : : URI_DOES_NOT_RETURN_DATA ,
& doesNotReturnData ) ;
nsresult result = NS_OK ;
if ( doesNotReturnData ) {
result = NS_ERROR_ABORT ;
}
mRedirectCallback - > OnRedirectVerifyCallback ( result ) ;
2012-07-30 07:20:58 -07:00
mRedirectCallback = nullptr ;
mRedirectChannel = nullptr ;
2011-07-01 10:03:38 -07:00
return NS_OK ;
}