Bug 1493563 - Part 9: Notify about trackers being unblocked when being granted a first-party exception; r=baku
☠☠ backed out by 1681bd622c63 ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Sun, 23 Sep 2018 02:36:04 -0400
changeset 494520 02b8b073f7d7007ce41c2fb71aab5ceafe5d371b
parent 494519 3ef707008502d3555d384f8803b97d4b4c7a0d55
child 494521 344298c73ee77f8e003717fad204e1cbb6da13eb
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1493563
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1493563 - Part 9: Notify about trackers being unblocked when being granted a first-party exception; r=baku Differential Revision: https://phabricator.services.mozilla.com/D6599
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsGlobalWindowOuter.h
dom/base/nsPIDOMWindow.h
toolkit/components/antitracking/AntiTrackingCommon.cpp
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -5277,16 +5277,17 @@ nsGlobalWindowOuter::FirePopupBlockedEve
   event->SetTrusted(true);
 
   aDoc->DispatchEvent(*event);
 }
 
 void
 nsGlobalWindowOuter::NotifyContentBlockingState(unsigned aState,
                                                 nsIChannel* aChannel,
+                                                bool aBlocked,
                                                 nsIURI* aURIHint)
 {
   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   if (!docShell) {
     return;
   }
   nsCOMPtr<nsIDocument> doc = docShell->GetDocument();
   NS_ENSURE_TRUE_VOID(doc);
@@ -5312,33 +5313,56 @@ nsGlobalWindowOuter::NotifyContentBlocki
     return;
   }
   securityUI->GetState(&state);
   nsAutoString origin;
   origin.SetIsVoid(true);
   if (aURIHint) {
     nsContentUtils::GetUTFOrigin(aURIHint, origin);
   }
+  bool unblocked = false;
   if (aState == nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT) {
-    doc->SetHasTrackingContentBlocked(true, origin);
+    doc->SetHasTrackingContentBlocked(aBlocked, origin);
+    if (!aBlocked) {
+      unblocked = !doc->GetHasTrackingContentBlocked();
+    }
   } else if (aState == nsIWebProgressListener::STATE_BLOCKED_SLOW_TRACKING_CONTENT) {
-    doc->SetHasSlowTrackingContentBlocked(true, origin);
+    doc->SetHasSlowTrackingContentBlocked(aBlocked, origin);
+    if (!aBlocked) {
+      unblocked = !doc->GetHasSlowTrackingContentBlocked();
+    }
   } else if (aState == nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION) {
-    doc->SetHasCookiesBlockedByPermission(true, origin);
+    doc->SetHasCookiesBlockedByPermission(aBlocked, origin);
+    if (!aBlocked) {
+      unblocked = !doc->GetHasCookiesBlockedByPermission();
+    }
   } else if (aState == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER) {
-    doc->SetHasTrackingCookiesBlocked(true, origin);
+    doc->SetHasTrackingCookiesBlocked(aBlocked, origin);
+    if (!aBlocked) {
+      unblocked = !doc->GetHasTrackingCookiesBlocked();
+    }
   } else if (aState == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL) {
-    doc->SetHasAllCookiesBlocked(true, origin);
+    doc->SetHasAllCookiesBlocked(aBlocked, origin);
+    if (!aBlocked) {
+      unblocked = !doc->GetHasAllCookiesBlocked();
+    }
   } else if (aState == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN) {
-    doc->SetHasForeignCookiesBlocked(true, origin);
+    doc->SetHasForeignCookiesBlocked(aBlocked, origin);
+    if (!aBlocked) {
+      unblocked = !doc->GetHasForeignCookiesBlocked();
+    }
   } else {
     // Ignore nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT;
   }
   const uint32_t oldState = state;
-  state |= aState;
+  if (aBlocked) {
+    state |= aState;
+  } else if (unblocked) {
+    state &= ~aState;
+  }
 
   eventSink->OnSecurityChange(aChannel, oldState, state, doc->GetContentBlockingLog());
 }
 
 //static
 bool
 nsGlobalWindowOuter::SameLoadingURI(nsIDocument *aDoc, nsIChannel *aChannel)
 {
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -480,16 +480,17 @@ public:
   FirePopupBlockedEvent(nsIDocument* aDoc,
                         nsIURI* aPopupURI,
                         const nsAString& aPopupWindowName,
                         const nsAString& aPopupWindowFeatures) override;
 
   virtual void
   NotifyContentBlockingState(unsigned aState,
                              nsIChannel* aChannel,
+                             bool aBlocked,
                              nsIURI* aURIHint) override;
 
   virtual uint32_t GetSerial() override {
     return mSerial;
   }
 
   void AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
 
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -1090,16 +1090,17 @@ public:
   FirePopupBlockedEvent(nsIDocument* aDoc,
                         nsIURI* aPopupURI,
                         const nsAString& aPopupWindowName,
                         const nsAString& aPopupWindowFeatures) = 0;
 
   virtual void
   NotifyContentBlockingState(unsigned aState,
                              nsIChannel* aChannel,
+                             bool aBlocked = true,
                              nsIURI* aURIHint = nullptr) = 0;
 
   // WebIDL-ish APIs
   void MarkUncollectableForCCGeneration(uint32_t aGeneration)
   {
     mMarkedCCGeneration = aGeneration;
   }
 
--- a/toolkit/components/antitracking/AntiTrackingCommon.cpp
+++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp
@@ -320,16 +320,42 @@ ReportUnblockingConsole(nsPIDOMWindowInn
                                     NS_LITERAL_CSTRING("Content Blocking"),
                                     doc,
                                     nsContentUtils::eNECKO_PROPERTIES,
                                     messageWithDifferentOrigin,
                                     params, 3);
   }
 }
 
