Bug 1270680 - Part 1: Double-key the image cache by origin attribute. r=jdm

This commit is contained in:
Jonathan Hao 2016-08-04 20:22:00 +02:00
Родитель 44b84273d1
Коммит ea61afe035
3 изменённых файлов: 55 добавлений и 12 удалений

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

@ -45,8 +45,11 @@ BlobSerial(ImageURL* aURI)
return Nothing();
}
ImageCacheKey::ImageCacheKey(nsIURI* aURI, nsIDocument* aDocument)
ImageCacheKey::ImageCacheKey(nsIURI* aURI,
const PrincipalOriginAttributes& aAttrs,
nsIDocument* aDocument)
: mURI(new ImageURL(aURI))
, mOriginAttributes(aAttrs)
, mControlledDocument(GetControlledDocumentToken(aDocument))
, mIsChrome(URISchemeIs(mURI, "chrome"))
{
@ -56,11 +59,14 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI, nsIDocument* aDocument)
mBlobSerial = BlobSerial(mURI);
}
mHash = ComputeHash(mURI, mBlobSerial, mControlledDocument);
mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument);
}
ImageCacheKey::ImageCacheKey(ImageURL* aURI, nsIDocument* aDocument)
ImageCacheKey::ImageCacheKey(ImageURL* aURI,
const PrincipalOriginAttributes& aAttrs,
nsIDocument* aDocument)
: mURI(aURI)
, mOriginAttributes(aAttrs)
, mControlledDocument(GetControlledDocumentToken(aDocument))
, mIsChrome(URISchemeIs(mURI, "chrome"))
{
@ -70,12 +76,13 @@ ImageCacheKey::ImageCacheKey(ImageURL* aURI, nsIDocument* aDocument)
mBlobSerial = BlobSerial(mURI);
}
mHash = ComputeHash(mURI, mBlobSerial, mControlledDocument);
mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument);
}
ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
: mURI(aOther.mURI)
, mBlobSerial(aOther.mBlobSerial)
, mOriginAttributes(aOther.mOriginAttributes)
, mControlledDocument(aOther.mControlledDocument)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
@ -84,6 +91,7 @@ ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
: mURI(Move(aOther.mURI))
, mBlobSerial(Move(aOther.mBlobSerial))
, mOriginAttributes(aOther.mOriginAttributes)
, mControlledDocument(aOther.mControlledDocument)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
@ -96,6 +104,10 @@ ImageCacheKey::operator==(const ImageCacheKey& aOther) const
if (mControlledDocument != aOther.mControlledDocument) {
return false;
}
// The origin attributes always have to match.
if (mOriginAttributes != aOther.mOriginAttributes) {
return false;
}
if (mBlobSerial || aOther.mBlobSerial) {
// If at least one of us has a blob serial, just compare the blob serial and
// the ref portion of the URIs.
@ -116,12 +128,16 @@ ImageCacheKey::Spec() const
/* static */ uint32_t
ImageCacheKey::ComputeHash(ImageURL* aURI,
const Maybe<uint64_t>& aBlobSerial,
const PrincipalOriginAttributes& aAttrs,
void* aControlledDocument)
{
// Since we frequently call Hash() several times in a row on the same
// ImageCacheKey, as an optimization we compute our hash once and store it.
nsPrintfCString ptr("%p", aControlledDocument);
nsAutoCString suffix;
aAttrs.CreateSuffix(suffix);
if (aBlobSerial) {
// For blob URIs, we hash the serial number of the underlying blob, so that
// different blob URIs which point to the same blob share a cache entry. We
@ -130,13 +146,13 @@ ImageCacheKey::ComputeHash(ImageURL* aURI,
// the same.
nsAutoCString ref;
aURI->GetRef(ref);
return HashGeneric(*aBlobSerial, HashString(ref + ptr));
return HashGeneric(*aBlobSerial, HashString(ref + suffix + ptr));
}
// For non-blob URIs, we hash the URI spec.
nsAutoCString spec;
aURI->GetSpec(spec);
return HashString(spec + ptr);
return HashString(spec + suffix + ptr);
}
/* static */ void*

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

@ -10,6 +10,7 @@
#ifndef mozilla_image_src_ImageCacheKey_h
#define mozilla_image_src_ImageCacheKey_h
#include "mozilla/BasePrincipal.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
@ -32,8 +33,10 @@ class ImageURL;
class ImageCacheKey final
{
public:
ImageCacheKey(nsIURI* aURI, nsIDocument* aDocument);
ImageCacheKey(ImageURL* aURI, nsIDocument* aDocument);
ImageCacheKey(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs,
nsIDocument* aDocument);
ImageCacheKey(ImageURL* aURI, const PrincipalOriginAttributes& aAttrs,
nsIDocument* aDocument);
ImageCacheKey(const ImageCacheKey& aOther);
ImageCacheKey(ImageCacheKey&& aOther);
@ -54,11 +57,13 @@ public:
private:
static uint32_t ComputeHash(ImageURL* aURI,
const Maybe<uint64_t>& aBlobSerial,
const PrincipalOriginAttributes& aAttrs,
void* aControlledDocument);
static void* GetControlledDocumentToken(nsIDocument* aDocument);
RefPtr<ImageURL> mURI;
Maybe<uint64_t> mBlobSerial;
PrincipalOriginAttributes mOriginAttributes;
void* mControlledDocument;
uint32_t mHash;
bool mIsChrome;

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

@ -1352,7 +1352,16 @@ imgLoader::FindEntryProperties(nsIURI* uri,
*_retval = nullptr;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDOMDoc);
ImageCacheKey key(uri, doc);
PrincipalOriginAttributes attrs;
if (doc) {
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
if (principal) {
attrs = BasePrincipal::Cast(principal)->OriginAttributesRef();
}
}
ImageCacheKey key(uri, attrs, doc);
imgCacheTable& cache = GetCache(key);
RefPtr<imgCacheEntry> entry;
@ -2110,7 +2119,11 @@ imgLoader::LoadImage(nsIURI* aURI,
// 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.
ImageCacheKey key(aURI, aLoadingDocument);
PrincipalOriginAttributes attrs;
if (aLoadingPrincipal) {
attrs = BasePrincipal::Cast(aLoadingPrincipal)->OriginAttributesRef();
}
ImageCacheKey key(aURI, attrs, aLoadingDocument);
imgCacheTable& cache = GetCache(key);
if (cache.Get(key, getter_AddRefs(entry)) && entry) {
@ -2314,7 +2327,16 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
ImageCacheKey key(uri, doc);
NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
PrincipalOriginAttributes attrs;
if (loadInfo) {
attrs.InheritFromNecko(loadInfo->GetOriginAttributes());
}
ImageCacheKey key(uri, attrs, doc);
nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL;
channel->GetLoadFlags(&requestFlags);
@ -2416,7 +2438,7 @@ imgLoader::LoadImageWithChannel(nsIChannel* channel,
// constructed above with the *current URI* and not the *original URI*. I'm
// pretty sure this is a bug, and it's preventing us from ever getting a
// cache hit in LoadImageWithChannel when redirects are involved.
ImageCacheKey originalURIKey(originalURI, doc);
ImageCacheKey originalURIKey(originalURI, attrs, doc);
// Default to doing a principal check because we don't know who
// started that load and whether their principal ended up being