Bug 734062 - stale image in the image cache when an updated version is fetched into HTML5 offline cache in background, r=joedrew

This commit is contained in:
Honza Bambas 2012-11-08 19:54:00 +01:00
parent 6019a8993f
commit 33e46a6177
3 changed files with 74 additions and 1 deletions

View File

@ -2112,7 +2112,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
// we have to do is tell them to notify their listeners. // we have to do is tell them to notify their listeners.
nsCOMPtr<nsICachingChannel> cacheChan(do_QueryInterface(aRequest)); nsCOMPtr<nsICachingChannel> cacheChan(do_QueryInterface(aRequest));
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (cacheChan && channel) { if (cacheChan && channel && !mRequest->CacheChanged(aRequest)) {
bool isFromCache = false; bool isFromCache = false;
cacheChan->IsFromCache(&isFromCache); cacheChan->IsFromCache(&isFromCache);

View File

@ -30,6 +30,8 @@
#include "nsIInputStream.h" #include "nsIInputStream.h"
#include "nsIMultiPartChannel.h" #include "nsIMultiPartChannel.h"
#include "nsIHttpChannel.h" #include "nsIHttpChannel.h"
#include "nsIApplicationCache.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIComponentManager.h" #include "nsIComponentManager.h"
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
@ -440,6 +442,67 @@ void imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aReq
} }
} }
namespace { // anon
already_AddRefed<nsIApplicationCache>
GetApplicationCache(nsIRequest* aRequest)
{
nsresult rv;
nsCOMPtr<nsIApplicationCacheChannel> appCacheChan = do_QueryInterface(aRequest);
if (!appCacheChan) {
return nullptr;
}
bool fromAppCache;
rv = appCacheChan->GetLoadedFromApplicationCache(&fromAppCache);
NS_ENSURE_SUCCESS(rv, nullptr);
if (!fromAppCache) {
return nullptr;
}
nsCOMPtr<nsIApplicationCache> appCache;
rv = appCacheChan->GetApplicationCache(getter_AddRefs(appCache));
NS_ENSURE_SUCCESS(rv, nullptr);
return appCache.forget();
}
} // anon
bool
imgRequest::CacheChanged(nsIRequest* aNewRequest)
{
nsresult rv;
nsCOMPtr<nsIApplicationCache> newAppCache = GetApplicationCache(aNewRequest);
NS_ENSURE_SUCCESS(rv, true); // cannot determine, play safely
// Application cache not involved at all or the same app cache involved
// in both of the loads (original and new).
if (newAppCache == mApplicationCache)
return false;
// In a rare case it may happen that two objects still refer
// the same application cache version.
if (newAppCache && mApplicationCache) {
nsAutoCString oldAppCacheClientId, newAppCacheClientId;
rv = mApplicationCache->GetClientID(oldAppCacheClientId);
NS_ENSURE_SUCCESS(rv, true);
rv = newAppCache->GetClientID(newAppCacheClientId);
NS_ENSURE_SUCCESS(rv, true);
if (oldAppCacheClientId == newAppCacheClientId)
return false;
}
// When we get here, app caches differ or app cache is involved
// just in one of the loads what we also consider as a change
// in a loading cache.
return true;
}
nsresult nsresult
imgRequest::LockImage() imgRequest::LockImage()
{ {
@ -547,6 +610,8 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
SetCacheValidation(mCacheEntry, aRequest); SetCacheValidation(mCacheEntry, aRequest);
mApplicationCache = GetApplicationCache(aRequest);
// Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace... // Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace...
if (GetStatusTracker().ConsumerCount() == 0) { if (GetStatusTracker().ConsumerCount() == 0) {
this->Cancel(NS_IMAGELIB_ERROR_FAILURE); this->Cancel(NS_IMAGELIB_ERROR_FAILURE);

View File

@ -16,6 +16,7 @@
#include "nsIURI.h" #include "nsIURI.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsITimedChannel.h" #include "nsITimedChannel.h"
#include "nsIApplicationCache.h"
#include "nsCategoryCache.h" #include "nsCategoryCache.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -91,6 +92,12 @@ public:
// wins. // wins.
static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest); static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest);
// Check if application cache of the original load is different from
// application cache of the new load. Also lack of application cache
// on one of the loads is considered a change of a loading cache since
// HTTP cache may contain a different data then app cache.
bool CacheChanged(nsIRequest* aNewRequest);
bool GetMultipart() const { return mIsMultiPartChannel; } bool GetMultipart() const { return mIsMultiPartChannel; }
// The CORS mode for which we loaded this image. // The CORS mode for which we loaded this image.
@ -200,6 +207,7 @@ private:
nsCOMPtr<nsISupports> mSecurityInfo; nsCOMPtr<nsISupports> mSecurityInfo;
nsCOMPtr<nsIChannel> mChannel; nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink; nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
nsCOMPtr<nsIApplicationCache> mApplicationCache;
nsCOMPtr<nsITimedChannel> mTimedChannel; nsCOMPtr<nsITimedChannel> mTimedChannel;