forked from mirrors/gecko-dev
Bug 1469993 - Grant storage access to a 3rd party, tracking resource if a opened document has user-interaction - part 1 - storing first user interaction in a document with an opener window, r=ehsan
This commit is contained in:
parent
d3ebf40764
commit
4322df2e13
7 changed files with 167 additions and 45 deletions
|
|
@ -515,41 +515,6 @@ EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||||
lm->~EventListenerManagerMapEntry();
|
lm->~EventListenerManagerMapEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
|
|
||||||
nsIChannel* aChannel,
|
|
||||||
nsIURI* aURI)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aWindow || !aChannel,
|
|
||||||
"A window and channel should not both be provided.");
|
|
||||||
|
|
||||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
|
|
||||||
if (!thirdPartyUtil) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the absence of a window or channel, we assume that we are first-party.
|
|
||||||
bool thirdParty = false;
|
|
||||||
|
|
||||||
if (aWindow) {
|
|
||||||
Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
|
|
||||||
aURI,
|
|
||||||
&thirdParty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aChannel) {
|
|
||||||
// Note, we must call IsThirdPartyChannel() here and not just try to
|
|
||||||
// use nsILoadInfo.isThirdPartyContext. That nsILoadInfo property only
|
|
||||||
// indicates if the parent loading window is third party or not. We
|
|
||||||
// want to check the channel URI against the loading principal as well.
|
|
||||||
Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
|
|
||||||
nullptr,
|
|
||||||
&thirdParty);
|
|
||||||
}
|
|
||||||
|
|
||||||
return thirdParty;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SameOriginCheckerImpl final : public nsIChannelEventSink,
|
class SameOriginCheckerImpl final : public nsIChannelEventSink,
|
||||||
public nsIInterfaceRequestor
|
public nsIInterfaceRequestor
|
||||||
{
|
{
|
||||||
|
|
@ -8837,6 +8802,42 @@ nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static public
|
||||||
|
bool
|
||||||
|
nsContentUtils::IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
|
||||||
|
nsIChannel* aChannel,
|
||||||
|
nsIURI* aURI)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!aWindow || !aChannel,
|
||||||
|
"A window and channel should not both be provided.");
|
||||||
|
|
||||||
|
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
|
||||||
|
if (!thirdPartyUtil) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the absence of a window or channel, we assume that we are first-party.
|
||||||
|
bool thirdParty = false;
|
||||||
|
|
||||||
|
if (aWindow) {
|
||||||
|
Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
|
||||||
|
aURI,
|
||||||
|
&thirdParty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aChannel) {
|
||||||
|
// Note, we must call IsThirdPartyChannel() here and not just try to
|
||||||
|
// use nsILoadInfo.isThirdPartyContext. That nsILoadInfo property only
|
||||||
|
// indicates if the parent loading window is third party or not. We
|
||||||
|
// want to check the channel URI against the loading principal as well.
|
||||||
|
Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
|
||||||
|
nullptr,
|
||||||
|
&thirdParty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return thirdParty;
|
||||||
|
}
|
||||||
|
|
||||||
// static public
|
// static public
|
||||||
bool
|
bool
|
||||||
nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
|
nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
|
||||||
|
|
@ -8852,19 +8853,42 @@ nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> channel;
|
|
||||||
|
|
||||||
// aChannel and aWindow are mutually exclusive.
|
|
||||||
channel = aChannel;
|
|
||||||
if (aWindow) {
|
if (aWindow) {
|
||||||
|
nsCOMPtr<nsIHttpChannel> httpChannel;
|
||||||
nsIDocument* document = aWindow->GetExtantDoc();
|
nsIDocument* document = aWindow->GetExtantDoc();
|
||||||
if (document) {
|
if (document) {
|
||||||
channel = document->GetChannel();
|
httpChannel = do_QueryInterface(document->GetChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is not a tracking resource, nothing is disabled.
|
||||||
|
if (!httpChannel || !httpChannel->GetIsTrackingResource()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maybe we want to grant this origin.
|
||||||
|
nsIURI* documentURI = aURI ? aURI : aWindow->GetDocumentURI();
|
||||||
|
if (documentURI &&
|
||||||
|
nsGlobalWindowInner::Cast(aWindow)->IsFirstPartyStorageAccessGrantedFor(documentURI)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
// aChannel and aWindow are mutually exclusive.
|
||||||
return httpChannel && httpChannel->GetIsTrackingResource();
|
MOZ_ASSERT(aChannel);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||||
|
if (!httpChannel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!httpChannel->GetIsTrackingResource()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO storage access check
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static, private
|
// static, private
|
||||||
|
|
|
||||||
|
|
@ -2957,6 +2957,13 @@ public:
|
||||||
nsIChannel* aChannel,
|
nsIChannel* aChannel,
|
||||||
nsIURI* aURI);
|
nsIURI* aURI);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if this window/channel is a 3rd party context.
|
||||||
|
*/
|
||||||
|
static bool IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
|
||||||
|
nsIChannel* aChannel,
|
||||||
|
nsIURI* aURI);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Serializes a HTML nsINode into its markup representation.
|
* Serializes a HTML nsINode into its markup representation.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/StaticPrefs.h"
|
||||||
#include "mozilla/URLExtraData.h"
|
#include "mozilla/URLExtraData.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
@ -12415,10 +12416,62 @@ nsIDocument::NotifyUserGestureActivation()
|
||||||
LogLevel::Debug,
|
LogLevel::Debug,
|
||||||
("Document %p has been activated by user.", this));
|
("Document %p has been activated by user.", this));
|
||||||
doc->mUserGestureActivated = true;
|
doc->mUserGestureActivated = true;
|
||||||
|
doc->MaybeAllowStorageForOpener();
|
||||||
doc = doc->GetSameTypeParentDocument();
|
doc = doc->GetSameTypeParentDocument();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsIDocument::MaybeAllowStorageForOpener()
|
||||||
|
{
|
||||||
|
if (!StaticPrefs::privacy_restrict3rdpartystorage_enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will probably change for project fission, but currently this document
|
||||||
|
// and the opener are on the same process. In the future, we should make this
|
||||||
|
// part async.
|
||||||
|
|
||||||
|
nsPIDOMWindowInner* inner = GetInnerWindow();
|
||||||
|
if (NS_WARN_IF(!inner)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindowOuter> outer = inner->GetOuterWindow();
|
||||||
|
if (NS_WARN_IF(!outer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsPIDOMWindowOuter> outerOpener = outer->GetOpener();
|
||||||
|
if (NS_WARN_IF(!outerOpener)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsPIDOMWindowInner* openerInner = outerOpener->GetCurrentInnerWindow();
|
||||||
|
if (NS_WARN_IF(!openerInner)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No 3rd party.
|
||||||
|
if (!nsContentUtils::IsThirdPartyWindowOrChannel(openerInner, nullptr,
|
||||||
|
nullptr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> uri = GetDocumentURI();
|
||||||
|
if (NS_WARN_IF(!uri)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString origin;
|
||||||
|
nsresult rv = nsContentUtils::GetUTFOrigin(uri, origin);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsGlobalWindowInner::Cast(openerInner)->AddFirstPartyStorageAccessGrantedFor(origin);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsIDocument::HasBeenUserGestureActivated()
|
nsIDocument::HasBeenUserGestureActivated()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#if defined(MOZ_WIDGET_ANDROID)
|
#if defined(MOZ_WIDGET_ANDROID)
|
||||||
#include "mozilla/dom/WindowOrientationObserver.h"
|
#include "mozilla/dom/WindowOrientationObserver.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "mozilla/StaticPrefs.h"
|
||||||
#include "nsDOMOfflineResourceList.h"
|
#include "nsDOMOfflineResourceList.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "nsIIdleService.h"
|
#include "nsIIdleService.h"
|
||||||
|
|
@ -8034,6 +8035,34 @@ nsGlobalWindowInner::GetRegionalPrefsLocales(nsTArray<nsString>& aLocales)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindowInner::AddFirstPartyStorageAccessGrantedFor(const nsAString& aOrigin)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(StaticPrefs::privacy_restrict3rdpartystorage_enabled());
|
||||||
|
|
||||||
|
if (mStorageGrantedOrigins.Contains(aOrigin)) {
|
||||||
|
mStorageGrantedOrigins.AppendElement(aOrigin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsGlobalWindowInner::IsFirstPartyStorageAccessGrantedFor(nsIURI* aURI) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aURI);
|
||||||
|
|
||||||
|
if (mStorageGrantedOrigins.IsEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString origin;
|
||||||
|
nsresult rv = nsContentUtils::GetUTFOrigin(aURI, origin);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mStorageGrantedOrigins.Contains(origin);
|
||||||
|
}
|
||||||
|
|
||||||
IntlUtils*
|
IntlUtils*
|
||||||
nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError)
|
nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -717,6 +717,12 @@ public:
|
||||||
mozilla::dom::IntlUtils*
|
mozilla::dom::IntlUtils*
|
||||||
GetIntlUtils(mozilla::ErrorResult& aRv);
|
GetIntlUtils(mozilla::ErrorResult& aRv);
|
||||||
|
|
||||||
|
void
|
||||||
|
AddFirstPartyStorageAccessGrantedFor(const nsAString& aOrigin);
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsFirstPartyStorageAccessGrantedFor(nsIURI* aURI) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Alert(nsIPrincipal& aSubjectPrincipal,
|
void Alert(nsIPrincipal& aSubjectPrincipal,
|
||||||
mozilla::ErrorResult& aError);
|
mozilla::ErrorResult& aError);
|
||||||
|
|
@ -1476,6 +1482,8 @@ protected:
|
||||||
|
|
||||||
nsTArray<mozilla::UniquePtr<PromiseDocumentFlushedResolver>> mDocumentFlushedResolvers;
|
nsTArray<mozilla::UniquePtr<PromiseDocumentFlushedResolver>> mDocumentFlushedResolvers;
|
||||||
|
|
||||||
|
nsTArray<nsString> mStorageGrantedOrigins;
|
||||||
|
|
||||||
static InnerWindowByIdTable* sInnerWindowsById;
|
static InnerWindowByIdTable* sInnerWindowsById;
|
||||||
|
|
||||||
// Members in the mChromeFields member should only be used in chrome windows.
|
// Members in the mChromeFields member should only be used in chrome windows.
|
||||||
|
|
|
||||||
|
|
@ -3682,6 +3682,8 @@ protected:
|
||||||
// Return the same type parent docuement if exists, or return null.
|
// Return the same type parent docuement if exists, or return null.
|
||||||
nsIDocument* GetSameTypeParentDocument();
|
nsIDocument* GetSameTypeParentDocument();
|
||||||
|
|
||||||
|
void MaybeAllowStorageForOpener();
|
||||||
|
|
||||||
// Helpers for GetElementsByName.
|
// Helpers for GetElementsByName.
|
||||||
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
|
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
|
||||||
int32_t aNamespaceID,
|
int32_t aNamespaceID,
|
||||||
|
|
|
||||||
|
|
@ -142,9 +142,8 @@ ImageCacheKey::GetSpecialCaseDocumentToken(nsIDocument* aDocument, nsIURI* aURI)
|
||||||
// If this document has been marked as tracker, let's use its address to make
|
// If this document has been marked as tracker, let's use its address to make
|
||||||
// a unique cache key.
|
// a unique cache key.
|
||||||
if (!pointer && aDocument &&
|
if (!pointer && aDocument &&
|
||||||
nsContentUtils::StorageDisabledByAntiTracking(nullptr,
|
nsContentUtils::StorageDisabledByAntiTracking(aDocument->GetInnerWindow(),
|
||||||
aDocument->GetChannel(),
|
nullptr, aURI)) {
|
||||||
aURI)) {
|
|
||||||
pointer = aDocument;
|
pointer = aDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue