Bug 457809 - Speculatively load images from preloading. r=mrbkap, sr=bzbarsky

This commit is contained in:
bjarne@runitsoft.com 2009-07-07 22:23:20 -07:00
Родитель 909cc48b7b
Коммит 136ecf84de
6 изменённых файлов: 84 добавлений и 5 удалений

Просмотреть файл

@ -81,6 +81,7 @@ class nsIURI;
class imgIDecoderObserver;
class imgIRequest;
class imgILoader;
class imgICache;
class nsIPrefBranch;
class nsIImage;
class nsIImageLoadingContent;
@ -647,6 +648,11 @@ public:
PRInt32 aLoadFlags,
imgIRequest** aRequest);
/**
* Returns whether the given URI is in the image cache.
*/
static PRBool IsImageInCache(nsIURI* aURI);
/**
* Method to get an nsIImage from an image loading content
*
@ -1504,6 +1510,7 @@ private:
static nsIPref *sPref;
static imgILoader* sImgLoader;
static imgICache* sImgCache;
static nsIConsoleService* sConsoleService;

Просмотреть файл

@ -105,8 +105,8 @@ class nsIBoxObject;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{0x2c155ed0, 0x3302, 0x4cff, \
{0x9d, 0xb3, 0xed, 0x0c, 0xcd, 0xfc, 0x50, 0x06 } }
{ 0x46003091, 0x7f99, 0x420f, \
{ 0x95, 0xbc, 0x28, 0xd7, 0xd5, 0x01, 0x5a, 0x41 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1148,6 +1148,14 @@ public:
PRUint32 EventHandlingSuppressed() const { return mEventsSuppressed; }
PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
/**
* Called by nsParser to preload images. Can be removed and code moved
* to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
* parser-module is linked with gklayout-module.
*/
virtual void MaybePreLoadImage(nsIURI* uri) = 0;
protected:
~nsIDocument()
{

Просмотреть файл

@ -179,6 +179,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIConsoleService.h"
#include "mozAutoDocUpdate.h"
#include "imgICache.h"
#include "jsinterp.h"
const char kLoadAsData[] = "loadAsData";
@ -200,6 +201,7 @@ nsIXTFService *nsContentUtils::sXTFService = nsnull;
nsIPrefBranch *nsContentUtils::sPrefBranch = nsnull;
nsIPref *nsContentUtils::sPref = nsnull;
imgILoader *nsContentUtils::sImgLoader;
imgICache *nsContentUtils::sImgCache;
nsIConsoleService *nsContentUtils::sConsoleService;
nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sEventTable = nsnull;
nsIStringBundleService *nsContentUtils::sStringBundleService;
@ -330,6 +332,10 @@ nsContentUtils::Init()
if (NS_FAILED(rv)) {
// no image loading for us. Oh, well.
sImgLoader = nsnull;
sImgCache = nsnull;
} else {
if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache )))
sImgCache = nsnull;
}
sPtrsToPtrsToRelease = new nsTArray<nsISupports**>();
@ -893,6 +899,7 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sXTFService);
#endif
NS_IF_RELEASE(sImgLoader);
NS_IF_RELEASE(sImgCache);
NS_IF_RELEASE(sPrefBranch);
NS_IF_RELEASE(sPref);
#ifdef IBMBIDI
@ -2383,6 +2390,19 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
return NS_FAILED(rv) ? PR_FALSE : NS_CP_ACCEPTED(decision);
}
// static
PRBool
nsContentUtils::IsImageInCache(nsIURI* aURI)
{
if (!sImgCache) return PR_FALSE;
// If something unexpected happened we return false, otherwise if props
// is set, the image is cached and we return true
nsCOMPtr<nsIProperties> props;
nsresult rv = sImgCache->FindEntryProperties(aURI, getter_AddRefs(props));
return (NS_SUCCEEDED(rv) && props);
}
// static
nsresult
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,

Просмотреть файл

@ -1780,6 +1780,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mVisitednessChangedURIs)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPreloadingImages)
#ifdef MOZ_SMIL
// Traverse animation components
@ -1824,6 +1825,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mParentDocument = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPreloadingImages)
// nsDocument has a pretty complex destructor, so we're going to
// assume that *most* cycles you actually want to break somewhere
// else, and not unlink an awful lot here.
@ -3863,6 +3866,9 @@ nsDocument::DispatchContentLoadedEvents()
// If you add early returns from this method, make sure you're
// calling UnblockOnload properly.
// Unpin references to preloaded images
mPreloadingImages.Clear();
// Fire a DOM event notifying listeners that this document has been
// loaded (excluding images and other loads initiated by this
// document).
@ -7485,6 +7491,34 @@ FireOrClearDelayedEvents(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments,
}
}
void
nsDocument::MaybePreLoadImage(nsIURI* uri)
{
// Early exit if the img is already present in the img-cache
// which indicates that the "real" load has already started and
// that we shouldn't preload it.
if (nsContentUtils::IsImageInCache(uri)) {
return;
}
// Image not in cache - trigger preload
nsCOMPtr<imgIRequest> request;
nsresult rv =
nsContentUtils::LoadImage(uri,
this,
NodePrincipal(),
mDocumentURI, // uri of document used as referrer
nsnull, // no observer
nsIRequest::LOAD_NORMAL,
getter_AddRefs(request));
// Pin image-reference to avoid evicting it from the img-cache before
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
// unlink
if (NS_SUCCEEDED(rv)) {
mPreloadingImages.AppendObject(request);
}
}
class nsDelayedEventDispatcher : public nsRunnable
{
public:

Просмотреть файл

@ -116,6 +116,7 @@
#include "nsIProgressEventSink.h"
#include "nsISecurityEventSink.h"
#include "nsIChannelEventSink.h"
#include "imgIRequest.h"
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
@ -1006,6 +1007,8 @@ public:
void MaybeInitializeFinalizeFrameLoaders();
void MaybeEndOutermostXBLUpdate();
virtual void MaybePreLoadImage(nsIURI* uri);
protected:
void RegisterNamedItems(nsIContent *aContent);
@ -1264,6 +1267,9 @@ private:
nsExternalResourceMap mExternalResourceMap;
// All images in process of being preloaded
nsCOMArray<imgIRequest> mPreloadingImages;
#ifdef MOZ_SMIL
nsAutoPtr<nsSMILAnimationController> mAnimationController;
#endif // MOZ_SMIL

Просмотреть файл

@ -382,6 +382,9 @@ nsPreloadURIs::PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::Prefetc
case nsSpeculativeScriptThread::SCRIPT:
doc->ScriptLoader()->PreloadURI(uri, pe.charset, pe.elementType);
break;
case nsSpeculativeScriptThread::IMAGE:
doc->MaybePreLoadImage(uri);
break;
case nsSpeculativeScriptThread::STYLESHEET: {
nsCOMPtr<nsICSSLoaderObserver> obs = new nsDummyCSSLoaderObserver();
doc->CSSLoader()->LoadSheet(uri, doc->NodePrincipal(),
@ -389,9 +392,6 @@ nsPreloadURIs::PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::Prefetc
obs);
break;
}
case nsSpeculativeScriptThread::IMAGE:
NS_NOTREACHED("We don't scan these yet");
break;
case nsSpeculativeScriptThread::NONE:
NS_NOTREACHED("Uninitialized preload entry?");
break;
@ -601,6 +601,10 @@ nsSpeculativeScriptThread::ProcessToken(CToken *aToken)
ptype = STYLESHEET;
break;
case eHTMLTag_img:
ptype = IMAGE;
break;
case eHTMLTag_script:
ptype = SCRIPT;
break;