Bug 1474651 - Grant storage access to 3rd party, tracking resource on window.open(), r=ehsan

This commit is contained in:
Andrea Marchesini 2018-07-11 12:38:47 +02:00
Родитель 5e3e0d4498
Коммит 648c87fe95
6 изменённых файлов: 67 добавлений и 7 удалений

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

@ -8838,6 +8838,26 @@ nsContentUtils::IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
return thirdParty; return thirdParty;
} }
// static public
bool
nsContentUtils::IsTrackingResourceWindow(nsPIDOMWindowInner* aWindow)
{
MOZ_ASSERT(aWindow);
nsIDocument* document = aWindow->GetExtantDoc();
if (!document) {
return false;
}
nsCOMPtr<nsIHttpChannel> httpChannel =
do_QueryInterface(document->GetChannel());
if (!httpChannel) {
return false;
}
return httpChannel->GetIsTrackingResource();
}
// static public // static public
bool bool
nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow, nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,

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

@ -2964,6 +2964,12 @@ public:
nsIChannel* aChannel, nsIChannel* aChannel,
nsIURI* aURI); nsIURI* aURI);
/*
* Returns true if this window's channel has been marked as a tracking
* resource.
*/
static bool IsTrackingResourceWindow(nsPIDOMWindowInner* aWindow);
/* /*
* Serializes a HTML nsINode into its markup representation. * Serializes a HTML nsINode into its markup representation.
*/ */

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

@ -12450,9 +12450,10 @@ nsIDocument::MaybeAllowStorageForOpener()
return; return;
} }
// No 3rd party. // No 3rd party or no tracking resource.
if (!nsContentUtils::IsThirdPartyWindowOrChannel(openerInner, nullptr, if (!nsContentUtils::IsThirdPartyWindowOrChannel(openerInner, nullptr,
nullptr)) { nullptr) ||
!nsContentUtils::IsTrackingResourceWindow(openerInner)) {
return; return;
} }

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

