Bug 1202085 - Part 4: Add an ID for controlled document to the image cache key; r=seth

This ID will be null for non-controlled documents and also for image cache
entries for which a document is not available, and it will be the numerical
value of the document pointer for controlled documents.

This effectively makes sure that a controlled document doesn't share its
image cache entries with anything else.
This commit is contained in:
Ehsan Akhgari
2015-10-27 14:12:46 -04:00
parent 4892e4602a
commit b2b0a28d1e
4 changed files with 57 additions and 15 deletions

View File

@@ -10,6 +10,10 @@
#include "ImageURL.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsString.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
#include "nsPrintfCString.h"
namespace mozilla {
@@ -42,8 +46,9 @@ BlobSerial(ImageURL* aURI)
return Nothing();
}
ImageCacheKey::ImageCacheKey(nsIURI* aURI)
ImageCacheKey::ImageCacheKey(nsIURI* aURI, nsIDOMDocument* aDocument)
: mURI(new ImageURL(aURI))
, mControlledDocument(GetControlledDocumentToken(aDocument))
, mIsChrome(URISchemeIs(mURI, "chrome"))
{
MOZ_ASSERT(NS_IsMainThread());
@@ -52,11 +57,12 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI)
mBlobSerial = BlobSerial(mURI);
}
mHash = ComputeHash(mURI, mBlobSerial);
mHash = ComputeHash(mURI, mBlobSerial, mControlledDocument);
}
ImageCacheKey::ImageCacheKey(ImageURL* aURI)
ImageCacheKey::ImageCacheKey(ImageURL* aURI, nsIDOMDocument* aDocument)
: mURI(aURI)
, mControlledDocument(GetControlledDocumentToken(aDocument))
, mIsChrome(URISchemeIs(mURI, "chrome"))
{
MOZ_ASSERT(aURI);
@@ -65,12 +71,13 @@ ImageCacheKey::ImageCacheKey(ImageURL* aURI)
mBlobSerial = BlobSerial(mURI);
}
mHash = ComputeHash(mURI, mBlobSerial);
mHash = ComputeHash(mURI, mBlobSerial, mControlledDocument);
}
ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
: mURI(aOther.mURI)
, mBlobSerial(aOther.mBlobSerial)
, mControlledDocument(aOther.mControlledDocument)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
@@ -78,6 +85,7 @@ ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
: mURI(Move(aOther.mURI))
, mBlobSerial(Move(aOther.mBlobSerial))
, mControlledDocument(aOther.mControlledDocument)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
@@ -85,6 +93,10 @@ ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
bool
ImageCacheKey::operator==(const ImageCacheKey& aOther) const
{
// Don't share the image cache between a controlled document and anything else.
if (mControlledDocument != aOther.mControlledDocument) {
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.
@@ -104,11 +116,13 @@ ImageCacheKey::Spec() const
/* static */ uint32_t
ImageCacheKey::ComputeHash(ImageURL* aURI,
const Maybe<uint64_t>& aBlobSerial)
const Maybe<uint64_t>& aBlobSerial,
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);
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
@@ -117,13 +131,32 @@ ImageCacheKey::ComputeHash(ImageURL* aURI,
// the same.
nsAutoCString ref;
aURI->GetRef(ref);
return HashGeneric(*aBlobSerial, HashString(ref));
return HashGeneric(*aBlobSerial, HashString(ref + ptr));
}
// For non-blob URIs, we hash the URI spec.
nsAutoCString spec;
aURI->GetSpec(spec);
return HashString(spec);
return HashString(spec + ptr);
}
/* static */ void*
ImageCacheKey::GetControlledDocumentToken(nsIDOMDocument* aDocument)
{
// For non-controlled documents, we just return null. For controlled
// documents, we cast the pointer into a void* to avoid dereferencing
// it (since we only use it for comparisons), and return it.
void* pointer = nullptr;
using dom::workers::ServiceWorkerManager;
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
if (doc && swm) {
ErrorResult rv;
if (swm->IsControlled(doc, rv)) {
pointer = doc;
}
}
return pointer;
}
} // namespace image