+already_AddRefed<nsPIDOMWindowOuter>
+GetTopWindow(nsPIDOMWindowInner* aWindow)
+{
+  nsIDocument* document = aWindow->GetExtantDoc();
+  if (!document) {
+    return nullptr;
+  }
+
+  nsIChannel* channel = document->GetChannel();
+  if (!channel) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> pwin;
+  auto* outer = nsGlobalWindowOuter::Cast(aWindow->GetOuterWindow());
+  if (outer) {
+    pwin = outer->GetTopOuter();
+  }
+
+  if (!pwin) {
+    return nullptr;
+  }
+
+  return pwin.forget();
+}
+
 } // anonymous
 
 /* static */ bool
 AntiTrackingCommon::ShouldHonorContentBlockingCookieRestrictions()
 {
   return StaticPrefs::browser_contentblocking_enabled();
 }
 
@@ -385,19 +411,40 @@ AntiTrackingCommon::AddFirstPartyStorage
   // We are a 3rd party source.
   } else if (!GetParentPrincipalAndTrackingOrigin(parentWindow,
                                                   getter_AddRefs(topLevelStoragePrincipal),
                                                   trackingOrigin)) {
     LOG(("Error while computing the parent principal and tracking origin, bailing out early"));
     return StorageAccessGrantPromise::CreateAndReject(false, __func__);
   }
 
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_NewURI(getter_AddRefs(uri), trackingOrigin);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    LOG(("Couldn't make a new URI out of the tracking origin"));
+    return StorageAccessGrantPromise::CreateAndReject(false, __func__);
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> pwin = GetTopWindow(parentWindow);
+  if (!pwin) {
+    LOG(("Couldn't get the top window"));
+    return StorageAccessGrantPromise::CreateAndReject(false, __func__);
+  }
+
+  nsIChannel* channel =
+    pwin->GetCurrentInnerWindow()->GetExtantDoc()->GetChannel();
+
+  // We hardcode this block reason since the first-party storage access permission
+  // is granted for the purpose of blocking trackers.
+  const uint32_t blockReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER;
+  pwin->NotifyContentBlockingState(blockReason, channel, false, uri);
+
   NS_ConvertUTF16toUTF8 grantedOrigin(aOrigin);
 
-  ReportUnblockingConsole(aParentWindow, NS_ConvertUTF8toUTF16(trackingOrigin),
+  ReportUnblockingConsole(parentWindow, NS_ConvertUTF8toUTF16(trackingOrigin),
                           aOrigin, aReason);
 
   if (XRE_IsParentProcess()) {
     LOG(("Saving the permission: trackingOrigin=%s, grantedOrigin=%s",
          trackingOrigin.get(), grantedOrigin.get()));
 
     RefPtr<StorageAccessGrantPromise::Private> p = new StorageAccessGrantPromise::Private(__func__);
     SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(topLevelStoragePrincipal,
@@ -1083,56 +1130,58 @@ AntiTrackingCommon::NotifyRejection(nsIC
   nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(win);
   if (!pwin) {
     return;
   }
 
   nsCOMPtr<nsIURI> uri;
   aChannel->GetURI(getter_AddRefs(uri));
 
-  pwin->NotifyContentBlockingState(aRejectedReason, aChannel, uri);
+  pwin->NotifyContentBlockingState(aRejectedReason, aChannel, true, uri);
 
   ReportBlockingToConsole(pwin, uri, aRejectedReason);
 }
 
 /* static */ void
 AntiTrackingCommon::NotifyRejection(nsPIDOMWindowInner* aWindow,
                                     uint32_t aRejectedReason)
 {
   MOZ_ASSERT(aWindow);
   MOZ_ASSERT(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);
 
-  nsIDocument* document = aWindow->GetExtantDoc();
-  if (!document) {
+
+  nsCOMPtr<nsPIDOMWindowOuter> pwin = GetTopWindow(aWindow);
+  if (!pwin) {
     return;
   }
 
-  nsIChannel* channel = document->GetChannel();
+  nsPIDOMWindowInner* inner = pwin->GetCurrentInnerWindow();
+  if (!inner) {
+    return;
+  }
+  nsIDocument* pwinDoc = inner->GetExtantDoc();
+  if (!pwinDoc) {
+    return;
+  }
+  nsIChannel* channel = pwinDoc->GetChannel();
   if (!channel) {
     return;
   }
 
-  nsCOMPtr<nsPIDOMWindowOuter> pwin;
-  auto* outer = nsGlobalWindowOuter::Cast(aWindow->GetOuterWindow());
-  if (outer) {
-    pwin = outer->GetTopOuter();
-  }
-
-  if (!pwin) {
+  nsIDocument* document = aWindow->GetExtantDoc();
+  if (!document) {
     return;
   }
+  nsIURI* uri = document->GetDocumentURI();
 
-  nsCOMPtr<nsIURI> uri;
-  channel->GetURI(getter_AddRefs(uri));
-
-  pwin->NotifyContentBlockingState(aRejectedReason, channel, uri);
+  pwin->NotifyContentBlockingState(aRejectedReason, channel, true, uri);
 
   ReportBlockingToConsole(pwin, uri, aRejectedReason);
 }
 
 /* static */ void
 AntiTrackingCommon::StoreUserInteractionFor(nsIPrincipal* aPrincipal)
 {
   if (XRE_IsParentProcess()) {