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"
2014-12-30 15:54:59 -08:00
# include "nsCORSListenerProxy.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"
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"
2014-09-22 14:30:20 -07:00
# include "gfxPrefs.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 ;
2014-11-18 05:46:53 -08:00
using namespace mozilla : : net ;
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
2015-03-21 09:28:04 -07:00
class imgMemoryReporter final : public nsIMemoryReporter
2010-05-21 21:10:14 -07:00
{
2014-11-26 18:00:15 -08:00
~ imgMemoryReporter ( ) { }
2014-06-23 11:49:08 -07:00
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-11-26 18:00:15 -08:00
NS_IMETHOD CollectReports ( nsIHandleReportCallback * aHandleReport ,
2015-03-21 09:28:04 -07:00
nsISupports * aData , bool aAnonymize ) override
2010-05-21 21:10:14 -07:00
{
2014-05-15 16:11:57 -07:00
nsresult rv ;
2014-11-26 18:00:15 -08:00
nsTArray < ImageMemoryCounter > chrome ;
nsTArray < ImageMemoryCounter > content ;
nsTArray < ImageMemoryCounter > 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-11-26 18:00:15 -08:00
mKnownLoaders [ i ] - > mChromeCache . EnumerateRead ( DoRecordCounter , & chrome ) ;
mKnownLoaders [ i ] - > mCache . EnumerateRead ( DoRecordCounter , & content ) ;
2014-09-05 14:36:11 -07:00
MutexAutoLock lock ( mKnownLoaders [ i ] - > mUncachedImagesMutex ) ;
2014-11-26 18:00:15 -08:00
mKnownLoaders [ i ] - >
mUncachedImages . EnumerateEntries ( DoRecordCounterUncached , & 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-11-26 18:00:15 -08:00
rv = ReportCounterArray ( aHandleReport , aData , chrome , " images/chrome " ) ;
2014-05-15 16:11:57 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-11-26 18:00:15 -08:00
rv = ReportCounterArray ( aHandleReport , aData , content ,
" images/content " , aAnonymize ) ;
2014-05-15 16:11:57 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2012-03-01 16:05:32 -08:00
2014-11-26 18:00:15 -08:00
// Uncached images may be content or chrome, so anonymize them.
rv = ReportCounterArray ( aHandleReport , aData , uncached ,
" images/uncached " , aAnonymize ) ;
2014-09-05 14:36:11 -07:00
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 + + ) {
2014-11-26 18:00:15 -08:00
imgLoader : : sMemReporter - > mKnownLoaders [ i ] - >
mCache . EnumerateRead ( DoRecordCounterUsedDecoded , & n ) ;
2012-06-25 21:20:12 -07:00
}
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-11-26 18:00:15 -08:00
struct MemoryCounter
2014-05-15 16:11:57 -07:00
{
2014-11-26 18:00:15 -08:00
MemoryCounter ( )
: mSource ( 0 )
, mDecodedHeap ( 0 )
, mDecodedNonHeap ( 0 )
{ }
void SetSource ( size_t aCount ) { mSource = aCount ; }
size_t Source ( ) const { return mSource ; }
void SetDecodedHeap ( size_t aCount ) { mDecodedHeap = aCount ; }
size_t DecodedHeap ( ) const { return mDecodedHeap ; }
void SetDecodedNonHeap ( size_t aCount ) { mDecodedNonHeap = aCount ; }
size_t DecodedNonHeap ( ) const { return mDecodedNonHeap ; }
MemoryCounter & operator + = ( const MemoryCounter & aOther )
2014-05-15 16:11:57 -07:00
{
2014-11-26 18:00:15 -08:00
mSource + = aOther . mSource ;
mDecodedHeap + = aOther . mDecodedHeap ;
mDecodedNonHeap + = aOther . mDecodedNonHeap ;
return * this ;
2014-05-15 16:11:57 -07:00
}
2014-11-26 18:00:15 -08:00
private :
size_t mSource ;
size_t mDecodedHeap ;
size_t mDecodedNonHeap ;
2014-05-15 16:11:57 -07:00
} ;
2014-11-26 18:00:15 -08:00
struct ImageMemoryCounter
2014-05-15 16:11:57 -07:00
{
2014-11-26 18:00:15 -08:00
ImageMemoryCounter ( uint16_t aType , const nsACString & aURI , bool aIsUsed )
: mURI ( aURI )
, mType ( aType )
, mIsUsed ( aIsUsed )
2014-05-15 16:11:57 -07:00
{
2014-11-26 18:00:15 -08:00
MOZ_ASSERT ( ! mURI . IsEmpty ( ) , " Should have a URI for all images " ) ;
2014-05-15 16:11:57 -07:00
}
2014-11-26 18:00:15 -08:00
nsCString & URI ( ) { return mURI ; }
const nsCString & URI ( ) const { return mURI ; }
uint16_t Type ( ) const { return mType ; }
MemoryCounter & Values ( ) { return mValues ; }
const MemoryCounter & Values ( ) const { return mValues ; }
bool IsUsed ( ) const { return mIsUsed ; }
bool IsNotable ( ) const
2014-05-15 16:11:57 -07:00
{
const size_t NotableThreshold = 16 * 1024 ;
2014-11-26 18:00:15 -08:00
size_t total = mValues . Source ( ) + mValues . DecodedHeap ( )
+ mValues . DecodedNonHeap ( ) ;
2014-05-15 16:11:57 -07:00
return total > = NotableThreshold ;
}
2014-11-26 18:00:15 -08:00
private :
2014-05-08 05:31:55 -07:00
nsCString mURI ;
2014-11-26 18:00:15 -08:00
uint16_t mType ;
MemoryCounter mValues ;
bool mIsUsed ;
2014-05-08 02:53:00 -07:00
} ;
2014-11-26 18:00:15 -08:00
struct MemoryTotal
2014-05-15 16:11:57 -07:00
{
2014-11-26 18:00:15 -08:00
MemoryTotal & operator + = ( const ImageMemoryCounter & aImageCounter )
{
if ( aImageCounter . Type ( ) = = imgIContainer : : TYPE_RASTER ) {
if ( aImageCounter . IsUsed ( ) ) {
mUsedRasterCounter + = aImageCounter . Values ( ) ;
} else {
mUnusedRasterCounter + = aImageCounter . Values ( ) ;
}
} else if ( aImageCounter . Type ( ) = = imgIContainer : : TYPE_VECTOR ) {
if ( aImageCounter . IsUsed ( ) ) {
mUsedVectorCounter + = aImageCounter . Values ( ) ;
} else {
mUnusedVectorCounter + = aImageCounter . Values ( ) ;
}
} else {
MOZ_CRASH ( " Unexpected image type " ) ;
}
return * this ;
}
const MemoryCounter & UsedRaster ( ) const { return mUsedRasterCounter ; }
const MemoryCounter & UnusedRaster ( ) const { return mUnusedRasterCounter ; }
const MemoryCounter & UsedVector ( ) const { return mUsedVectorCounter ; }
const MemoryCounter & UnusedVector ( ) const { return mUnusedVectorCounter ; }
private :
MemoryCounter mUsedRasterCounter ;
MemoryCounter mUnusedRasterCounter ;
MemoryCounter mUsedVectorCounter ;
MemoryCounter mUnusedVectorCounter ;
2010-05-21 21:10:14 -07:00
} ;
2014-11-26 18:00:15 -08:00
// Reports all images of a single kind, e.g. all used chrome images.
nsresult ReportCounterArray ( nsIHandleReportCallback * aHandleReport ,
nsISupports * aData ,
const nsTArray < ImageMemoryCounter > & aCounterArray ,
const char * aPathPrefix ,
bool aAnonymize = false )
2014-05-15 16:11:57 -07:00
{
nsresult rv ;
2014-11-26 18:00:15 -08:00
MemoryTotal summaryTotal ;
MemoryTotal nonNotableTotal ;
2014-05-15 16:11:57 -07:00
// Report notable images, and compute total and non-notable aggregate sizes.
2014-11-26 18:00:15 -08:00
for ( uint32_t i = 0 ; i < aCounterArray . Length ( ) ; i + + ) {
ImageMemoryCounter counter = aCounterArray [ i ] ;
2014-05-20 23:06:54 -07:00
if ( aAnonymize ) {
2014-11-26 18:00:15 -08:00
counter . URI ( ) . Truncate ( ) ;
counter . URI ( ) . AppendPrintf ( " <anonymized-%u> " , i ) ;
2014-05-20 23:06:54 -07:00
} else {
2014-11-26 18:00:15 -08:00
// The URI could be an extremely long data: URI. Truncate if needed.
2014-05-20 23:06:54 -07:00
static const size_t max = 256 ;
2014-11-26 18:00:15 -08:00
if ( counter . URI ( ) . Length ( ) > max ) {
counter . URI ( ) . Truncate ( max ) ;
counter . URI ( ) . AppendLiteral ( " (truncated) " ) ;
2014-05-20 23:06:54 -07:00
}
2014-11-26 18:00:15 -08:00
counter . URI ( ) . ReplaceChar ( ' / ' , ' \\ ' ) ;
2014-05-15 16:11:57 -07:00
}
2014-11-26 18:00:15 -08:00
summaryTotal + = counter ;
2014-05-15 16:11:57 -07:00
2014-11-26 18:00:15 -08:00
if ( counter . IsNotable ( ) ) {
rv = ReportCounter ( aHandleReport , aData , aPathPrefix , counter ) ;
2014-11-26 02:56:28 -08:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2014-11-26 18:00:15 -08:00
} else {
nonNotableTotal + = counter ;
2014-05-15 16:11:57 -07:00
}
}
// Report non-notable images in aggregate.
2014-11-26 18:00:15 -08:00
rv = ReportTotal ( aHandleReport , aData , /* aExplicit = */ true ,
aPathPrefix , " <non-notable images>/ " , nonNotableTotal ) ;
2014-11-26 01:37:57 -08:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2014-11-26 18:00:15 -08:00
// Report a summary in aggregate, outside of the explicit tree.
rv = ReportTotal ( aHandleReport , aData , /* aExplicit = */ false ,
aPathPrefix , " " , summaryTotal ) ;
2014-11-26 01:37:57 -08:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2010-05-21 21:10:14 -07:00
2014-11-26 18:00:15 -08:00
static nsresult ReportCounter ( nsIHandleReportCallback * aHandleReport ,
nsISupports * aData ,
const char * aPathPrefix ,
const ImageMemoryCounter & aCounter )
2014-11-26 01:37:57 -08:00
{
2014-11-26 18:00:15 -08:00
nsAutoCString pathPrefix ( NS_LITERAL_CSTRING ( " explicit/ " ) ) ;
pathPrefix . Append ( aPathPrefix ) ;
pathPrefix . Append ( aCounter . Type ( ) = = imgIContainer : : TYPE_RASTER
? " /raster/ "
: " /vector/ " ) ;
pathPrefix . Append ( aCounter . IsUsed ( ) ? " used/ " : " unused/ " ) ;
pathPrefix . Append ( " image( " ) ;
if ( aCounter . URI ( ) . IsEmpty ( ) ) {
pathPrefix . Append ( " <unknown URI> " ) ;
} else {
pathPrefix . Append ( aCounter . URI ( ) ) ;
}
pathPrefix . Append ( " )/ " ) ;
2014-11-26 01:37:57 -08:00
2014-11-26 18:00:15 -08:00
return ReportValues ( aHandleReport , aData , pathPrefix , aCounter . Values ( ) ) ;
}
static nsresult ReportTotal ( nsIHandleReportCallback * aHandleReport ,
nsISupports * aData ,
bool aExplicit ,
const char * aPathPrefix ,
const char * aPathInfix ,
const MemoryTotal & aTotal )
{
nsresult rv ;
nsAutoCString pathPrefix ;
if ( aExplicit ) {
pathPrefix . Append ( " explicit/ " ) ;
2014-11-26 01:37:57 -08:00
}
2014-11-26 18:00:15 -08:00
pathPrefix . Append ( aPathPrefix ) ;
nsAutoCString rasterUsedPrefix ( pathPrefix ) ;
rasterUsedPrefix . Append ( " /raster/used/ " ) ;
rasterUsedPrefix . Append ( aPathInfix ) ;
rv = ReportValues ( aHandleReport , aData , rasterUsedPrefix ,
aTotal . UsedRaster ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsAutoCString rasterUnusedPrefix ( pathPrefix ) ;
rasterUnusedPrefix . Append ( " /raster/unused/ " ) ;
rasterUnusedPrefix . Append ( aPathInfix ) ;
rv = ReportValues ( aHandleReport , aData , rasterUnusedPrefix ,
aTotal . UnusedRaster ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsAutoCString vectorUsedPrefix ( pathPrefix ) ;
vectorUsedPrefix . Append ( " /vector/used/ " ) ;
vectorUsedPrefix . Append ( aPathInfix ) ;
rv = ReportValues ( aHandleReport , aData , vectorUsedPrefix ,
aTotal . UsedVector ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsAutoCString vectorUnusedPrefix ( pathPrefix ) ;
vectorUnusedPrefix . Append ( " /vector/unused/ " ) ;
vectorUnusedPrefix . Append ( aPathInfix ) ;
rv = ReportValues ( aHandleReport , aData , vectorUnusedPrefix ,
aTotal . UnusedVector ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2014-11-26 01:37:57 -08:00
2014-11-26 18:00:15 -08:00
static nsresult ReportValues ( nsIHandleReportCallback * aHandleReport ,
nsISupports * aData ,
const nsACString & aPathPrefix ,
const MemoryCounter & aCounter )
{
nsresult rv ;
rv = ReportValue ( aHandleReport , aData , KIND_HEAP , aPathPrefix ,
" source " ,
" Raster image source data and vector image documents. " ,
aCounter . Source ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = ReportValue ( aHandleReport , aData , KIND_HEAP , aPathPrefix ,
" decoded-heap " ,
" Decoded image data which is stored on the heap. " ,
aCounter . DecodedHeap ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
rv = ReportValue ( aHandleReport , aData , KIND_NONHEAP , aPathPrefix ,
" decoded-nonheap " ,
" Decoded image data which isn't stored on the heap. " ,
aCounter . DecodedNonHeap ( ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
static nsresult ReportValue ( nsIHandleReportCallback * aHandleReport ,
nsISupports * aData ,
int32_t aKind ,
const nsACString & aPathPrefix ,
const char * aPathSuffix ,
const char * aDescription ,
size_t aValue )
{
if ( aValue = = 0 ) {
return NS_OK ;
}
nsAutoCString desc ( aDescription ) ;
nsAutoCString path ( aPathPrefix ) ;
path . Append ( aPathSuffix ) ;
return aHandleReport - > Callback ( EmptyCString ( ) , path , aKind , UNITS_BYTES ,
aValue , desc , aData ) ;
}
static PLDHashOperator DoRecordCounter ( const nsACString & ,
imgCacheEntry * aEntry ,
void * aUserArg )
{
nsRefPtr < imgRequest > req = aEntry - > GetRequest ( ) ;
RecordCounterForRequest ( req ,
static_cast < nsTArray < ImageMemoryCounter > * > ( aUserArg ) ,
! aEntry - > HasNoProxies ( ) ) ;
2010-05-21 21:10:14 -07:00
return PL_DHASH_NEXT ;
}
2014-11-26 18:00:15 -08:00
static PLDHashOperator DoRecordCounterUncached ( nsPtrHashKey < imgRequest > * aEntry ,
2014-09-05 14:36:11 -07:00
void * aUserArg )
{
nsRefPtr < imgRequest > req = aEntry - > GetKey ( ) ;
2014-11-26 18:00:15 -08:00
RecordCounterForRequest ( req ,
static_cast < nsTArray < ImageMemoryCounter > * > ( aUserArg ) ,
req - > HasConsumers ( ) ) ;
return PL_DHASH_NEXT ;
}
2014-09-05 14:36:11 -07:00
2014-11-26 18:00:15 -08:00
static void RecordCounterForRequest ( imgRequest * aRequest ,
nsTArray < ImageMemoryCounter > * aArray ,
bool aIsUsed )
{
2015-03-23 19:37:44 -07:00
auto image = static_cast < Image * > ( aRequest - > mImage . get ( ) ) ;
2014-11-26 18:00:15 -08:00
if ( ! image ) {
return ;
2014-09-05 14:36:11 -07:00
}
2014-11-26 18:00:15 -08:00
nsRefPtr < ImageURL > imageURL ( image - > GetURI ( ) ) ;
nsAutoCString spec ;
imageURL - > GetSpec ( spec ) ;
ImageMemoryCounter counter ( image - > GetType ( ) , spec , aIsUsed ) ;
counter . Values ( ) . SetSource ( image - >
SizeOfSourceWithComputedFallback ( ImagesMallocSizeOf ) ) ;
counter . Values ( ) . SetDecodedHeap ( image - >
SizeOfDecoded ( gfxMemoryLocation : : IN_PROCESS_HEAP , ImagesMallocSizeOf ) ) ;
counter . Values ( ) . SetDecodedNonHeap ( image - >
SizeOfDecoded ( gfxMemoryLocation : : IN_PROCESS_NONHEAP , nullptr ) ) ;
aArray - > AppendElement ( counter ) ;
2014-09-05 14:36:11 -07:00
}
2014-11-26 18:00:15 -08:00
static PLDHashOperator DoRecordCounterUsedDecoded ( const nsACString & ,
imgCacheEntry * aEntry ,
void * aUserArg )
2011-06-16 11:34:09 -07:00
{
2014-11-26 18:00:15 -08:00
if ( aEntry - > HasNoProxies ( ) ) {
return PL_DHASH_NEXT ;
2014-11-26 01:37:57 -08:00
}
2014-11-26 18:00:15 -08:00
nsRefPtr < imgRequest > req = aEntry - > GetRequest ( ) ;
2015-03-23 19:37:44 -07:00
auto image = static_cast < Image * > ( req - > mImage . get ( ) ) ;
2014-11-26 18:00:15 -08:00
if ( ! image ) {
return PL_DHASH_NEXT ;
}
// Both this and EntryImageSizes measure images/content/raster/used/decoded
// 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.
auto n = static_cast < size_t * > ( aUserArg ) ;
* n + = image - > SizeOfDecoded ( gfxMemoryLocation : : IN_PROCESS_HEAP ,
moz_malloc_size_of ) ;
* n + = image - > SizeOfDecoded ( gfxMemoryLocation : : IN_PROCESS_NONHEAP , nullptr ) ;
2012-03-01 16:05:32 -08:00
return PL_DHASH_NEXT ;
}
2010-05-21 21:10:14 -07:00
} ;
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 ,
2015-01-08 11:48:52 -08:00
int64_t progress ,
int64_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
2014-11-18 05:46:53 -08:00
// to CORS. Also checks the Referrer Policy, since requests with different
// referrers/policies may generate different responses.
2011-07-14 11:47:34 -07:00
static bool
2014-11-18 05:46:53 -08:00
ValidateSecurityInfo ( imgRequest * request , bool forcePrincipalCheck ,
int32_t corsmode , nsIPrincipal * loadingPrincipal ,
ReferrerPolicy referrerPolicy )
2011-07-14 11:47:34 -07:00
{
2014-11-18 05:46:53 -08:00
// If the entry's Referrer Policy doesn't match, we can't use this request.
if ( referrerPolicy ! = request - > GetReferrerPolicy ( ) ) {
return false ;
}
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 ,
2014-11-18 05:46:53 -08:00
ReferrerPolicy aReferrerPolicy ,
2007-03-22 10:30:00 -07:00
nsILoadGroup * aLoadGroup ,
2009-07-15 00:22:40 -07:00
const nsCString & aAcceptHeader ,
2010-05-20 13:08:02 -07:00
nsLoadFlags aLoadFlags ,
2014-08-19 14:49:38 -07:00
nsContentPolicyType aPolicyType ,
2014-09-21 09:45:34 -07:00
nsIPrincipal * aLoadingPrincipal ,
nsISupports * aRequestingContext )
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 ;
2014-09-21 09:45:34 -07:00
2014-11-14 08:56:55 -08:00
nsCOMPtr < nsIPrincipal > triggeringPrincipal = aLoadingPrincipal ;
2014-07-17 16:07:58 -07:00
bool isSandBoxed = false ;
// only inherit if we have a principal
bool inherit = false ;
2014-11-14 08:56:55 -08:00
if ( triggeringPrincipal ) {
inherit = nsContentUtils : : ChannelShouldInheritPrincipal ( triggeringPrincipal ,
2014-07-17 16:07:58 -07:00
aURI ,
false , // aInheritForAboutBlank
false ) ; // aForceInherit
}
else {
2014-11-14 08:56:55 -08:00
triggeringPrincipal = nsContentUtils : : GetSystemPrincipal ( ) ;
2014-09-21 09:45:34 -07:00
}
nsCOMPtr < nsINode > requestingNode = do_QueryInterface ( aRequestingContext ) ;
2014-07-17 16:07:58 -07:00
nsSecurityFlags securityFlags = nsILoadInfo : : SEC_NORMAL ;
if ( inherit ) {
securityFlags | = nsILoadInfo : : SEC_FORCE_INHERIT_PRINCIPAL ;
}
2014-08-19 14:49:38 -07:00
2014-11-14 08:56:55 -08:00
// Note we are calling NS_NewChannelWithTriggeringPrincipal() here with a node
// and a principal. This is for things like background images that are specified
// by user stylesheets, where the document is being styled, but the principal
// is that of the user stylesheet.
if ( requestingNode ) {
rv = NS_NewChannelWithTriggeringPrincipal ( aResult ,
aURI ,
requestingNode ,
triggeringPrincipal ,
securityFlags ,
nsIContentPolicy : : TYPE_IMAGE ,
nullptr , // loadGroup
callbacks ,
aLoadFlags ) ;
}
else {
// either we are loading something inside a document, in which case
// we should always have a requestingNode, or we are loading something
// outside a document, in which case the triggeringPrincipal
// should always be the systemPrincipal.
MOZ_ASSERT ( nsContentUtils : : IsSystemPrincipal ( triggeringPrincipal ) ) ;
rv = NS_NewChannel ( aResult ,
aURI ,
triggeringPrincipal ,
securityFlags ,
nsIContentPolicy : : TYPE_IMAGE ,
nullptr , // loadGroup
callbacks ,
aLoadFlags ) ;
}
2014-09-21 09:45:34 -07:00
2007-03-22 10:30:00 -07:00
if ( NS_FAILED ( rv ) )
return rv ;
2014-07-17 16:07:58 -07:00
* aForcePrincipalCheckForCacheEntry = inherit & & ! isSandBoxed ;
2011-09-20 14:00:42 -07:00
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 ) ;
2014-11-18 05:46:53 -08:00
newHttpChannel - > SetReferrerWithPolicy ( aReferringURI , aReferrerPolicy ) ;
2007-03-22 10:30:00 -07:00
}
// 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 ) ;
}
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 | .
*/
2015-03-04 22:18:09 -08:00
nsRefPtr < imgRequestProxy > proxyRequest = new imgRequestProxy ( ) ;
2008-09-04 16:00:42 -07:00
/* 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 ) ;
2015-03-04 22:18:09 -08:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
2008-09-04 16:00:42 -07:00
return rv ;
}
2015-03-04 22:18:09 -08:00
proxyRequest . forget ( _retval ) ;
2008-09-04 16:00:42 -07:00
return NS_OK ;
}
2015-03-21 09:28:04 -07:00
class imgCacheExpirationTracker final
2012-01-02 12:23:41 -08:00
: 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
}
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 ( )
{
2014-12-22 15:10:44 -08:00
static nsRefPtr < imgLoader > singleton ;
2012-10-12 05:43:01 -07:00
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 + + ;
2015-02-09 14:34:50 -08:00
MOZ_ASSERT ( queuesize = = trackersize , " Queue and tracker sizes out of sync! " ) ;
MOZ_ASSERT ( 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
{
2014-09-22 14:30:20 -07:00
sCacheTimeWeight = gfxPrefs : : ImageCacheTimeWeight ( ) / 1000.0 ;
int32_t cachesize = gfxPrefs : : ImageCacheSize ( ) ;
sCacheMaxSize = cachesize > 0 ? cachesize : 0 ;
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 {
2015-02-09 14:34:50 -08:00
MOZ_ASSERT ( 0 , " Invalid topic received " ) ;
2010-07-11 18:01:53 -07:00
}
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 ) {
2015-03-04 22:18:09 -08:00
nsCOMPtr < nsIProperties > properties = request - > Properties ( ) ;
properties . forget ( _retval ) ;
2008-09-04 16:00:42 -07:00
}
}
return NS_OK ;
}
void imgLoader : : Shutdown ( )
{
2014-04-08 15:51:33 -07:00
NS_IF_RELEASE ( gSingleton ) ;
NS_IF_RELEASE ( gPBSingleton ) ;
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 ,
2014-11-18 05:46:53 -08:00
ReferrerPolicy aReferrerPolicy ,
2008-09-04 16:00:42 -07:00
nsILoadGroup * aLoadGroup ,
2012-10-12 09:11:22 -07:00
imgINotificationObserver * aObserver ,
2008-09-04 16:00:42 -07:00
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
2014-08-19 14:49:38 -07:00
nsContentPolicyType aLoadPolicyType ,
2012-10-12 05:43:01 -07:00
imgRequestProxy * * aProxyRequest ,
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.
2015-03-23 19:37:45 -07:00
if ( request - > GetValidator ( ) ) {
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
2015-03-23 19:37:45 -07:00
request - > GetValidator ( ) - > AddProxy ( proxy ) ;
2010-08-02 12:44:49 -07:00
}
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 ,
2014-11-18 05:46:53 -08:00
aReferrerPolicy ,
2008-09-04 16:00:42 -07:00
aLoadGroup ,
2009-07-15 00:22:40 -07:00
mAcceptHeader ,
2010-05-20 13:08:02 -07:00
aLoadFlags ,
2014-08-19 14:49:38 -07:00
aLoadPolicyType ,
2014-09-21 09:45:34 -07:00
aLoadingPrincipal ,
aCX ) ;
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
}
2015-03-23 19:37:45 -07:00
request - > SetValidator ( hvc ) ;
2008-09-04 16:00:42 -07:00
2010-08-02 12:44:49 -07:00
// 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.
2015-03-04 22:18:09 -08:00
req - > SetNotificationsDeferred ( true ) ;
2010-08-02 12:44:49 -07:00
// Add the proxy without notifying
2015-03-04 22:18:09 -08:00
hvc - > AddProxy ( req ) ;
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 ) ;
2015-03-04 22:18:09 -08:00
if ( NS_WARN_IF ( NS_FAILED ( rv ) ) ) {
return false ;
}
2008-09-04 16:00:42 -07:00
2015-03-04 22:18:09 -08:00
req . forget ( aProxyRequest ) ;
return true ;
2008-09-04 16:00:42 -07:00
}
}
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 ,
2014-11-18 05:46:53 -08:00
ReferrerPolicy aReferrerPolicy ,
2008-09-04 16:00:42 -07:00
nsILoadGroup * aLoadGroup ,
2012-10-12 09:11:22 -07:00
imgINotificationObserver * aObserver ,
2008-09-04 16:00:42 -07:00
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
2014-08-19 14:49:38 -07:00
nsContentPolicyType aLoadPolicyType ,
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: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
2014-11-18 05:46:53 -08:00
if ( ! ValidateSecurityInfo ( request , aEntry - > ForcePrincipalCheck ( ) ,
aCORSMode , aLoadingPrincipal ,
aReferrerPolicy ) )
2011-10-17 07:59:28 -07:00
return false ;
2011-07-14 11:47:34 -07:00
2014-10-22 02:48:36 -07:00
// data URIs are immutable and by their nature can't leak data, so we can
// just return true in that case. Doing so would mean that shift-reload
// doesn't reload data URI documents/images though (which is handy for
// debugging during gecko development) so we make an exception in that case.
2012-11-20 16:58:32 -08:00
nsAutoCString scheme ;
aURI - > GetScheme ( scheme ) ;
2014-10-22 02:48:36 -07:00
if ( scheme . EqualsLiteral ( " data " ) & &
! ( aLoadFlags & nsIRequest : : LOAD_BYPASS_CACHE ) ) {
2012-11-20 16:58:32 -08:00
return true ;
2014-10-22 02:48:36 -07:00
}
2012-11-20 16:58:32 -08:00
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 ;
2015-03-23 19:37:45 -07:00
if ( request - > LoadId ( ) ! = 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 ;
2015-03-23 19:37:45 -07:00
if ( ( appCacheContainer = do_GetInterface ( request - > GetRequest ( ) ) ) ) {
2009-01-04 21:52:22 -08:00
appCacheContainer - > GetApplicationCache ( getter_AddRefs ( requestAppCache ) ) ;
2015-03-23 19:37:45 -07:00
}
if ( ( appCacheContainer = do_QueryInterface ( aLoadGroup ) ) ) {
2009-01-04 21:52:22 -08:00
appCacheContainer - > GetApplicationCache ( getter_AddRefs ( groupAppCache ) ) ;
2015-03-23 19:37:45 -07:00
}
2009-01-04 21:52:22 -08:00
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 ,
2014-11-18 05:46:53 -08:00
aReferrerURI , aReferrerPolicy ,
aLoadGroup , aObserver ,
2014-08-19 14:49:38 -07:00
aCX , aLoadFlags , aLoadPolicyType ,
aProxyRequest , aLoadingPrincipal ,
aCORSMode ) ;
2011-07-14 11:47:34 -07:00
}
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
2015-02-09 14:34:50 -08:00
MOZ_ASSERT ( ! entry - > Evicted ( ) , " Evicting an already-evicted cache entry! " ) ;
2009-01-30 18:17:47 -08:00
// 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 ,
2014-11-18 05:46:53 -08:00
const nsAString & aReferrerPolicy ,
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 ,
2014-08-19 14:49:38 -07:00
nsContentPolicyType aContentPolicyType ,
2007-03-22 10:30:00 -07:00
imgIRequest * * _retval )
{
2014-08-19 14:49:38 -07:00
// Optional parameter, so defaults to 0 (== TYPE_INVALID)
if ( ! aContentPolicyType ) {
aContentPolicyType = nsIContentPolicy : : TYPE_IMAGE ;
}
2012-10-12 05:43:01 -07:00
imgRequestProxy * proxy ;
2014-11-18 05:46:53 -08:00
ReferrerPolicy refpol = ReferrerPolicyFromString ( aReferrerPolicy ) ;
nsresult rv = LoadImage ( aURI ,
aInitialDocumentURI ,
aReferrerURI ,
refpol ,
aLoadingPrincipal ,
aLoadGroup ,
aObserver ,
aCX ,
aLoadFlags ,
aCacheKey ,
aContentPolicyType ,
EmptyString ( ) ,
& proxy ) ;
2012-10-12 05:43:01 -07:00
* _retval = proxy ;
2014-11-18 05:46:53 -08:00
return rv ;
2012-10-12 05:43:01 -07:00
}
2014-10-15 19:11:45 -07:00
// 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);
2012-10-12 05:43:01 -07:00
nsresult imgLoader : : LoadImage ( nsIURI * aURI ,
2014-10-15 19:11:45 -07:00
nsIURI * aInitialDocumentURI ,
nsIURI * aReferrerURI ,
2014-11-18 05:46:53 -08:00
ReferrerPolicy aReferrerPolicy ,
2014-10-15 19:11:45 -07:00
nsIPrincipal * aLoadingPrincipal ,
nsILoadGroup * aLoadGroup ,
imgINotificationObserver * aObserver ,
nsISupports * aCX ,
nsLoadFlags aLoadFlags ,
nsISupports * aCacheKey ,
2014-08-19 14:49:38 -07:00
nsContentPolicyType aContentPolicyType ,
2014-10-15 19:11:45 -07:00
const nsAString & initiatorType ,
imgRequestProxy * * _retval )
2012-10-12 05:43:01 -07:00
{
2014-08-19 14:49:38 -07:00
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 ,
2014-11-18 05:46:53 -08:00
aReferrerPolicy , aLoadGroup , aObserver , aCX ,
requestFlags , aContentPolicyType , true , _retval ,
2014-08-19 14:49:38 -07:00
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 ( ) ) ;
2015-02-09 14:34:50 -08:00
MOZ_ASSERT ( ! request - > HasCacheEntry ( ) , " Proxyless entry's request has cache entry! " ) ;
2009-11-12 15:00:30 -08:00
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 ,
2014-11-18 05:46:53 -08:00
aReferrerPolicy ,
2007-03-22 10:30:00 -07:00
aLoadGroup ,
2009-07-15 00:22:40 -07:00
mAcceptHeader ,
2010-05-20 13:08:02 -07:00
requestFlags ,
2014-08-19 14:49:38 -07:00
aContentPolicyType ,
2014-09-21 09:45:34 -07:00
aLoadingPrincipal ,
aCX ) ;
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 ,
2014-11-18 05:46:53 -08:00
aLoadingPrincipal , corsmode , aReferrerPolicy ) ;
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 ) ;
}
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.
2014-08-19 14:49:38 -07:00
//
// Since aCanMakeNewChannel == false, we don't need to pass content policy
// type/principal/etc
2014-11-18 05:46:53 -08:00
if ( ValidateEntry ( entry , uri , nullptr , nullptr , RP_Default ,
nullptr , aObserver , aCX , requestFlags ,
2014-08-19 14:49:38 -07:00
nsIContentPolicy : : TYPE_INVALID , false , nullptr ,
nullptr , 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 ( ) ) ;
2015-02-09 14:34:50 -08:00
MOZ_ASSERT ( ! request - > HasCacheEntry ( ) , " Proxyless entry's request has cache entry! " ) ;
2009-01-30 18:17:47 -08:00
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 ,
2014-11-18 05:46:53 -08:00
aCX , nullptr , imgIRequest : : CORS_NONE , RP_Default ) ;
2007-03-22 10:30:00 -07:00
2015-03-04 22:18:09 -08:00
nsRefPtr < ProxyListener > pl =
new ProxyListener ( static_cast < nsIStreamListener * > ( request . get ( ) ) ) ;
pl . forget ( listener ) ;
2007-03-22 10:30:00 -07:00
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 ;
}
2014-12-05 11:33:08 -08:00
bool
imgLoader : : SupportImageWithMimeType ( const char * aMimeType ,
AcceptedMimeTypes aAccept
/* = AcceptedMimeTypes::IMAGES */ )
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 ) ;
2014-12-05 11:33:08 -08:00
if ( aAccept = = AcceptedMimeTypes : : IMAGES_AND_DOCUMENTS & &
mimeType . EqualsLiteral ( " image/svg+xml " ) ) {
return true ;
}
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 ) {
2014-10-29 08:35:05 -07:00
// We need to set the initiator type for the image load
nsCOMPtr < nsITimedChannel > timedChannel = do_QueryInterface ( channel ) ;
if ( timedChannel ) {
nsAutoString type ;
timedChannel - > GetInitiatorType ( type ) ;
if ( type . IsEmpty ( ) ) {
timedChannel - > SetInitiatorType ( NS_LITERAL_STRING ( " img " ) ) ;
}
}
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 ,
2015-03-23 19:37:45 -07:00
nsISupports * 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 ) {
2015-03-23 19:37:45 -07:00
mRequest - > SetValidator ( 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 ;
channel - > GetURI ( getter_AddRefs ( channelURI ) ) ;
2015-03-23 19:37:45 -07:00
nsCOMPtr < nsIURI > currentURI ;
mRequest - > GetCurrentURI ( getter_AddRefs ( currentURI ) ) ;
bool sameURI = false ;
if ( channelURI & & currentURI ) {
channelURI - > Equals ( currentURI , & sameURI ) ;
}
2011-07-01 10:03:42 -07:00
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.
2015-02-09 14:34:50 -08:00
MOZ_ASSERT ( 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 ) ;
2015-03-23 19:37:45 -07:00
mRequest - > SetValidator ( 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 ( ) ;
2014-11-18 05:46:53 -08:00
ReferrerPolicy refpol = mRequest - > GetReferrerPolicy ( ) ;
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 ( ) ;
2015-03-23 19:37:45 -07:00
mRequest - > SetValidator ( nullptr ) ;
2012-07-30 07:20:58 -07:00
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 ,
2014-11-18 05:46:53 -08:00
corsmode , refpol ) ;
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 ;
}