зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1548349 - Make sure the image cache for third-party tracking subresources is keyed to the top-level document's eTLD+1; r=baku,aosmond
Differential Revision: https://phabricator.services.mozilla.com/D29546 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
50b2b648b6
Коммит
27938631aa
|
@ -13,10 +13,12 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/AntiTrackingCommon.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/ServiceWorkerManager.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -43,6 +45,7 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI, const OriginAttributes& aAttrs,
|
|||
: mURI(aURI),
|
||||
mOriginAttributes(aAttrs),
|
||||
mControlledDocument(GetSpecialCaseDocumentToken(aDocument, aURI)),
|
||||
mTopLevelBaseDomain(GetTopLevelBaseDomain(aDocument, aURI)),
|
||||
mIsChrome(false) {
|
||||
if (SchemeIs("blob")) {
|
||||
mBlobSerial = BlobSerial(mURI);
|
||||
|
@ -57,6 +60,7 @@ ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
|
|||
mBlobRef(aOther.mBlobRef),
|
||||
mOriginAttributes(aOther.mOriginAttributes),
|
||||
mControlledDocument(aOther.mControlledDocument),
|
||||
mTopLevelBaseDomain(aOther.mTopLevelBaseDomain),
|
||||
mHash(aOther.mHash),
|
||||
mIsChrome(aOther.mIsChrome) {}
|
||||
|
||||
|
@ -66,6 +70,7 @@ ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
|
|||
mBlobRef(std::move(aOther.mBlobRef)),
|
||||
mOriginAttributes(aOther.mOriginAttributes),
|
||||
mControlledDocument(aOther.mControlledDocument),
|
||||
mTopLevelBaseDomain(aOther.mTopLevelBaseDomain),
|
||||
mHash(aOther.mHash),
|
||||
mIsChrome(aOther.mIsChrome) {}
|
||||
|
||||
|
@ -75,6 +80,12 @@ bool ImageCacheKey::operator==(const ImageCacheKey& aOther) const {
|
|||
if (mControlledDocument != aOther.mControlledDocument) {
|
||||
return false;
|
||||
}
|
||||
// Don't share the image cache between two top-level documents of different
|
||||
// base domains.
|
||||
if (!mTopLevelBaseDomain.Equals(aOther.mTopLevelBaseDomain,
|
||||
nsCaseInsensitiveCStringComparator())) {
|
||||
return false;
|
||||
}
|
||||
// The origin attributes always have to match.
|
||||
if (mOriginAttributes != aOther.mOriginAttributes) {
|
||||
return false;
|
||||
|
@ -127,7 +138,8 @@ void ImageCacheKey::EnsureHash() const {
|
|||
hash = HashString(spec);
|
||||
}
|
||||
|
||||
hash = AddToHash(hash, HashString(suffix), HashString(ptr));
|
||||
hash = AddToHash(hash, HashString(suffix), HashString(mTopLevelBaseDomain),
|
||||
HashString(ptr));
|
||||
mHash.emplace(hash);
|
||||
}
|
||||
|
||||
|
@ -153,27 +165,44 @@ void* ImageCacheKey::GetSpecialCaseDocumentToken(Document* aDocument,
|
|||
return aDocument;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsCString ImageCacheKey::GetTopLevelBaseDomain(Document* aDocument,
|
||||
nsIURI* aURI) {
|
||||
if (!aDocument || !aDocument->GetInnerWindow()) {
|
||||
return EmptyCString();
|
||||
}
|
||||
|
||||
// If the window is 3rd party resource, let's see if first-party storage
|
||||
// access is granted for this image.
|
||||
if (nsContentUtils::IsThirdPartyTrackingResourceWindow(
|
||||
aDocument->GetInnerWindow())) {
|
||||
return nsContentUtils::StorageDisabledByAntiTracking(aDocument, aURI)
|
||||
? aDocument
|
||||
: nullptr;
|
||||
? aDocument->GetBaseDomain()
|
||||
: EmptyCString();
|
||||
}
|
||||
|
||||
// Another scenario is if this image is a 3rd party resource loaded by a
|
||||
// first party context. In this case, we should check if the nsIChannel has
|
||||
// been marked as tracking resource, but we don't have the channel yet at
|
||||
// this point. The best approach here is to be conservative: if we are sure
|
||||
// that the permission is granted, let's return a nullptr. Otherwise, let's
|
||||
// make a unique image cache.
|
||||
// that the permission is granted, let's return 0. Otherwise, let's make a
|
||||
// unique image cache per the top-level document eTLD+1.
|
||||
if (!AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(
|
||||
aDocument->GetInnerWindow(), aURI)) {
|
||||
return aDocument;
|
||||
nsPIDOMWindowOuter* top = aDocument->GetInnerWindow()->GetScriptableTop();
|
||||
nsPIDOMWindowInner* topInner = top->GetCurrentInnerWindow();
|
||||
if (!topInner) {
|
||||
return aDocument
|
||||
->GetBaseDomain(); // because we don't have anything better!
|
||||
}
|
||||
return topInner->GetExtantDoc() ? topInner->GetExtantDoc()->GetBaseDomain()
|
||||
: EmptyCString();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return EmptyCString();
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
|
|
|
@ -61,11 +61,16 @@ class ImageCacheKey final {
|
|||
private:
|
||||
bool SchemeIs(const char* aScheme);
|
||||
|
||||
// For ServiceWorker and for anti-tracking we need to use the document as
|
||||
// For ServiceWorker we need to use the document as
|
||||
// token for the key. All those exceptions are handled by this method.
|
||||
static void* GetSpecialCaseDocumentToken(dom::Document* aDocument,
|
||||
nsIURI* aURI);
|
||||
|
||||
// For anti-tracking we need to use the top-level document's base domain for
|
||||
// the key. This is handled by this method.
|
||||
static nsCString GetTopLevelBaseDomain(dom::Document* aDocument,
|
||||
nsIURI* aURI);
|
||||
|
||||
void EnsureHash() const;
|
||||
void EnsureBlobRef() const;
|
||||
|
||||
|
@ -74,6 +79,7 @@ class ImageCacheKey final {
|
|||
mutable nsCString mBlobRef;
|
||||
OriginAttributes mOriginAttributes;
|
||||
void* mControlledDocument;
|
||||
nsCString mTopLevelBaseDomain;
|
||||
mutable Maybe<PLDHashNumber> mHash;
|
||||
bool mIsChrome;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче