зеркало из 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 "nsLayoutUtils.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "mozilla/AntiTrackingCommon.h"
|
#include "mozilla/AntiTrackingCommon.h"
|
||||||
|
#include "mozilla/HashFunctions.h"
|
||||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||||
#include "mozilla/dom/File.h"
|
#include "mozilla/dom/File.h"
|
||||||
#include "mozilla/dom/ServiceWorkerManager.h"
|
#include "mozilla/dom/ServiceWorkerManager.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -43,6 +45,7 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI, const OriginAttributes& aAttrs,
|
||||||
: mURI(aURI),
|
: mURI(aURI),
|
||||||
mOriginAttributes(aAttrs),
|
mOriginAttributes(aAttrs),
|
||||||
mControlledDocument(GetSpecialCaseDocumentToken(aDocument, aURI)),
|
mControlledDocument(GetSpecialCaseDocumentToken(aDocument, aURI)),
|
||||||
|
mTopLevelBaseDomain(GetTopLevelBaseDomain(aDocument, aURI)),
|
||||||
mIsChrome(false) {
|
mIsChrome(false) {
|
||||||
if (SchemeIs("blob")) {
|
if (SchemeIs("blob")) {
|
||||||
mBlobSerial = BlobSerial(mURI);
|
mBlobSerial = BlobSerial(mURI);
|
||||||
|
@ -57,6 +60,7 @@ ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
|
||||||
mBlobRef(aOther.mBlobRef),
|
mBlobRef(aOther.mBlobRef),
|
||||||
mOriginAttributes(aOther.mOriginAttributes),
|
mOriginAttributes(aOther.mOriginAttributes),
|
||||||
mControlledDocument(aOther.mControlledDocument),
|
mControlledDocument(aOther.mControlledDocument),
|
||||||
|
mTopLevelBaseDomain(aOther.mTopLevelBaseDomain),
|
||||||
mHash(aOther.mHash),
|
mHash(aOther.mHash),
|
||||||
mIsChrome(aOther.mIsChrome) {}
|
mIsChrome(aOther.mIsChrome) {}
|
||||||
|
|
||||||
|
@ -66,6 +70,7 @@ ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
|
||||||
mBlobRef(std::move(aOther.mBlobRef)),
|
mBlobRef(std::move(aOther.mBlobRef)),
|
||||||
mOriginAttributes(aOther.mOriginAttributes),
|
mOriginAttributes(aOther.mOriginAttributes),
|
||||||
mControlledDocument(aOther.mControlledDocument),
|
mControlledDocument(aOther.mControlledDocument),
|
||||||
|
mTopLevelBaseDomain(aOther.mTopLevelBaseDomain),
|
||||||
mHash(aOther.mHash),
|
mHash(aOther.mHash),
|
||||||
mIsChrome(aOther.mIsChrome) {}
|
mIsChrome(aOther.mIsChrome) {}
|
||||||
|
|
||||||
|
@ -75,6 +80,12 @@ bool ImageCacheKey::operator==(const ImageCacheKey& aOther) const {
|
||||||
if (mControlledDocument != aOther.mControlledDocument) {
|
if (mControlledDocument != aOther.mControlledDocument) {
|
||||||
return false;
|
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.
|
// The origin attributes always have to match.
|
||||||
if (mOriginAttributes != aOther.mOriginAttributes) {
|
if (mOriginAttributes != aOther.mOriginAttributes) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -127,7 +138,8 @@ void ImageCacheKey::EnsureHash() const {
|
||||||
hash = HashString(spec);
|
hash = HashString(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = AddToHash(hash, HashString(suffix), HashString(ptr));
|
hash = AddToHash(hash, HashString(suffix), HashString(mTopLevelBaseDomain),
|
||||||
|
HashString(ptr));
|
||||||
mHash.emplace(hash);
|
mHash.emplace(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,27 +165,44 @@ void* ImageCacheKey::GetSpecialCaseDocumentToken(Document* aDocument,
|
||||||
return 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
|
// If the window is 3rd party resource, let's see if first-party storage
|
||||||
// access is granted for this image.
|
// access is granted for this image.
|
||||||
if (nsContentUtils::IsThirdPartyTrackingResourceWindow(
|
if (nsContentUtils::IsThirdPartyTrackingResourceWindow(
|
||||||
aDocument->GetInnerWindow())) {
|
aDocument->GetInnerWindow())) {
|
||||||
return nsContentUtils::StorageDisabledByAntiTracking(aDocument, aURI)
|
return nsContentUtils::StorageDisabledByAntiTracking(aDocument, aURI)
|
||||||
? aDocument
|
? aDocument->GetBaseDomain()
|
||||||
: nullptr;
|
: EmptyCString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Another scenario is if this image is a 3rd party resource loaded by a
|
// 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
|
// 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
|
// 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
|
// 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
|
// that the permission is granted, let's return 0. Otherwise, let's make a
|
||||||
// make a unique image cache.
|
// unique image cache per the top-level document eTLD+1.
|
||||||
if (!AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(
|
if (!AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(
|
||||||
aDocument->GetInnerWindow(), aURI)) {
|
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
|
} // namespace image
|
||||||
|
|
|
@ -61,11 +61,16 @@ class ImageCacheKey final {
|
||||||
private:
|
private:
|
||||||
bool SchemeIs(const char* aScheme);
|
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.
|
// token for the key. All those exceptions are handled by this method.
|
||||||
static void* GetSpecialCaseDocumentToken(dom::Document* aDocument,
|
static void* GetSpecialCaseDocumentToken(dom::Document* aDocument,
|
||||||
nsIURI* aURI);
|
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 EnsureHash() const;
|
||||||
void EnsureBlobRef() const;
|
void EnsureBlobRef() const;
|
||||||
|
|
||||||
|
@ -74,6 +79,7 @@ class ImageCacheKey final {
|
||||||
mutable nsCString mBlobRef;
|
mutable nsCString mBlobRef;
|
||||||
OriginAttributes mOriginAttributes;
|
OriginAttributes mOriginAttributes;
|
||||||
void* mControlledDocument;
|
void* mControlledDocument;
|
||||||
|
nsCString mTopLevelBaseDomain;
|
||||||
mutable Maybe<PLDHashNumber> mHash;
|
mutable Maybe<PLDHashNumber> mHash;
|
||||||
bool mIsChrome;
|
bool mIsChrome;
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче