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:
Andrea Marchesini 2018-07-10 10:09:58 +02:00
Родитель 6eb9f8c25b
Коммит e6921e1adc
7 изменённых файлов: 167 добавлений и 45 удалений

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

@ -515,41 +515,6 @@ EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
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,
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
bool
nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
@ -8852,19 +8853,42 @@ nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
return false;
}
nsCOMPtr<nsIChannel> channel;
// aChannel and aWindow are mutually exclusive.
channel = aChannel;
if (aWindow) {
nsCOMPtr<nsIHttpChannel> httpChannel;
nsIDocument* document = aWindow->GetExtantDoc();
if (document) {
channel = document->GetChannel();
}
httpChannel = do_QueryInterface(document->GetChannel());
}
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
return httpChannel && httpChannel->GetIsTrackingResource();
// 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;
}
// aChannel and aWindow are mutually exclusive.
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

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

@ -2957,6 +2957,13 @@ public:
nsIChannel* aChannel,
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.
*/

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

@ -23,6 +23,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Likely.h"
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/URLExtraData.h"
#include <algorithm>
@ -12415,10 +12416,62 @@ nsIDocument::NotifyUserGestureActivation()
LogLevel::Debug,
("Document %p has been activated by user.", this));
doc->mUserGestureActivated = true;
doc->MaybeAllowStorageForOpener();
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
nsIDocument::HasBeenUserGestureActivated()
{

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

@ -36,6 +36,7 @@
#if defined(MOZ_WIDGET_ANDROID)
#include "mozilla/dom/WindowOrientationObserver.h"
#endif
#include "mozilla/StaticPrefs.h"
#include "nsDOMOfflineResourceList.h"
#include "nsError.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*
nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError)
{

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

@ -717,6 +717,12 @@ public:
mozilla::dom::IntlUtils*
GetIntlUtils(mozilla::ErrorResult& aRv);
void
AddFirstPartyStorageAccessGrantedFor(const nsAString& aOrigin);
bool
IsFirstPartyStorageAccessGrantedFor(nsIURI* aURI) const;
public:
void Alert(nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
@ -1476,6 +1482,8 @@ protected:
nsTArray<mozilla::UniquePtr<PromiseDocumentFlushedResolver>> mDocumentFlushedResolvers;
nsTArray<nsString> mStorageGrantedOrigins;
static InnerWindowByIdTable* sInnerWindowsById;
// 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.
nsIDocument* GetSameTypeParentDocument();
void MaybeAllowStorageForOpener();
// Helpers for GetElementsByName.
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
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
// a unique cache key.
if (!pointer && aDocument &&
nsContentUtils::StorageDisabledByAntiTracking(nullptr,
aDocument->GetChannel(),
aURI)) {
nsContentUtils::StorageDisabledByAntiTracking(aDocument->GetInnerWindow(),
nullptr, aURI)) {
pointer = aDocument;
}