diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index 9aa742d92093..dbf5cdee9def 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -2458,12 +2458,51 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument, PreloadLocalStorage(); - mStorageAccessPermissionGranted = ContentBlocking::ShouldAllowAccessFor( - newInnerWindow, aDocument->GetDocumentURI(), nullptr); + mStorageAccessPermissionGranted = + CheckStorageAccessPermission(aDocument, newInnerWindow); return NS_OK; } +bool nsGlobalWindowOuter::CheckStorageAccessPermission( + Document* aDocument, nsGlobalWindowInner* aInnerWindow) { + if (!aInnerWindow) { + return false; + } + + nsIURI* uri = aDocument->GetDocumentURI(); + if (!aDocument->CookieJarSettings()->GetRejectThirdPartyContexts() || + !nsContentUtils::IsThirdPartyWindowOrChannel(aInnerWindow, nullptr, + uri)) { + return false; + } + + uint32_t cookieBehavior = aDocument->CookieJarSettings()->GetCookieBehavior(); + + // Grant storage access by default if the first-party storage access + // permission has been granted already. Don't notify in this case, since we + // would be notifying the user needlessly. + bool checkStorageAccess = false; + if (net::CookieJarSettings::IsRejectThirdPartyWithExceptions( + cookieBehavior)) { + checkStorageAccess = true; + } else { + MOZ_ASSERT( + cookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER || + cookieBehavior == + nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN); + if (nsContentUtils::IsThirdPartyTrackingResourceWindow(aInnerWindow)) { + checkStorageAccess = true; + } + } + + if (checkStorageAccess) { + return ContentBlocking::ShouldAllowAccessFor(aInnerWindow, uri, nullptr); + } + + return false; +} + /* static */ void nsGlobalWindowOuter::PrepareForProcessChange(JSObject* aProxy) { JS::Rooted localProxy(RootingCx(), aProxy); diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h index 5b85a685bcbf..6a9d2081d4c5 100644 --- a/dom/base/nsGlobalWindowOuter.h +++ b/dom/base/nsGlobalWindowOuter.h @@ -1038,6 +1038,9 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, bool IsOnlyTopLevelDocumentInSHistory(); + bool CheckStorageAccessPermission(Document* aDocument, + nsGlobalWindowInner* aInnerWindow); + public: // Dispatch a runnable related to the global. virtual nsresult Dispatch(mozilla::TaskCategory aCategory, diff --git a/toolkit/components/antitracking/test/browser/browser.ini b/toolkit/components/antitracking/test/browser/browser.ini index 018e88c117ee..f4381fd47268 100644 --- a/toolkit/components/antitracking/test/browser/browser.ini +++ b/toolkit/components/antitracking/test/browser/browser.ini @@ -81,7 +81,6 @@ skip-if = os == "linux" && asan [browser_doublyNestedTracker.js] [browser_existingCookiesForSubresources.js] [browser_firstPartyCookieRejectionHonoursAllowList.js] -[browser_hasStorageAccess.js] [browser_imageCache4.js] [browser_imageCache8.js] [browser_onBeforeRequestNotificationForTrackingResources.js] diff --git a/toolkit/components/antitracking/test/browser/browser_hasStorageAccess.js b/toolkit/components/antitracking/test/browser/browser_hasStorageAccess.js deleted file mode 100644 index 1228f340ac34..000000000000 --- a/toolkit/components/antitracking/test/browser/browser_hasStorageAccess.js +++ /dev/null @@ -1,183 +0,0 @@ -// This test ensures HasStorageAccess API returns the right value under different -// scenarios. - -/* import-globals-from antitracking_head.js */ - -var settings = [ - // 3rd-party no-tracker - { - name: "Test whether 3rd-party non-tracker frame has storage access", - topPage: TEST_TOP_PAGE, - thirdPartyPage: TEST_4TH_PARTY_PAGE, - }, - // 3rd-party no-tracker with permission - { - name: - "Test whether 3rd-party non-tracker frame has storage access when storage permission is granted before", - topPage: TEST_TOP_PAGE, - thirdPartyPage: TEST_4TH_PARTY_PAGE, - setup: () => { - let type = "3rdPartyStorage^http://not-tracking.example.com"; - let permission = Services.perms.ALLOW_ACTION; - let expireType = Services.perms.EXPIRE_SESSION; - PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0); - - registerCleanupFunction(_ => { - Services.perms.removeAll(); - }); - }, - }, - // 3rd-party tracker - { - name: "Test whether 3rd-party tracker frame has storage access", - topPage: TEST_TOP_PAGE, - thirdPartyPage: TEST_3RD_PARTY_PAGE, - }, - // 3rd-party tracker with permission - { - name: - "Test whether 3rd-party tracker frame has storage access when storage access permission is granted before", - topPage: TEST_TOP_PAGE, - thirdPartyPage: TEST_3RD_PARTY_PAGE, - setup: () => { - let type = "3rdPartyStorage^https://tracking.example.org"; - let permission = Services.perms.ALLOW_ACTION; - let expireType = Services.perms.EXPIRE_SESSION; - PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0); - - registerCleanupFunction(_ => { - Services.perms.removeAll(); - }); - }, - }, - // same-site 3rd-party tracker - { - name: "Test whether same-site 3rd-party tracker frame has storage access", - topPage: TEST_TOP_PAGE, - thirdPartyPage: TEST_ANOTHER_3RD_PARTY_PAGE, - }, - // same-origin 3rd-party tracker - { - name: "Test whether same-origin 3rd-party tracker frame has storage access", - topPage: TEST_ANOTHER_3RD_PARTY_DOMAIN + TEST_PATH + "page.html", - thirdPartyPage: TEST_ANOTHER_3RD_PARTY_PAGE, - }, -]; - -var testCases = [ - { - behavior: BEHAVIOR_ACCEPT, // 0 - hasStorageAccess: [ - true /* 3rd-party non-tracker */, - true /* 3rd-party non-tracker with permission */, - true /* 3rd-party tracker */, - true /* 3rd-party tracker with permission */, - true /* same-site tracker */, - true /* same-origin tracker */, - ], - }, - { - behavior: BEHAVIOR_REJECT_FOREIGN, // 1 - hasStorageAccess: [ - false /* 3rd-party non-tracker */, - true /* 3rd-party non-tracker with permission */, - false /* 3rd-party tracker */, - true /* 3rd-party tracker with permission */, - true /* same-site tracker */, - true /* same-origin tracker */, - ], - }, - { - behavior: BEHAVIOR_REJECT, // 2 - hasStorageAccess: [ - false /* 3rd-party non-tracker */, - false /* 3rd-party non-tracker with permission */, - false /* 3rd-party tracker */, - false /* 3rd-party tracker with permission */, - false /* same-site tracker */, - true /* same-origin tracker */, - ], - }, - { - behavior: BEHAVIOR_LIMIT_FOREIGN, // 3 - hasStorageAccess: [ - false /* 3rd-party non-tracker */, - false /* 3rd-party non-tracker with permission */, - false /* 3rd-party tracker */, - false /* 3rd-party tracker with permission */, - true /* same-site tracker */, - true /* same-origin tracker */, - ], - }, - { - behavior: BEHAVIOR_REJECT_TRACKER, // 4 - hasStorageAccess: [ - true /* 3rd-party non-tracker */, - true /* 3rd-party non-tracker with permission */, - false /* 3rd-party tracker */, - true /* 3rd-party tracker with permission */, - true /* same-site tracker */, - true /* same-origin tracker */, - ], - }, - { - behavior: BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN, // 5 - hasStorageAccess: [ - false /* 3rd-party non-tracker */, - true /* 3rd-party non-tracker with permission */, - false /* 3rd-party tracker */, - true /* 3rd-party tracker with permission */, - true /* same-site tracker */, - true /* same-origin tracker */, - ], - }, -]; - -(function() { - settings.forEach(setting => { - if (setting.setup) { - add_task(async _ => { - setting.setup(); - }); - } - - testCases.forEach(test => { - //if (test.behavior != 3) { - //return; - //} - - let callback = test.hasStorageAccess[settings.indexOf(setting)] - ? async _ => { - /* import-globals-from storageAccessAPIHelpers.js */ - await hasStorageAccessInitially(); - } - : async _ => { - /* import-globals-from storageAccessAPIHelpers.js */ - await noStorageAccessInitially(); - }; - - AntiTracking._createTask({ - name: setting.name, - cookieBehavior: test.behavior, - allowList: false, - callback, - extraPrefs: null, - expectedBlockingNotifications: 0, - runInPrivateWindow: false, - iframeSandbox: null, - accessRemoval: null, - callbackAfterRemoval: null, - topPage: setting.topPage, - thirdPartyPage: setting.thirdPartyPage, - }); - }); - - add_task(async _ => { - await new Promise(resolve => { - Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => - resolve() - ); - }); - }); - }); -})();