Bug 1509691 - Ensure that the antitracking backend uses the channel third-party tracking flag r=baku
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 27 Nov 2018 08:59:09 +0000
changeset 507528 1e7b379680f8bb5fbc3201b21c69318790cdbbb6
parent 507527 5c14b80a2a3f8f8ef3bc3db36765e7da86372c53
child 507529 e01c587ecd1dea5b3a65a65d66f316d769a519ec
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1509691
milestone65.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 1509691 - Ensure that the antitracking backend uses the channel third-party tracking flag r=baku This makes a difference for doubly nested trackers that are embedded under the same top-level tracker, with a third-party origin in the middle, as the test case in this commit has set up things. The test case here fails without the code changes. Differential Revision: https://phabricator.services.mozilla.com/D12855
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
toolkit/components/antitracking/AntiTrackingCommon.cpp
toolkit/components/antitracking/test/browser/browser.ini
toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9033,16 +9033,36 @@ nsContentUtils::IsTrackingResourceWindow
     do_QueryInterface(document->GetChannel());
   if (!httpChannel) {
     return false;
   }
 
   return httpChannel->GetIsTrackingResource();
 }
 
+// static public
+bool
+nsContentUtils::IsThirdPartyTrackingResourceWindow(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->GetIsThirdPartyTrackingResource();
+}
+
 static bool
 StorageDisabledByAntiTrackingInternal(nsPIDOMWindowInner* aWindow,
                                       nsIChannel* aChannel,
                                       nsIPrincipal* aPrincipal,
                                       nsIURI* aURI,
                                       uint32_t* aRejectedReason)
 {
   MOZ_ASSERT(aWindow || aChannel || aPrincipal);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -3120,16 +3120,22 @@ public:
 
   /*
    * Returns true if this window's channel has been marked as a tracking
    * resource.
    */
   static bool IsTrackingResourceWindow(nsPIDOMWindowInner* aWindow);
 
   /*
+   * Returns true if this window's channel has been marked as a third-party
+   * tracking resource.
+   */
+  static bool IsThirdPartyTrackingResourceWindow(nsPIDOMWindowInner* aWindow);
+
+  /*
    * Serializes a HTML nsINode into its markup representation.
    */
   static bool SerializeNodeToMarkup(nsINode* aRoot,
                                     bool aDescendentsOnly,
                                     nsAString& aOut);
 
   /*
    * Returns true iff the provided JSObject is a global, and its URI matches
--- a/toolkit/components/antitracking/AntiTrackingCommon.cpp
+++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp
@@ -65,17 +65,17 @@ namespace {
 
 bool
 GetParentPrincipalAndTrackingOrigin(nsGlobalWindowInner* a3rdPartyTrackingWindow,
                                     nsIPrincipal** aTopLevelStoragePrincipal,
                                     nsACString& aTrackingOrigin,
                                     nsIURI** aTrackingURI,
                                     nsIPrincipal** aTrackingPrincipal)
 {
-  if (!nsContentUtils::IsTrackingResourceWindow(a3rdPartyTrackingWindow)) {
+  if (!nsContentUtils::IsThirdPartyTrackingResourceWindow(a3rdPartyTrackingWindow)) {
     return false;
   }
 
   nsIDocument* doc = a3rdPartyTrackingWindow->GetDocument();
   // Make sure storage access isn't disabled
   if (doc && ((doc->GetSandboxFlags() & SANDBOXED_STORAGE_ACCESS) != 0 ||
               nsContentUtils::IsInPrivateBrowsing(doc))) {
     return false;
@@ -811,18 +811,18 @@ AntiTrackingCommon::IsFirstPartyStorageA
     // for non-cookie storage types, this may change.
     LOG(("Nothing more to do due to the behavior code %d", int(behavior)));
     *aRejectedReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN;
     return false;
   }
 
   MOZ_ASSERT(behavior == nsICookieService::BEHAVIOR_REJECT_TRACKER);
 
-  if (!nsContentUtils::IsTrackingResourceWindow(aWindow)) {
-    LOG(("Our window isn't a tracking window"));
+  if (!nsContentUtils::IsThirdPartyTrackingResourceWindow(aWindow)) {
+    LOG(("Our window isn't a third-party tracking window"));
     return true;
   }
 
   nsCOMPtr<nsIPrincipal> parentPrincipal;
   nsCOMPtr<nsIURI> parentPrincipalURI;
   nsCOMPtr<nsIURI> trackingURI;
   nsAutoCString trackingOrigin;
   if (!GetParentPrincipalAndTrackingOrigin(nsGlobalWindowInner::Cast(aWindow),
@@ -1048,18 +1048,18 @@ AntiTrackingCommon::IsFirstPartyStorageA
     LOG(("Nothing more to do due to the behavior code %d", int(behavior)));
     *aRejectedReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN;
     return false;
   }
 
   MOZ_ASSERT(behavior == nsICookieService::BEHAVIOR_REJECT_TRACKER);
 
   // Not a tracker.
-  if (!aChannel->GetIsTrackingResource()) {
-    LOG(("Our channel isn't a tracking channel"));
+  if (!aChannel->GetIsThirdPartyTrackingResource()) {
+    LOG(("Our channel isn't a third-party tracking channel"));
     return true;
   }
 
   nsIPrincipal* parentPrincipal = loadInfo->GetTopLevelStorageAreaPrincipal();
   if (!parentPrincipal) {
     LOG(("No top-level storage area principal at hand"));
 
     // parentPrincipal can be null if the parent window is not the top-level
--- a/toolkit/components/antitracking/test/browser/browser.ini
+++ b/toolkit/components/antitracking/test/browser/browser.ini
@@ -33,16 +33,17 @@ skip-if = serviceworker_e10s
 [browser_blockingSessionStorage.js]
 skip-if = serviceworker_e10s
 [browser_blockingServiceWorkers.js]
 skip-if = (os == "win" && os_version == "6.1" && bits == 32 && !debug) # Bug 1491937
 [browser_blockingSharedWorkers.js]
 skip-if = (os == "win" && os_version == "6.1" && bits == 32 && !debug) # Bug 1491937
 [browser_blockingMessaging.js]
 [browser_blockingNoOpener.js]
+[browser_doublyNestedTracker.js]
 [browser_existingCookiesForSubresources.js]
 [browser_imageCache4.js]
 [browser_imageCache4-1.js]
 [browser_imageCache4-2.js]
 [browser_imageCache8.js]
 [browser_onBeforeRequestNotificationForTrackingResources.js]
 [browser_onModifyRequestNotificationForTrackingResources.js]
 [browser_permissionInNormalWindows.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/browser_doublyNestedTracker.js
@@ -0,0 +1,112 @@
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+add_task(async function() {
+  info("Starting doubly nested tracker test");
+
+  await SpecialPowers.flushPrefEnv();
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["browser.contentblocking.allowlist.annotations.enabled", true],
+    ["browser.contentblocking.allowlist.storage.enabled", true],
+    ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
+    ["privacy.trackingprotection.enabled", false],
+    ["privacy.trackingprotection.pbmode.enabled", false],
+    ["privacy.trackingprotection.annotate_channels", true],
+    ["privacy.restrict3rdpartystorage.userInteractionRequiredForHosts", "tracking.example.com,tracking.example.org"],
+  ]});
+
+  await UrlClassifierTestUtils.addTestTrackers();
+
+  let tab = BrowserTestUtils.addTab(gBrowser, TEST_3RD_PARTY_PAGE);
+  gBrowser.selectedTab = tab;
+
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  async function loadSubpage() {
+    async function runChecks() {
+      is(document.cookie, "", "No cookies for me");
+      document.cookie = "name=value";
+      is(document.cookie, "name=value", "I have the cookies!");
+    }
+
+    await new Promise(resolve => {
+      let ifr = document.createElement("iframe");
+      ifr.onload = _ => {
+        info("Sending code to the 3rd party content");
+        ifr.contentWindow.postMessage(runChecks.toString(), "*");
+      };
+
+      addEventListener("message", function msg(event) {
+        if (event.data.type == "finish") {
+          removeEventListener("message", msg);
+          resolve();
+          return;
+        }
+
+        if (event.data.type == "ok") {
+          ok(event.data.what, event.data.msg);
+          return;
+        }
+
+        if (event.data.type == "info") {
+          info(event.data.msg);
+          return;
+        }
+
+        ok(false, "Unknown message");
+      });
+
+      document.body.appendChild(ifr);
+      ifr.src = "https://tracking.example.org/browser/toolkit/components/antitracking/test/browser/3rdParty.html";
+    });
+  }
+
+  await ContentTask.spawn(browser,
+                          { page: TEST_ANOTHER_3RD_PARTY_PAGE,
+                            callback: loadSubpage.toString(),
+                          },
+                          async function(obj) {
+    await new content.Promise(resolve => {
+      let ifr = content.document.createElement("iframe");
+      ifr.onload = _ => {
+        info("Sending code to the 3rd party content");
+        ifr.contentWindow.postMessage(obj.callback, "*");
+      };
+
+      content.addEventListener("message", function msg(event) {
+        if (event.data.type == "finish") {
+          content.removeEventListener("message", msg);
+          resolve();
+          return;
+        }
+
+        if (event.data.type == "ok") {
+          ok(event.data.what, event.data.msg);
+          return;
+        }
+
+        if (event.data.type == "info") {
+          info(event.data.msg);
+          return;
+        }
+
+        ok(false, "Unknown message");
+      });
+
+      content.document.body.appendChild(ifr);
+      ifr.src = obj.page;
+    });
+  });
+
+  BrowserTestUtils.removeTab(tab);
+
+  UrlClassifierTestUtils.cleanupTestTrackers();
+});
+
+add_task(async function() {
+  info("Cleaning up.");
+  await new Promise(resolve => {
+    Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
+  });
+});
+