@ -6898,12 +6898,14 @@ nsGlobalWindowOuter::OpenInternal(const nsAString& aUrl, const nsAString& aName,
} }
} }
bool windowExists = WindowExists(aName, forceNoOpener, !aCalledNoScript);
// XXXbz When this gets fixed to not use LegacyIsCallerNativeCode() // XXXbz When this gets fixed to not use LegacyIsCallerNativeCode()
// (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run. // (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
// But note that if you change this to GetEntryGlobal(), say, then // But note that if you change this to GetEntryGlobal(), say, then
// OnLinkClickEvent::Run will need a full-blown AutoEntryScript. // OnLinkClickEvent::Run will need a full-blown AutoEntryScript.
const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() && const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
!aDialog && !WindowExists(aName, forceNoOpener, !aCalledNoScript); !aDialog && !windowExists;
// Note: the Void handling here is very important, because the window watcher // Note: the Void handling here is very important, because the window watcher
// expects a null URL string (not an empty string) if there is no URL to load. // expects a null URL string (not an empty string) if there is no URL to load.
@ -6911,6 +6913,8 @@ nsGlobalWindowOuter::OpenInternal(const nsAString& aUrl, const nsAString& aName,
url.SetIsVoid(true); url.SetIsVoid(true);
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsCOMPtr<nsIURI> uri;
// It's important to do this security check before determining whether this // It's important to do this security check before determining whether this
// window opening should be blocked, to ensure that we don't FireAbuseEvents // window opening should be blocked, to ensure that we don't FireAbuseEvents
// for a window opening that wouldn't have succeeded in the first place. // for a window opening that wouldn't have succeeded in the first place.
@ -6924,7 +6928,7 @@ nsGlobalWindowOuter::OpenInternal(const nsAString& aUrl, const nsAString& aName,
// If we're not navigating, we assume that whoever *does* navigate the // If we're not navigating, we assume that whoever *does* navigate the
// window will do a security check of their own. // window will do a security check of their own.
if (!url.IsVoid() && !aDialog && aNavigate) if (!url.IsVoid() && !aDialog && aNavigate)
rv = SecurityCheckURL(url.get()); rv = SecurityCheckURL(url.get(), getter_AddRefs(uri));
} }
if (NS_FAILED(rv)) if (NS_FAILED(rv))
@ -7026,6 +7030,10 @@ nsGlobalWindowOuter::OpenInternal(const nsAString& aUrl, const nsAString& aName,
// success! // success!
if (!aCalledNoScript && !windowExists && uri) {
MaybeAllowStorageForOpenedWindow(uri);
}
NS_ENSURE_TRUE(domReturn, NS_OK); NS_ENSURE_TRUE(domReturn, NS_OK);
nsCOMPtr<nsPIDOMWindowOuter> outerReturn = nsCOMPtr<nsPIDOMWindowOuter> outerReturn =
nsPIDOMWindowOuter::From(domReturn); nsPIDOMWindowOuter::From(domReturn);
@ -7050,6 +7058,29 @@ nsGlobalWindowOuter::OpenInternal(const nsAString& aUrl, const nsAString& aName,
return rv; return rv;
} }
void
nsGlobalWindowOuter::MaybeAllowStorageForOpenedWindow(nsIURI* aURI)
{
nsGlobalWindowInner *inner = GetCurrentInnerWindowInternal();
if (NS_WARN_IF(!inner)) {
return;
}
// No 3rd party or no tracking resource.
if (!nsContentUtils::IsThirdPartyWindowOrChannel(inner, nullptr, nullptr) ||
!nsContentUtils::IsTrackingResourceWindow(inner)) {
return;
}
nsAutoString origin;
nsresult rv = nsContentUtils::GetUTFOrigin(aURI, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
inner->AddFirstPartyStorageAccessGrantedFor(origin, true);
}
//***************************************************************************** //*****************************************************************************
// nsGlobalWindowOuter: Helper Functions // nsGlobalWindowOuter: Helper Functions
//***************************************************************************** //*****************************************************************************
@ -7109,7 +7140,7 @@ nsGlobalWindowOuter::GetScrollFrame()
} }
nsresult nsresult
nsGlobalWindowOuter::SecurityCheckURL(const char *aURL) nsGlobalWindowOuter::SecurityCheckURL(const char *aURL, nsIURI** aURI)
{ {
nsCOMPtr<nsPIDOMWindowInner> sourceWindow = do_QueryInterface(GetEntryGlobal()); nsCOMPtr<nsPIDOMWindowInner> sourceWindow = do_QueryInterface(GetEntryGlobal());
if (!sourceWindow) { if (!sourceWindow) {
@ -7142,6 +7173,7 @@ nsGlobalWindowOuter::SecurityCheckURL(const char *aURL)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
uri.forget(aURI);
return NS_OK; return NS_OK;
} }

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

@ -907,7 +907,7 @@ public:
already_AddRefed<nsIDocShellTreeOwner> GetTreeOwner(); already_AddRefed<nsIDocShellTreeOwner> GetTreeOwner();
already_AddRefed<nsIBaseWindow> GetTreeOwnerWindow(); already_AddRefed<nsIBaseWindow> GetTreeOwnerWindow();
already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome(); already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome();
nsresult SecurityCheckURL(const char *aURL); nsresult SecurityCheckURL(const char *aURL, nsIURI** aURI);
bool IsPrivateBrowsing(); bool IsPrivateBrowsing();
bool PopupWhitelisted(); bool PopupWhitelisted();
@ -1054,6 +1054,8 @@ private:
nsresult GetInterfaceInternal(const nsIID& aIID, void** aSink); nsresult GetInterfaceInternal(const nsIID& aIID, void** aSink);
void MaybeAllowStorageForOpenedWindow(nsIURI* aURI);
public: public:
// Dispatch a runnable related to the global. // Dispatch a runnable related to the global.
virtual nsresult Dispatch(mozilla::TaskCategory aCategory, virtual nsresult Dispatch(mozilla::TaskCategory aCategory,

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

@ -6,7 +6,6 @@
<h1>hi!</h1> <h1>hi!</h1>
<script> <script>
SpecialPowers.wrap(document).userInteractionForTesting();
opener.postMessage("hello!", "*"); opener.postMessage("hello!", "*");
window.close(); window.close();