mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1536411 - StoragePrincipal - part 6 - Cookies, r=Ehsan
Differential Revision: https://phabricator.services.mozilla.com/D24864 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
7524dcd07e
commit
0830861f7e
@ -1030,7 +1030,14 @@ void nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsContentUtils::StorageDisabledByAntiTracking(this, nullptr)) {
|
||||
nsContentUtils::StorageAccess storageAccess =
|
||||
nsContentUtils::StorageAllowedForDocument(this);
|
||||
if (storageAccess == nsContentUtils::StorageAccess::eDeny) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (storageAccess == nsContentUtils::StorageAccess::ePartitionedOrDeny &&
|
||||
!StaticPrefs::privacy_storagePrincipal_enabledForTrackers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1083,7 +1090,14 @@ void nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsContentUtils::StorageDisabledByAntiTracking(this, nullptr)) {
|
||||
nsContentUtils::StorageAccess storageAccess =
|
||||
nsContentUtils::StorageAllowedForDocument(this);
|
||||
if (storageAccess == nsContentUtils::StorageAccess::eDeny) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (storageAccess == nsContentUtils::StorageAccess::ePartitionedOrDeny &&
|
||||
!StaticPrefs::privacy_storagePrincipal_enabledForTrackers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/StoragePrincipalHelper.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsCategoryCache.h"
|
||||
@ -1851,13 +1852,14 @@ nsresult NS_LoadPersistentPropertiesFromURISpec(
|
||||
|
||||
bool NS_UsePrivateBrowsing(nsIChannel *channel) {
|
||||
OriginAttributes attrs;
|
||||
bool result = NS_GetOriginAttributes(channel, attrs);
|
||||
bool result = NS_GetOriginAttributes(channel, attrs, false);
|
||||
NS_ENSURE_TRUE(result, result);
|
||||
return attrs.mPrivateBrowsingId > 0;
|
||||
}
|
||||
|
||||
bool NS_GetOriginAttributes(nsIChannel *aChannel,
|
||||
mozilla::OriginAttributes &aAttributes) {
|
||||
mozilla::OriginAttributes &aAttributes,
|
||||
bool aUsingStoragePrincipal) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
loadInfo->GetOriginAttributes(&aAttributes);
|
||||
|
||||
@ -1873,6 +1875,10 @@ bool NS_GetOriginAttributes(nsIChannel *aChannel,
|
||||
isPrivate = loadContext && loadContext->UsePrivateBrowsing();
|
||||
}
|
||||
aAttributes.SyncAttributesWithPrivateBrowsing(isPrivate);
|
||||
|
||||
if (aUsingStoragePrincipal) {
|
||||
StoragePrincipalHelper::PrepareOriginAttributes(aChannel, aAttributes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -610,9 +610,12 @@ bool NS_UsePrivateBrowsing(nsIChannel *channel);
|
||||
|
||||
/**
|
||||
* Extract the OriginAttributes from the channel's triggering principal.
|
||||
* If aUsingStoragePrincipal is set to true, the originAttributes could have
|
||||
* first-party isolation domain set to the top-level URI.
|
||||
*/
|
||||
bool NS_GetOriginAttributes(nsIChannel *aChannel,
|
||||
mozilla::OriginAttributes &aAttributes);
|
||||
mozilla::OriginAttributes &aAttributes,
|
||||
bool aUsingStoragePrincipal = false);
|
||||
|
||||
/**
|
||||
* Returns true if the channel has visited any cross-origin URLs on any
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "mozilla/StoragePrincipalHelper.h"
|
||||
#include "nsCookie.h"
|
||||
#include "nsCookieService.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -175,6 +176,7 @@ void CookieServiceChild::TrackCookieLoad(nsIChannel *aChannel) {
|
||||
}
|
||||
}
|
||||
mozilla::OriginAttributes attrs = loadInfo->GetOriginAttributes();
|
||||
StoragePrincipalHelper::PrepareOriginAttributes(aChannel, attrs);
|
||||
URIParams uriParams;
|
||||
SerializeURI(uri, uriParams);
|
||||
bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
|
||||
@ -294,6 +296,7 @@ void CookieServiceChild::GetCookieStringFromCookieHashTable(
|
||||
if (aChannel) {
|
||||
loadInfo = aChannel->LoadInfo();
|
||||
attrs = loadInfo->GetOriginAttributes();
|
||||
StoragePrincipalHelper::PrepareOriginAttributes(aChannel, attrs);
|
||||
}
|
||||
|
||||
nsCookieService::GetBaseDomain(TLDService, aHostURI, baseDomain,
|
||||
@ -562,6 +565,7 @@ nsresult CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI,
|
||||
|
||||
MOZ_ASSERT(loadInfo);
|
||||
attrs = loadInfo->GetOriginAttributes();
|
||||
StoragePrincipalHelper::PrepareOriginAttributes(aChannel, attrs);
|
||||
} else {
|
||||
SerializeURI(nullptr, channelURIParams);
|
||||
}
|
||||
@ -573,7 +577,7 @@ nsresult CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI,
|
||||
if (mIPCOpen) {
|
||||
SendSetCookieString(hostURIParams, channelURIParams, optionalLoadInfoArgs,
|
||||
isForeign, isTrackingResource,
|
||||
firstPartyStorageAccessGranted, cookieString,
|
||||
firstPartyStorageAccessGranted, attrs, cookieString,
|
||||
stringServerTime, aFromHttp);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/StoragePrincipalHelper.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsCookieService.h"
|
||||
#include "nsIChannel.h"
|
||||
@ -126,6 +127,8 @@ void CookieServiceParent::TrackCookieLoad(nsIChannel *aChannel) {
|
||||
bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
|
||||
bool aIsSameSiteForeign = NS_IsSameSiteForeign(aChannel, uri);
|
||||
|
||||
StoragePrincipalHelper::PrepareOriginAttributes(aChannel, attrs);
|
||||
|
||||
// Send matching cookies to Child.
|
||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil;
|
||||
thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
||||
@ -207,8 +210,9 @@ mozilla::ipc::IPCResult CookieServiceParent::RecvSetCookieString(
|
||||
const URIParams &aHost, const Maybe<URIParams> &aChannelURI,
|
||||
const Maybe<LoadInfoArgs> &aLoadInfoArgs, const bool &aIsForeign,
|
||||
const bool &aIsTrackingResource,
|
||||
const bool &aFirstPartyStorageAccessGranted, const nsCString &aCookieString,
|
||||
const nsCString &aServerTime, const bool &aFromHttp) {
|
||||
const bool &aFirstPartyStorageAccessGranted, const OriginAttributes &aAttrs,
|
||||
const nsCString &aCookieString, const nsCString &aServerTime,
|
||||
const bool &aFromHttp) {
|
||||
if (!mCookieService) return IPC_OK();
|
||||
|
||||
// Deserialize URI. Having a host URI is mandatory and should always be
|
||||
@ -240,17 +244,12 @@ mozilla::ipc::IPCResult CookieServiceParent::RecvSetCookieString(
|
||||
// NB: dummyChannel could be null if something failed in CreateDummyChannel.
|
||||
nsDependentCString cookieString(aCookieString, 0);
|
||||
|
||||
OriginAttributes attrs;
|
||||
if (loadInfo) {
|
||||
attrs = loadInfo->GetOriginAttributes();
|
||||
}
|
||||
|
||||
// We set this to true while processing this cookie update, to make sure
|
||||
// we don't send it back to the same content process.
|
||||
mProcessingCookie = true;
|
||||
mCookieService->SetCookieStringInternal(
|
||||
hostURI, aIsForeign, aIsTrackingResource, aFirstPartyStorageAccessGranted,
|
||||
cookieString, aServerTime, aFromHttp, attrs, dummyChannel);
|
||||
cookieString, aServerTime, aFromHttp, aAttrs, dummyChannel);
|
||||
mProcessingCookie = false;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -49,8 +49,8 @@ class CookieServiceParent : public PCookieServiceParent {
|
||||
const Maybe<LoadInfoArgs> &aLoadInfoArgs, const bool &aIsForeign,
|
||||
const bool &aIsTrackingResource,
|
||||
const bool &aFirstPartyStorageAccessGranted,
|
||||
const nsCString &aCookieString, const nsCString &aServerTime,
|
||||
const bool &aFromHttp);
|
||||
const OriginAttributes &aAttrs, const nsCString &aCookieString,
|
||||
const nsCString &aServerTime, const bool &aFromHttp);
|
||||
|
||||
mozilla::ipc::IPCResult RecvPrepareCookieList(
|
||||
const URIParams &aHost, const bool &aIsForeign,
|
||||
|
@ -75,6 +75,7 @@ parent:
|
||||
bool isForeign,
|
||||
bool isTrackingResource,
|
||||
bool firstPartyStorageAccessGranted,
|
||||
OriginAttributes aStoragePrincipalAttrs,
|
||||
nsCString cookieString,
|
||||
nsCString serverTime,
|
||||
bool aFromHttp);
|
||||
|
@ -1990,7 +1990,8 @@ nsresult nsCookieService::GetCookieStringCommon(nsIURI *aHostURI,
|
||||
|
||||
OriginAttributes attrs;
|
||||
if (aChannel) {
|
||||
NS_GetOriginAttributes(aChannel, attrs);
|
||||
NS_GetOriginAttributes(aChannel, attrs,
|
||||
true /* considering storage principal */);
|
||||
}
|
||||
|
||||
bool isSafeTopLevelNav = NS_IsSafeTopLevelNav(aChannel);
|
||||
@ -2109,7 +2110,8 @@ nsresult nsCookieService::SetCookieStringCommon(nsIURI *aHostURI,
|
||||
|
||||
OriginAttributes attrs;
|
||||
if (aChannel) {
|
||||
NS_GetOriginAttributes(aChannel, attrs);
|
||||
NS_GetOriginAttributes(aChannel, attrs,
|
||||
true /* considering storage principal */);
|
||||
}
|
||||
|
||||
nsDependentCString cookieString(aCookieHeader);
|
||||
@ -4040,6 +4042,12 @@ CookieStatus nsCookieService::CheckPrefs(
|
||||
if (aIsForeign && aIsTrackingResource && !aFirstPartyStorageAccessGranted &&
|
||||
aCookieSettings->GetCookieBehavior() ==
|
||||
nsICookieService::BEHAVIOR_REJECT_TRACKER) {
|
||||
if (StaticPrefs::privacy_storagePrincipal_enabledForTrackers()) {
|
||||
MOZ_ASSERT(!aOriginAttrs.mFirstPartyDomain.IsEmpty(),
|
||||
"We must have a StoragePrincipal here!");
|
||||
return STATUS_ACCEPTED;
|
||||
}
|
||||
|
||||
COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI,
|
||||
aCookieHeader, "cookies are disabled in trackers");
|
||||
*aRejectedReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER;
|
||||
|
@ -13,6 +13,47 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace {
|
||||
|
||||
already_AddRefed<nsIURI> MaybeGetFirstPartyURI(nsIChannel* aChannel) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
if (!StaticPrefs::privacy_storagePrincipal_enabledForTrackers()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Let's use the storage principal only if we need to partition the cookie
|
||||
// jar.
|
||||
nsContentUtils::StorageAccess access =
|
||||
nsContentUtils::StorageAllowedForChannel(aChannel);
|
||||
if (access != nsContentUtils::StorageAccess::ePartitionedOrDeny) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(httpChannel->IsThirdPartyTrackingResource());
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
nsCOMPtr<nsIPrincipal> toplevelPrincipal = loadInfo->GetTopLevelPrincipal();
|
||||
if (!toplevelPrincipal) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
nsresult rv = toplevelPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return principalURI.forget();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
nsresult StoragePrincipalHelper::Create(nsIChannel* aChannel,
|
||||
nsIPrincipal* aPrincipal,
|
||||
@ -26,37 +67,11 @@ nsresult StoragePrincipalHelper::Create(nsIChannel* aChannel,
|
||||
storagePrincipal.forget(aStoragePrincipal);
|
||||
});
|
||||
|
||||
if (!StaticPrefs::privacy_storagePrincipal_enabledForTrackers()) {
|
||||
nsCOMPtr<nsIURI> principalURI = MaybeGetFirstPartyURI(aChannel);
|
||||
if (!principalURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Let's use the storage principal only if we need to partition the cookie
|
||||
// jar.
|
||||
nsContentUtils::StorageAccess access =
|
||||
nsContentUtils::StorageAllowedForChannel(aChannel);
|
||||
if (access != nsContentUtils::StorageAccess::ePartitionedOrDeny) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(httpChannel->IsThirdPartyTrackingResource());
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
nsCOMPtr<nsIPrincipal> toplevelPrincipal = loadInfo->GetTopLevelPrincipal();
|
||||
if (!toplevelPrincipal) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
nsresult rv = toplevelPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
scopeExit.release();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> storagePrincipal =
|
||||
@ -67,4 +82,19 @@ nsresult StoragePrincipalHelper::Create(nsIChannel* aChannel,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult StoragePrincipalHelper::PrepareOriginAttributes(
|
||||
nsIChannel* aChannel, OriginAttributes& aOriginAttributes) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
nsCOMPtr<nsIURI> principalURI = MaybeGetFirstPartyURI(aChannel);
|
||||
if (!principalURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aOriginAttributes.SetFirstPartyDomain(false, principalURI,
|
||||
true /* aForced */);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -12,10 +12,15 @@ class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class OriginAttributes;
|
||||
|
||||
class StoragePrincipalHelper final {
|
||||
public:
|
||||
static nsresult Create(nsIChannel* aChannel, nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal** aStoragePrincipal);
|
||||
|
||||
static nsresult PrepareOriginAttributes(nsIChannel* aChannel,
|
||||
OriginAttributes& aOriginAttributes);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -93,3 +93,5 @@ support-files = workerIframe.html
|
||||
[browser_cookieBetweenTabs.js]
|
||||
[browser_partitionedMessaging.js]
|
||||
[browser_partitionedIndexedDB.js]
|
||||
[browser_partitionedCookies.js]
|
||||
support-files = cookies.sjs
|
||||
|
@ -0,0 +1,49 @@
|
||||
/* import-globals-from storageprincipal_head.js */
|
||||
|
||||
StoragePrincipalHelper.runTest("HTTP Cookies",
|
||||
async (win3rdParty, win1stParty, allowed) => {
|
||||
await win3rdParty.fetch("cookies.sjs?3rd").then(r => r.text());
|
||||
await win3rdParty.fetch("cookies.sjs").then(r => r.text()).then(text => {
|
||||
is(text, "cookie:foopy=3rd", "3rd party cookie set");
|
||||
});
|
||||
|
||||
await win1stParty.fetch("cookies.sjs?first").then(r => r.text());
|
||||
await win1stParty.fetch("cookies.sjs").then(r => r.text()).then(text => {
|
||||
is(text, "cookie:foopy=first", "First party cookie set");
|
||||
});
|
||||
|
||||
await win3rdParty.fetch("cookies.sjs").then(r => r.text()).then(text => {
|
||||
if (allowed) {
|
||||
is(text, "cookie:foopy=first", "3rd party has the first party cookie set");
|
||||
} else {
|
||||
is(text, "cookie:foopy=3rd", "3rd party has not the first party cookie set");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async _ => {
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
|
||||
});
|
||||
});
|
||||
|
||||
StoragePrincipalHelper.runTest("DOM Cookies",
|
||||
async (win3rdParty, win1stParty, allowed) => {
|
||||
win3rdParty.document.cookie = "foo=3rd";
|
||||
is(win3rdParty.document.cookie, "foo=3rd", "3rd party cookie set");
|
||||
|
||||
win1stParty.document.cookie = "foo=first";
|
||||
is(win1stParty.document.cookie, "foo=first", "First party cookie set");
|
||||
|
||||
if (allowed) {
|
||||
is(win3rdParty.document.cookie, "foo=first", "3rd party has the first party cookie set");
|
||||
} else {
|
||||
is(win3rdParty.document.cookie, "foo=3rd", "3rd party has not the first party cookie set");
|
||||
}
|
||||
},
|
||||
|
||||
async _ => {
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
|
||||
});
|
||||
});
|
12
toolkit/components/antitracking/test/browser/cookies.sjs
Normal file
12
toolkit/components/antitracking/test/browser/cookies.sjs
Normal file
@ -0,0 +1,12 @@
|
||||
function handleRequest(aRequest, aResponse) {
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 200);
|
||||
let cookie = "";
|
||||
if (aRequest.hasHeader("Cookie")) {
|
||||
cookie = aRequest.getHeader("Cookie");
|
||||
}
|
||||
aResponse.write("cookie:" + cookie);
|
||||
|
||||
if (aRequest.queryString) {
|
||||
aResponse.setHeader("Set-Cookie", "foopy=" + aRequest.queryString);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user