Bug 1504728 - Part 1: Add a content blocking notification for indicating when a top-level page is using cookies or site data r=baku,valentin,johannh

Differential Revision: https://phabricator.services.mozilla.com/D11122

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ehsan Akhgari 2018-11-14 17:19:25 +00:00
parent a4d4ccb3fc
commit 7f3a7b13de
34 changed files with 371 additions and 82 deletions

View File

@ -119,6 +119,7 @@ function startTest1() {
gAllNotifications = [
"onStateChange",
"onSecurityChange",
"onLocationChange",
"onSecurityChange",
"onStateChange",
@ -131,6 +132,7 @@ function startTest2() {
info("\nTest 2");
gAllNotifications = [
"onStateChange",
"onSecurityChange",
"onLocationChange",
"onSecurityChange",
"onStateChange",
@ -143,6 +145,7 @@ function startTest3() {
info("\nTest 3");
gAllNotifications = [
"onStateChange",
"onSecurityChange",
"onLocationChange",
"onSecurityChange",
"onStateChange",
@ -155,6 +158,7 @@ function startTest4() {
info("\nTest 4");
gAllNotifications = [
"onStateChange",
"onSecurityChange",
"onLocationChange",
"onSecurityChange",
"onStateChange",
@ -175,6 +179,7 @@ function startTest5() {
gAllNotifications = [
"onStateChange",
"onSecurityChange",
"onLocationChange",
"onSecurityChange",
"onStateChange",
@ -187,6 +192,7 @@ function startTest6() {
info("\nTest 6");
gAllNotifications = [
"onStateChange",
"onSecurityChange",
"onLocationChange",
"onSecurityChange",
"onStateChange",

View File

@ -189,19 +189,19 @@ add_task(async function navigate_around() {
},
"security.insecure_connection_icon.pbmode.enabled": {
min: 20,
max: 30,
max: 60,
},
"security.insecure_connection_icon.enabled": {
min: 20,
max: 30,
max: 60,
},
"security.insecure_connection_text.enabled": {
min: 20,
max: 30,
max: 60,
},
"security.insecure_connection_text.pbmode.enabled": {
min: 20,
max: 30,
max: 60,
},
"toolkit.cosmeticAnimations.enabled": {
min: 45,

View File

@ -31,11 +31,11 @@ add_task(async function() {
BrowserTestUtils.loadURI(browser, uri);
await BrowserTestUtils.browserLoaded(browser, false, uri);
is(onLocationChangeCount, 1, "should have 1 onLocationChange event");
is(onSecurityChangeCount, 1, "should have 1 onSecurityChange event");
is(onSecurityChangeCount, 2, "should have 2 onSecurityChange event");
await ContentTask.spawn(browser, null, async () => {
content.history.pushState({}, "", "https://example.com");
});
is(onLocationChangeCount, 2, "should have 2 onLocationChange events");
is(onSecurityChangeCount, 1, "should still have only 1 onSecurityChange event");
is(onSecurityChangeCount, 2, "should still have only 2 onSecurityChange event");
});
});

View File

@ -11,6 +11,8 @@ const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/te
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
const COOKIE_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/cookiePage.html";
requestLongerTimeout(2);
registerCleanupFunction(function() {
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(TP_PREF);
@ -83,7 +85,7 @@ async function testTrackingProtectionAnimation(tabbrowser) {
ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Reload tracking cookies tab");
securityChanged = waitForSecurityChange(tabbrowser, 2);
securityChanged = waitForSecurityChange(tabbrowser, 4);
tabbrowser.reload();
await securityChanged;
@ -92,7 +94,7 @@ async function testTrackingProtectionAnimation(tabbrowser) {
await BrowserTestUtils.waitForEvent(ContentBlocking.animatedIcon, "animationend");
info("Reload tracking tab");
securityChanged = waitForSecurityChange(tabbrowser, 3);
securityChanged = waitForSecurityChange(tabbrowser, 5);
tabbrowser.selectedTab = trackingTab;
tabbrowser.reload();
await securityChanged;
@ -102,7 +104,7 @@ async function testTrackingProtectionAnimation(tabbrowser) {
await BrowserTestUtils.waitForEvent(ContentBlocking.animatedIcon, "animationend");
info("Inject tracking cookie inside tracking tab");
securityChanged = waitForSecurityChange(tabbrowser);
securityChanged = waitForSecurityChange(tabbrowser, 2);
await ContentTask.spawn(tabbrowser.selectedBrowser, {},
function() {
content.postMessage("cookie", "*");
@ -126,7 +128,7 @@ async function testTrackingProtectionAnimation(tabbrowser) {
tabbrowser.selectedTab = trackingCookiesTab;
info("Inject tracking cookie inside tracking cookies tab");
securityChanged = waitForSecurityChange(tabbrowser);
securityChanged = waitForSecurityChange(tabbrowser, 2);
await ContentTask.spawn(tabbrowser.selectedBrowser, {},
function() {
content.postMessage("cookie", "*");
@ -137,7 +139,7 @@ async function testTrackingProtectionAnimation(tabbrowser) {
ok(!ContentBlocking.iconBox.hasAttribute("animate"), "iconBox not animating");
info("Inject tracking element inside tracking cookies tab");
securityChanged = waitForSecurityChange(tabbrowser);
securityChanged = waitForSecurityChange(tabbrowser, 2);
await ContentTask.spawn(tabbrowser.selectedBrowser, {},
function() {
content.postMessage("tracking", "*");

View File

@ -51,7 +51,7 @@ add_task(async function testShieldHistogram() {
getShieldHistogram().clear();
await promiseTabLoadEvent(tab, BENIGN_PAGE);
is(getShieldCounts()[0], 1, "Page loads without tracking");
is(getShieldCounts()[0], 2, "Page loads without tracking");
await promiseTabLoadEvent(tab, TRACKING_PAGE);
// Note that right now the shield histogram is not measuring what

View File

@ -1511,6 +1511,14 @@ nsDocShell::GetHasForeignCookiesBeenBlocked(bool* aHasForeignCookiesBeenBlocked)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetHasCookiesLoaded(bool* aHasCookiesLoaded)
{
nsCOMPtr<nsIDocument> doc(GetDocument());
*aHasCookiesLoaded = doc && doc->GetHasCookiesLoaded();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetAllowPlugins(bool* aAllowPlugins)
{

View File

@ -649,6 +649,12 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[infallible] readonly attribute boolean hasForeignCookiesBeenBlocked;
/**
* This attribute determines whether a document seen cookies or storage
* attempts ever whether they've been allowed or blocked.
*/
[infallible] readonly attribute boolean hasCookiesLoaded;
/**
* Disconnects this docshell's editor from its window, and stores the
* editor data in the open document's session history entry. This

View File

@ -544,16 +544,17 @@ Navigator::CookieEnabled()
}
uint32_t rejectedReason = 0;
if (AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(mWindow,
codebaseURI,
&rejectedReason)) {
return true;
}
bool granted =
AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(mWindow,
codebaseURI,
&rejectedReason);
if (rejectedReason) {
AntiTrackingCommon::NotifyRejection(mWindow, rejectedReason);
}
return false;
AntiTrackingCommon::NotifyBlockingDecision(mWindow,
granted ?
AntiTrackingCommon::BlockingDecision::eAllow :
AntiTrackingCommon::BlockingDecision::eBlock,
rejectedReason);
return granted;
}
bool

View File

@ -8956,11 +8956,19 @@ nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
bool disabled =
StorageDisabledByAntiTrackingInternal(aWindow, aChannel, aPrincipal, aURI,
&rejectedReason);
if (disabled && sAntiTrackingControlCenterUIEnabled && rejectedReason) {
if (sAntiTrackingControlCenterUIEnabled) {
if (aWindow) {
AntiTrackingCommon::NotifyRejection(aWindow, rejectedReason);
AntiTrackingCommon::NotifyBlockingDecision(aWindow,
disabled ?
AntiTrackingCommon::BlockingDecision::eBlock :
AntiTrackingCommon::BlockingDecision::eAllow,
rejectedReason);
} else if (aChannel) {
AntiTrackingCommon::NotifyRejection(aChannel, rejectedReason);
AntiTrackingCommon::NotifyBlockingDecision(aChannel,
disabled ?
AntiTrackingCommon::BlockingDecision::eBlock :
AntiTrackingCommon::BlockingDecision::eAllow,
rejectedReason);
}
}
return disabled;

View File

@ -5375,6 +5375,14 @@ nsGlobalWindowOuter::NotifyContentBlockingState(unsigned aState,
if (!aBlocked) {
unblocked = !doc->GetHasForeignCookiesBlocked();
}
} else if (aState == nsIWebProgressListener::STATE_COOKIES_LOADED) {
MOZ_ASSERT(!aBlocked, "We don't expected to see blocked STATE_COOKIES_LOADED");
// Note that the logic in this branch is the logical negation of the logic
// in other branches, since the nsIDocument API we have is phrased in
// "loaded" terms as opposed to "blocked" terms.
doc->SetHasCookiesLoaded(!aBlocked, origin);
aBlocked = true;
unblocked = false;
} else {
// Ignore nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT;
}

View File

@ -1111,6 +1111,26 @@ public:
aHasCookiesBlockedByPermission);
}
/**
* Set the cookies loaded flag for this document.
*/
void SetHasCookiesLoaded(bool aHasCookiesLoaded,
const nsAString& aOriginLoaded)
{
RecordContentBlockingLog(aOriginLoaded,
nsIWebProgressListener::STATE_COOKIES_LOADED,
aHasCookiesLoaded);
}
/**
* Get cookies loaded flag for this document.
*/
bool GetHasCookiesLoaded()
{
return mContentBlockingLog.HasBlockedAnyOfType(
nsIWebProgressListener::STATE_COOKIES_LOADED);
}
/**
* Get tracking content loaded flag for this document.
*/

View File

@ -38,6 +38,13 @@ SimpleChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::NotifyCookieAllowed()
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::NotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{

View File

@ -34,6 +34,12 @@ interface nsIParentChannel : nsIStreamListener
*/
[noscript] void notifyTrackingProtectionDisabled();
/**
* Called to notify the HttpChannelChild that cookie has been allowed for
* this load.
*/
[noscript] void notifyCookieAllowed();
/**
* Called to notify the HttpChannelChild that cookie has been blocked for
* this load.

View File

@ -2269,6 +2269,7 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
return;
case STATUS_ACCEPTED: // Fallthrough
case STATUS_ACCEPT_SESSION:
NotifyAccepted(aChannel);
if (aIsForeign) {
NotifyThirdParty(aHostURI, true, aChannel);
}
@ -2288,6 +2289,14 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
}
}
void
nsCookieService::NotifyAccepted(nsIChannel* aChannel)
{
AntiTrackingCommon::NotifyBlockingDecision(aChannel,
AntiTrackingCommon::BlockingDecision::eAllow,
0);
}
// notify observers that a cookie was rejected due to the users' prefs.
void
nsCookieService::NotifyRejected(nsIURI *aHostURI, nsIChannel* aChannel,
@ -2298,7 +2307,9 @@ nsCookieService::NotifyRejected(nsIURI *aHostURI, nsIChannel* aChannel,
os->NotifyObservers(aHostURI, "cookie-rejected", nullptr);
}
AntiTrackingCommon::NotifyRejection(aChannel, aRejectedReason);
AntiTrackingCommon::NotifyBlockingDecision(aChannel,
AntiTrackingCommon::BlockingDecision::eBlock,
aRejectedReason);
}
// notify observers that a third-party cookie was accepted/rejected

View File

@ -319,6 +319,7 @@ class nsCookieService final : public nsICookieService
bool FindSecureCookie(const nsCookieKey& aKey, nsCookie* aCookie);
void FindStaleCookies(nsCookieEntry *aEntry, int64_t aCurrentTime, const mozilla::Maybe<bool> &aIsSecure, nsTArray<nsListIter>& aOutput, uint32_t aLimit);
void TelemetryForEvictingStaleCookie(nsCookie* aEvicted, int64_t oldestCookieTime);
void NotifyAccepted(nsIChannel* aChannel);
void NotifyRejected(nsIURI *aHostURI, nsIChannel* aChannel, uint32_t aRejectedReason);
void NotifyThirdParty(nsIURI *aHostURI, bool aAccepted, nsIChannel *aChannel);
void NotifyChanged(nsISupports *aSubject, const char16_t *aData, bool aOldCookieIsSession = false, bool aFromHttp = false);

View File

@ -38,6 +38,13 @@ DataChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
DataChannelParent::NotifyCookieAllowed()
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
DataChannelParent::NotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{

View File

@ -38,6 +38,13 @@ FileChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
FileChannelParent::NotifyCookieAllowed()
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
FileChannelParent::NotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{

View File

@ -577,6 +577,13 @@ FTPChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::NotifyCookieAllowed()
{
// One day, this should probably be filled in.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::NotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{

View File

@ -348,6 +348,21 @@ HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled()
return IPC_OK();
}
IPCResult
HttpBackgroundChannelChild::RecvNotifyCookieAllowed()
{
LOG(("HttpBackgroundChannelChild::RecvNotifyCookieAllowed [this=%p]\n", this));
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
}
mChannelChild->ProcessNotifyCookieAllowed();
return IPC_OK();
}
IPCResult
HttpBackgroundChannelChild::RecvNotifyTrackingCookieBlocked(const uint32_t& aRejectedReason)
{

View File

@ -65,6 +65,8 @@ protected:
IPCResult RecvNotifyTrackingProtectionDisabled() override;
IPCResult RecvNotifyCookieAllowed() override;
IPCResult RecvNotifyTrackingCookieBlocked(const uint32_t& aRejectedReason) override;
IPCResult RecvNotifyTrackingResource(const bool& aIsThirdParty) override;

View File

@ -379,6 +379,35 @@ HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled()
return SendNotifyTrackingProtectionDisabled();
}
bool
HttpBackgroundChannelParent::OnNotifyCookieAllowed()
{
LOG(("HttpBackgroundChannelParent::OnNotifyCookieAllowed [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
RefPtr<HttpBackgroundChannelParent> self = this;
nsresult rv = mBackgroundThread->Dispatch(
NS_NewRunnableFunction(
"net::HttpBackgroundChannelParent::OnNotifyCookieAllowed",
[self]() {
self->OnNotifyCookieAllowed();
}),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendNotifyCookieAllowed();
}
bool
HttpBackgroundChannelParent::OnNotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{

View File

@ -69,6 +69,9 @@ public:
// To send NotifyTrackingProtectionDisabled message over background channel.
bool OnNotifyTrackingProtectionDisabled();
// To send NotifyCookieAllowed message over background channel.
bool OnNotifyCookieAllowed();
// To send NotifyTrackingCookieBlocked message over background channel.
bool OnNotifyTrackingCookieBlocked(uint32_t aRejectedReason);

View File

@ -2050,6 +2050,25 @@ HttpChannelChild::ProcessNotifyTrackingProtectionDisabled()
NS_DISPATCH_NORMAL);
}
void
HttpChannelChild::ProcessNotifyCookieAllowed()
{
LOG(("HttpChannelChild::ProcessNotifyCookieAllowed [this=%p]\n", this));
MOZ_ASSERT(OnSocketThread());
RefPtr<HttpChannelChild> self = this;
nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
neckoTarget->Dispatch(
NS_NewRunnableFunction(
"nsChannelClassifier::NotifyBlockingDecision",
[self]() {
AntiTrackingCommon::NotifyBlockingDecision(self,
AntiTrackingCommon::BlockingDecision::eAllow,
0);
}),
NS_DISPATCH_NORMAL);
}
void
HttpChannelChild::ProcessNotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{
@ -2062,7 +2081,9 @@ HttpChannelChild::ProcessNotifyTrackingCookieBlocked(uint32_t aRejectedReason)
NS_NewRunnableFunction(
"nsChannelClassifier::NotifyTrackingCookieBlocked",
[self, aRejectedReason]() {
AntiTrackingCommon::NotifyRejection(self, aRejectedReason);
AntiTrackingCommon::NotifyBlockingDecision(self,
AntiTrackingCommon::BlockingDecision::eBlock,
aRejectedReason);
}),
NS_DISPATCH_NORMAL);
}

View File

@ -259,6 +259,7 @@ private:
void ProcessFlushedForDiversion();
void ProcessDivertMessages();
void ProcessNotifyTrackingProtectionDisabled();
void ProcessNotifyCookieAllowed();
void ProcessNotifyTrackingCookieBlocked(uint32_t aRejectedReason);
void ProcessNotifyTrackingResource(bool aIsThirdParty);
void ProcessSetClassifierMatchedInfo(const nsCString& aList,

View File

@ -1903,6 +1903,17 @@ HttpChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
HttpChannelParent::NotifyCookieAllowed()
{
LOG(("HttpChannelParent::NotifyCookieAllowed [this=%p]\n", this));
if (!mIPCClosed) {
MOZ_ASSERT(mBgParent);
Unused << NS_WARN_IF(!mBgParent->OnNotifyCookieAllowed());
}
return NS_OK;
}
NS_IMETHODIMP
HttpChannelParent::NotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{

View File

@ -56,6 +56,9 @@ child:
// Tell the child that tracking protection was disabled for this load.
async NotifyTrackingProtectionDisabled();
// Tell the child that cookies are allowed for this load.
async NotifyCookieAllowed();
// Tell the child that tracking cookies are blocked for this load.
async NotifyTrackingCookieBlocked(uint32_t aRejectedReason);

View File

@ -832,12 +832,18 @@ nsHttpChannel::ConnectOnTailUnblock()
LOG(("nsHttpChannel::ConnectOnTailUnblock [this=%p]\n", this));
bool isTrackingResource = mIsThirdPartyTrackingResource; // is atomic
if (isTrackingResource && CheckFastBlocked()) {
AntiTrackingCommon::NotifyRejection(this,
nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT);
Unused << AsyncAbort(NS_ERROR_TRACKING_ANNOTATION_URI);
CloseCacheEntry(false);
return NS_OK;
if (isTrackingResource) {
bool engageFastBlock = CheckFastBlocked();
AntiTrackingCommon::NotifyBlockingDecision(this,
engageFastBlock ?
AntiTrackingCommon::BlockingDecision::eBlock :
AntiTrackingCommon::BlockingDecision::eAllow,
nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT);
if (engageFastBlock) {
Unused << AsyncAbort(NS_ERROR_TRACKING_ANNOTATION_URI);
CloseCacheEntry(false);
return NS_OK;
}
}
// Consider opening a TCP connection right away.

View File

@ -208,6 +208,10 @@ nsSecureBrowserUIImpl::CheckForBlockedContent()
if (docShell->GetHasAllCookiesBeenBlocked()) {
mState |= STATE_COOKIES_BLOCKED_ALL;
}
if (docShell->GetHasCookiesLoaded()) {
mState |= STATE_COOKIES_LOADED;
}
}
// Helper function to determine if the given URI can be considered secure.

View File

@ -229,7 +229,8 @@ ReportBlockingToConsole(nsPIDOMWindowOuter* aWindow, nsIURI* aURI,
uint32_t aRejectedReason)
{
MOZ_ASSERT(aWindow && aURI);
MOZ_ASSERT(aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
MOZ_ASSERT(aRejectedReason == 0 ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN ||
@ -494,7 +495,7 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(nsIPrincipal* aPrincipa
LOG_SPEC(("Tracking principal (%s) hasn't been interacted with before, "
"refusing to add a first-party storage permission to access it",
_spec), trackingURI);
NotifyRejection(aParentWindow, blockReason);
NotifyBlockingDecision(aParentWindow, BlockingDecision::eBlock, blockReason);
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
}
@ -1205,26 +1206,41 @@ AntiTrackingCommon::IsOnContentBlockingAllowList(nsIURI* aTopWinURI,
}
/* static */ void
AntiTrackingCommon::NotifyRejection(nsIChannel* aChannel,
uint32_t aRejectedReason)
AntiTrackingCommon::NotifyBlockingDecision(nsIChannel* aChannel,
BlockingDecision aDecision,
uint32_t aRejectedReason)
{
MOZ_ASSERT(aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
MOZ_ASSERT(aRejectedReason == 0 ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT);
MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
aDecision == BlockingDecision::eAllow);
if (!aChannel) {
return;
}
// When we allow loads, collapse all cookie related reason codes into STATE_COOKIES_LOADED.
bool sendCookieLoadedNotification = false;
if (aRejectedReason != nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT) {
sendCookieLoadedNotification = true;
}
// Can be called in EITHER the parent or child process.
nsCOMPtr<nsIParentChannel> parentChannel;
NS_QueryNotificationCallbacks(aChannel, parentChannel);
if (parentChannel) {
// This channel is a parent-process proxy for a child process request.
// Tell the child process channel to do this instead.
parentChannel->NotifyTrackingCookieBlocked(aRejectedReason);
if (aDecision == BlockingDecision::eBlock) {
parentChannel->NotifyTrackingCookieBlocked(aRejectedReason);
} else {
// Ignore the code related to fastblock
parentChannel->NotifyCookieAllowed();
}
return;
}
@ -1246,22 +1262,38 @@ AntiTrackingCommon::NotifyRejection(nsIChannel* aChannel,
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
pwin->NotifyContentBlockingState(aRejectedReason, aChannel, true, uri);
if (aDecision == BlockingDecision::eBlock) {
pwin->NotifyContentBlockingState(aRejectedReason, aChannel, true, uri);
ReportBlockingToConsole(pwin, uri, aRejectedReason);
ReportBlockingToConsole(pwin, uri, aRejectedReason);
}
if (sendCookieLoadedNotification) {
pwin->NotifyContentBlockingState(nsIWebProgressListener::STATE_COOKIES_LOADED,
aChannel, false, uri);
}
}
/* static */ void
AntiTrackingCommon::NotifyRejection(nsPIDOMWindowInner* aWindow,
uint32_t aRejectedReason)
AntiTrackingCommon::NotifyBlockingDecision(nsPIDOMWindowInner* aWindow,
BlockingDecision aDecision,
uint32_t aRejectedReason)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
MOZ_ASSERT(aRejectedReason == 0 ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT);
MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
aDecision == BlockingDecision::eAllow);
// When we allow loads, collapse all cookie related reason codes into STATE_COOKIES_LOADED.
bool sendCookieLoadedNotification = false;
if (aRejectedReason != nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT) {
sendCookieLoadedNotification = true;
}
nsCOMPtr<nsPIDOMWindowOuter> pwin = GetTopWindow(aWindow);
if (!pwin) {
@ -1287,9 +1319,16 @@ AntiTrackingCommon::NotifyRejection(nsPIDOMWindowInner* aWindow,
}
nsIURI* uri = document->GetDocumentURI();
pwin->NotifyContentBlockingState(aRejectedReason, channel, true, uri);
if (aDecision == BlockingDecision::eBlock) {
pwin->NotifyContentBlockingState(aRejectedReason, channel, true, uri);
ReportBlockingToConsole(pwin, uri, aRejectedReason);
ReportBlockingToConsole(pwin, uri, aRejectedReason);
}
if (sendCookieLoadedNotification) {
pwin->NotifyContentBlockingState(nsIWebProgressListener::STATE_COOKIES_LOADED,
channel, false, uri);
}
}
/* static */ void

View File

@ -129,10 +129,18 @@ public:
ContentBlockingAllowListPurpose aPurpose,
bool& aIsAllowListed);
enum class BlockingDecision {
eBlock,
eAllow,
};
// This method can be called on the parent process or on the content process.
// The notification is propagated to the child channel if aChannel is a parent
// channel proxy.
//
// aDecision can be eBlock if we have decided to block some content, or eAllow
// if we have decided to allow the content through.
//
// aRejectedReason must be one of these values:
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER
@ -140,10 +148,12 @@ public:
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN
// * nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT
static void
NotifyRejection(nsIChannel* aChannel, uint32_t aRejectedReason);
NotifyBlockingDecision(nsIChannel* aChannel, BlockingDecision aDecision,
uint32_t aRejectedReason);
static void
NotifyRejection(nsPIDOMWindowInner* aWindow, uint32_t aRejectedReason);
NotifyBlockingDecision(nsPIDOMWindowInner* aWindow, BlockingDecision aDecision,
uint32_t aRejectedReason);
};
} // namespace mozilla

View File

@ -156,29 +156,54 @@ add_task(async function() {
is(text, 1, "One cookie received received for scripts.");
});
let expectTrackerBlocked = (item, blocked) => {
is(item[0], Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER,
"Correct blocking type reported");
is(item[1], blocked,
"Correct blocking status reported");
ok(item[2] >= 1,
"Correct repeat count reported");
};
let expectTrackerFound = item => {
is(item[0], Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT,
"Correct blocking type reported");
is(item[1], true,
"Correct blocking status reported");
ok(item[2] >= 1,
"Correct repeat count reported");
};
let expectCookiesLoaded = item => {
is(item[0], Ci.nsIWebProgressListener.STATE_COOKIES_LOADED,
"Correct blocking type reported");
is(item[1], true,
"Correct blocking status reported");
ok(item[2] >= 1,
"Correct repeat count reported");
};
let log = JSON.parse(await browser.getContentBlockingLog());
for (let trackerOrigin in log) {
is(trackerOrigin, TEST_3RD_PARTY_DOMAIN, "Correct tracker origin must be reported");
let originLog = log[trackerOrigin];
is(originLog.length, 3, "We should have 3 entries in the compressed log");
is(originLog[0][0], Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT,
"Correct blocking type reported");
is(originLog[0][1], true,
"Correct blocking status reported");
ok(originLog[0][2] >= 1,
"Correct repeat count reported");
is(originLog[1][0], Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER,
"Correct blocking type reported");
is(originLog[1][1], true,
"Correct blocking status reported");
is(originLog[1][2], 6,
"Correct repeat count reported");
is(originLog[2][0], Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER,
"Correct blocking type reported");
is(originLog[2][1], false,
"Correct blocking status reported");
ok(originLog[2][2] >= 1,
"Correct repeat count reported");
is(originLog.length, 16, "We should have 16 entries in the compressed log");
expectTrackerFound(originLog[0]);
expectCookiesLoaded(originLog[1]);
expectTrackerBlocked(originLog[2], true);
expectCookiesLoaded(originLog[3]);
expectTrackerBlocked(originLog[4], true);
expectCookiesLoaded(originLog[5]);
expectTrackerBlocked(originLog[6], true);
expectCookiesLoaded(originLog[7]);
expectTrackerBlocked(originLog[8], true);
expectCookiesLoaded(originLog[9]);
expectTrackerBlocked(originLog[10], true);
expectCookiesLoaded(originLog[11]);
expectTrackerBlocked(originLog[12], true);
expectCookiesLoaded(originLog[13]);
expectTrackerBlocked(originLog[14], false);
expectCookiesLoaded(originLog[15]);
}
info("Removing the tab");

View File

@ -365,10 +365,16 @@ this.AntiTracking = {
let originLog = contentBlockingLog[trackerOrigin];
for (let i = 0; i < originLog.length; ++i) {
let item = originLog[i];
is(item[0], Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT,
"Correct blocking type must be reported");
is(item[1], true, "Correct blocking status reported");
ok(item[2] >= 1, "Correct repeat count reported");
switch (item[0]) {
case Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT:
is(item[1], true, "Correct blocking status reported");
ok(item[2] >= 1, "Correct repeat count reported");
break;
case Ci.nsIWebProgressListener.STATE_COOKIES_LOADED:
is(item[1], true, "Correct blocking status reported");
ok(item[2] >= 1, "Correct repeat count reported");
break;
}
}
}
}
@ -548,20 +554,11 @@ this.AntiTracking = {
contentBlockingLog = JSON.parse(contentBlockingLogJSON);
} catch (e) {
}
// If this is the first cookie to be blocked, our state should have
// just changed, otherwise it should have previously contained the
// STATE_COOKIES_BLOCKED_TRACKER bit too.
if (cookieBlocked) {
if (cookieBlocked == 1) {
is(oldState & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER, 0,
"When blocking the first cookie, old state should not have had the " +
"STATE_COOKIES_BLOCKED_TRACKER bit");
}
for (let trackerOrigin in contentBlockingLog) {
is(trackerOrigin, TEST_3RD_PARTY_DOMAIN, "Correct tracker origin must be reported");
let originLog = contentBlockingLog[trackerOrigin];
ok(originLog.length > 1, "We should have at least two items in the log");
ok(originLog.length >= 1, "We should have at least two items in the log");
for (let i = 0; i < originLog.length; ++i) {
let item = originLog[i];
switch (item[0]) {
@ -583,6 +580,10 @@ this.AntiTracking = {
is(item[2], 1, "Correct repeat count reported");
}
break;
case Ci.nsIWebProgressListener.STATE_COOKIES_LOADED:
is(item[1], true, "Correct blocking status reported");
ok(item[2] >= 1, "Correct repeat count reported");
break;
}
}
}
@ -696,17 +697,18 @@ this.AntiTracking = {
}
for (let trackerOrigin in contentBlockingLog) {
is(trackerOrigin, TEST_3RD_PARTY_DOMAIN, "Correct tracker origin must be reported");
let originLog = contentBlockingLog[trackerOrigin];
ok(originLog.length > 1, "We should have at least two items in the log");
ok(originLog.length >= 1, "We should have at least two items in the log");
for (let i = 0; i < originLog.length; ++i) {
let item = originLog[i];
switch (item[0]) {
case Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT:
is(trackerOrigin, TEST_3RD_PARTY_DOMAIN, "Correct tracker origin must be reported");
is(item[1], true, "Correct blocking status reported");
ok(item[2] >= 1, "Correct repeat count reported");
break;
case Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT:
is(trackerOrigin, TEST_3RD_PARTY_DOMAIN, "Correct tracker origin must be reported");
if (item[1]) {
ok(item[2] >= 1, "Correct repeat count reported");
} else {
@ -716,10 +718,16 @@ this.AntiTracking = {
}
break;
case Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER:
is(trackerOrigin, TEST_3RD_PARTY_DOMAIN, "Correct tracker origin must be reported");
// We can expect 1 or more repeat count whether or not blocking has happened,
// so nothing to assert on item[1].
ok(item[2] >= 1, "Correct repeat count reported");
break;
case Ci.nsIWebProgressListener.STATE_COOKIES_LOADED:
// The trackerOrigin here is sometimes TEST_DOMAIN, sometimes TEST_3RD_PARTY_DOMAIN.
is(item[1], true, "Correct blocking status reported");
ok(item[2] >= 1, "Correct repeat count reported");
break;
}
}
}

View File

@ -327,6 +327,7 @@ interface nsIWebProgressListener : nsISupports
* STATE_BLOCKED_SLOW_TRACKING_CONTENT
* Rejected because of the FastBlock feature.
*/
const unsigned long STATE_COOKIES_LOADED = 0x00008000;
const unsigned long STATE_COOKIES_BLOCKED_BY_PERMISSION = 0x10000000;
const unsigned long STATE_COOKIES_BLOCKED_TRACKER = 0x20000000;
const unsigned long STATE_COOKIES_BLOCKED_ALL = 0x40000000;

View File

@ -422,6 +422,12 @@ NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::NotifyCookieAllowed()
{
// nothing to do
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingCookieBlocked(uint32_t aRejectedReason)
{
// nothing to do