mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 12:50:09 +00:00
Bug 479328 and bug 481753 - Ensure imgRequest always knows when it's in the cache, and doesn't try to do cache manipulation when it isn't. Also, fix redirect handling to not simply invalidate the cache entry. r=vlad, sr=bzbarsky
This commit is contained in:
parent
2a9c7ac66c
commit
cc15c830d3
@ -128,8 +128,6 @@ static PRBool NewRequestAndEntry(nsIURI *uri, imgRequest **request, imgCacheEntr
|
||||
NS_ADDREF(*request);
|
||||
NS_ADDREF(*entry);
|
||||
|
||||
imgLoader::SetHasNoProxies(uri, *entry);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -267,8 +265,6 @@ void imgCacheEntry::TouchWithSize(PRInt32 diff)
|
||||
// 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()) {
|
||||
// We can't use mKeyURI here, because we're not guaranteed to be updated if
|
||||
// the request has no observers and has thus dropped its reference to us.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mRequest->GetKeyURI(getter_AddRefs(uri));
|
||||
imgLoader::CacheEntriesChanged(uri, diff);
|
||||
@ -285,8 +281,6 @@ void imgCacheEntry::Touch(PRBool updateTime /* = PR_TRUE */)
|
||||
// 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()) {
|
||||
// We can't use mKeyURI here, because we're not guaranteed to be updated if
|
||||
// the request has no observers and has thus dropped its reference to us.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mRequest->GetKeyURI(getter_AddRefs(uri));
|
||||
imgLoader::CacheEntriesChanged(uri);
|
||||
@ -711,6 +705,27 @@ PRBool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
|
||||
if (!cache.Put(spec, entry))
|
||||
return PR_FALSE;
|
||||
|
||||
// We can be called to resurrect an evicted entry.
|
||||
if (entry->Evicted())
|
||||
entry->SetEvicted(PR_FALSE);
|
||||
|
||||
// If we're resurrecting an entry with no proxies, put it back in the
|
||||
// tracker and queue.
|
||||
if (entry->HasNoProxies()) {
|
||||
nsresult addrv = NS_OK;
|
||||
|
||||
if (gCacheTracker)
|
||||
addrv = gCacheTracker->AddObject(entry);
|
||||
|
||||
if (NS_SUCCEEDED(addrv)) {
|
||||
imgCacheQueue &queue = GetCacheQueue(key);
|
||||
queue.Push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<imgRequest> request(getter_AddRefs(entry->GetRequest()));
|
||||
request->SetIsInCache(PR_TRUE);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -1039,6 +1054,9 @@ PRBool imgLoader::RemoveFromCache(nsIURI *aKey)
|
||||
|
||||
entry->SetEvicted(PR_TRUE);
|
||||
|
||||
nsRefPtr<imgRequest> request(getter_AddRefs(entry->GetRequest()));
|
||||
request->SetIsInCache(PR_FALSE);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
else
|
||||
@ -1070,6 +1088,7 @@ PRBool imgLoader::RemoveFromCache(imgCacheEntry *entry)
|
||||
}
|
||||
|
||||
entry->SetEvicted(PR_TRUE);
|
||||
request->SetIsInCache(PR_FALSE);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -1269,8 +1288,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
|
||||
}
|
||||
|
||||
// Try to add the new request into the cache.
|
||||
if (!PutIntoCache(aURI, entry))
|
||||
request->SetCacheable(PR_FALSE);
|
||||
PutIntoCache(aURI, entry);
|
||||
|
||||
// If we did get a cache hit, use it.
|
||||
} else {
|
||||
@ -1406,8 +1424,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
|
||||
NS_RELEASE(pl);
|
||||
|
||||
// Try to add the new request into the cache.
|
||||
if (!PutIntoCache(uri, entry))
|
||||
request->SetCacheable(PR_FALSE);
|
||||
PutIntoCache(uri, entry);
|
||||
}
|
||||
|
||||
// XXX: It looks like the wrong load flags are being passed in...
|
||||
@ -1686,8 +1703,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
|
||||
// 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.
|
||||
if (!sImgLoader.PutIntoCache(uri, entry))
|
||||
request->SetCacheable(PR_FALSE);
|
||||
sImgLoader.PutIntoCache(uri, entry);
|
||||
|
||||
PRUint32 count = mProxies.Count();
|
||||
for (PRInt32 i = count-1; i>=0; i--) {
|
||||
|
@ -168,7 +168,6 @@ private: // data
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
nsRefPtr<imgRequest> mRequest;
|
||||
nsCOMPtr<nsIURI> mKeyURI;
|
||||
PRUint32 mDataSize;
|
||||
PRInt32 mTouchedTime;
|
||||
PRInt32 mExpiryTime;
|
||||
|
@ -85,7 +85,7 @@ imgRequest::imgRequest() :
|
||||
mImageStatus(imgIRequest::STATUS_NONE), mState(0), mCacheId(0),
|
||||
mValidator(nsnull), mImageSniffers("image-sniffing-services"),
|
||||
mIsMultiPartChannel(PR_FALSE), mLoading(PR_FALSE), mProcessing(PR_FALSE),
|
||||
mHadLastPart(PR_FALSE), mGotData(PR_FALSE), mIsCacheable(PR_TRUE)
|
||||
mHadLastPart(PR_FALSE), mGotData(PR_FALSE), mIsInCache(PR_FALSE)
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
@ -419,14 +419,15 @@ void imgRequest::RemoveFromCache()
|
||||
{
|
||||
LOG_SCOPE(gImgLog, "imgRequest::RemoveFromCache");
|
||||
|
||||
if (mIsCacheable) {
|
||||
if (mIsInCache) {
|
||||
// mCacheEntry is nulled out when we have no more observers.
|
||||
if (mCacheEntry)
|
||||
imgLoader::RemoveFromCache(mCacheEntry);
|
||||
else
|
||||
imgLoader::RemoveFromCache(mKeyURI);
|
||||
|
||||
mCacheEntry = nsnull;
|
||||
}
|
||||
|
||||
mCacheEntry = nsnull;
|
||||
}
|
||||
|
||||
PRBool imgRequest::HaveProxyWithObserver(imgRequestProxy* aProxyToIgnore) const
|
||||
@ -473,13 +474,10 @@ void imgRequest::AdjustPriority(imgRequestProxy *proxy, PRInt32 delta)
|
||||
p->AdjustPriority(delta);
|
||||
}
|
||||
|
||||
void imgRequest::SetCacheable(PRBool cacheable)
|
||||
void imgRequest::SetIsInCache(PRBool incache)
|
||||
{
|
||||
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequest::SetIsCacheable", "cacheable", cacheable);
|
||||
mIsCacheable = cacheable;
|
||||
|
||||
if (!mIsCacheable)
|
||||
mCacheEntry = nsnull;
|
||||
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequest::SetIsCacheable", "incache", incache);
|
||||
mIsInCache = incache;
|
||||
}
|
||||
|
||||
/** imgILoad methods **/
|
||||
@ -1079,29 +1077,42 @@ imgRequest::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PR
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
nsCAutoString spec;
|
||||
mKeyURI->GetSpec(spec);
|
||||
|
||||
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "old", spec.get());
|
||||
#endif
|
||||
|
||||
RemoveFromCache();
|
||||
|
||||
mChannel = newChannel;
|
||||
|
||||
newChannel->GetOriginalURI(getter_AddRefs(mKeyURI));
|
||||
// Don't make any cache changes if we're going to point to the same thing. We
|
||||
// compare specs and not just URIs here because URIs that compare as
|
||||
// .Equals() might have different hashes.
|
||||
nsCAutoString oldspec;
|
||||
if (mKeyURI)
|
||||
mKeyURI->GetSpec(oldspec);
|
||||
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "old", oldspec.get());
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
mKeyURI->GetSpec(spec);
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
newChannel->GetOriginalURI(getter_AddRefs(newURI));
|
||||
nsCAutoString newspec;
|
||||
if (newURI)
|
||||
newURI->GetSpec(newspec);
|
||||
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "new", newspec.get());
|
||||
|
||||
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "new", spec.get());
|
||||
#endif
|
||||
if (oldspec != newspec) {
|
||||
if (mIsInCache) {
|
||||
// Remove the cache entry from the cache, but don't null out mCacheEntry
|
||||
// (as imgRequest::RemoveFromCache() does), because we need it to put
|
||||
// ourselves back in the cache.
|
||||
if (mCacheEntry)
|
||||
imgLoader::RemoveFromCache(mCacheEntry);
|
||||
else
|
||||
imgLoader::RemoveFromCache(mKeyURI);
|
||||
}
|
||||
|
||||
if (mIsCacheable) {
|
||||
// If we don't still have a cache entry, we don't want to refresh the cache.
|
||||
if (mKeyURI && mCacheEntry)
|
||||
imgLoader::PutIntoCache(mKeyURI, mCacheEntry);
|
||||
mKeyURI = newURI;
|
||||
|
||||
if (mIsInCache) {
|
||||
// If we don't still have a URI or cache entry, we don't want to put
|
||||
// ourselves back into the cache.
|
||||
if (mKeyURI && mCacheEntry)
|
||||
imgLoader::PutIntoCache(mKeyURI, mCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -164,10 +164,10 @@ private:
|
||||
// Return whether we've seen some data at this point
|
||||
PRBool HasTransferredData() const { return mGotData; }
|
||||
|
||||
// Set whether this request is cacheable. By default, all requests are
|
||||
// cacheable, but they might not be if there is already a request with this
|
||||
// key URI in the cache.
|
||||
void SetCacheable(PRBool cacheable);
|
||||
// Set whether this request is stored in the cache. If it isn't, regardless
|
||||
// of whether this request has a non-null mCacheEntry, this imgRequest won't
|
||||
// try to update or modify the image cache.
|
||||
void SetIsInCache(PRBool cacheable);
|
||||
|
||||
public:
|
||||
NS_DECL_IMGILOAD
|
||||
@ -213,7 +213,7 @@ private:
|
||||
PRPackedBool mProcessing : 1;
|
||||
PRPackedBool mHadLastPart : 1;
|
||||
PRPackedBool mGotData : 1;
|
||||
PRPackedBool mIsCacheable : 1;
|
||||
PRPackedBool mIsInCache : 1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -467,6 +467,9 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
|
||||
testURL += "?" + "&".join(urlOpts)
|
||||
|
||||
browserEnv["XPCOM_MEM_BLOAT_LOG"] = LEAK_REPORT_FILE
|
||||
if options.a11y:
|
||||
browserEnv["XPCOM_MEM_REFCNT_LOG"] = PROFILE_DIRECTORY + "/refcnt.log"
|
||||
browserEnv["XPCOM_MEM_LOG_CLASSES"] = "imgRequest,imgCacheEntry"
|
||||
|
||||
if options.fatalAssertions:
|
||||
browserEnv["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
|
||||
|
Loading…
x
Reference in New Issue
Block a user