diff --git a/browser/base/content/browser-siteProtections.js b/browser/base/content/browser-siteProtections.js index fb289da9a2c6..2d0675cc756a 100644 --- a/browser/base/content/browser-siteProtections.js +++ b/browser/base/content/browser-siteProtections.js @@ -779,7 +779,10 @@ var ThirdPartyCookies = { for (let perm of Services.perms.getAllForPrincipal( gBrowser.contentPrincipal )) { - if (perm.type == "3rdPartyStorage^" + origin) { + if ( + perm.type == "3rdPartyStorage^" + origin || + perm.type.startsWith("3rdPartyStorage^" + origin + "^") + ) { return perm.capability; } } @@ -796,7 +799,10 @@ var ThirdPartyCookies = { for (let perm of Services.perms.getAllForPrincipal( gBrowser.contentPrincipal )) { - if (perm.type == "3rdPartyStorage^" + origin) { + if ( + perm.type == "3rdPartyStorage^" + origin || + perm.type.startsWith("3rdPartyStorage^" + origin + "^") + ) { Services.perms.removePermission(perm); } } diff --git a/browser/base/content/test/performance/browser_startup_mainthreadio.js b/browser/base/content/test/performance/browser_startup_mainthreadio.js index 5c6a78a16def..5f5cab77bf13 100644 --- a/browser/base/content/test/performance/browser_startup_mainthreadio.js +++ b/browser/base/content/test/performance/browser_startup_mainthreadio.js @@ -267,7 +267,7 @@ const startupPhases = { condition: WIN || MAC, fsync: 7, stat: 26, - write: 40, + write: 38, }, { // bug 975996 diff --git a/browser/base/content/test/siteProtections/browser.ini b/browser/base/content/test/siteProtections/browser.ini index 502968fa84f1..ad63ed7f0a50 100644 --- a/browser/base/content/test/siteProtections/browser.ini +++ b/browser/base/content/test/siteProtections/browser.ini @@ -1,7 +1,6 @@ [DEFAULT] support-files = head.js - !/browser/base/content/test/trackingUI/trackingPage.html [browser_protections_UI.js] fail-if = fission # Bug 1590696 diff --git a/browser/base/content/test/trackingUI/cookieServer.sjs b/browser/base/content/test/trackingUI/cookieServer.sjs index 91e30de0c10d..4c84df3922e3 100644 --- a/browser/base/content/test/trackingUI/cookieServer.sjs +++ b/browser/base/content/test/trackingUI/cookieServer.sjs @@ -2,19 +2,8 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -// A 1x1 PNG image. -// Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain) -const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" + - "ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII="); - function handleRequest(request, response) { response.setStatusLine(request.httpVersion, 200); - if (request.queryString && - request.queryString.includes("type=image-no-cookie")) { - response.setHeader("Content-Type", "image/png", false); - response.write(IMAGE); - } else { - response.setHeader("Set-Cookie", "foopy=1"); - response.write("cookie served"); - } + response.setHeader("Set-Cookie", "foopy=1"); + response.write("cookie served"); } diff --git a/browser/base/content/test/trackingUI/trackingAPI.js b/browser/base/content/test/trackingUI/trackingAPI.js index c0403da81beb..d36c0cac0622 100644 --- a/browser/base/content/test/trackingUI/trackingAPI.js +++ b/browser/base/content/test/trackingUI/trackingAPI.js @@ -4,15 +4,6 @@ function createIframe(src) { document.body.appendChild(ifr); } -function createImage(src) { - let img = document.createElement("img"); - img.src = src; - img.onload = () => { - parent.postMessage("done", "*"); - }; - document.body.appendChild(img); -} - onmessage = event => { switch (event.data) { case "tracking": @@ -50,11 +41,6 @@ onmessage = event => { "https://test1.example.org/browser/browser/base/content/test/trackingUI/cookieServer.sjs" ); break; - case "image": - createImage( - "http://trackertest.org/browser/browser/base/content/test/trackingUI/cookieServer.sjs?type=image-no-cookie" - ); - break; case "window-open": window.win = window.open( "http://trackertest.org/browser/browser/base/content/test/trackingUI/cookieServer.sjs", diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 03eb8610433a..b0f18ae4ddee 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -5787,11 +5787,13 @@ mozilla::ipc::IPCResult ContentParent::RecvAutomaticStorageAccessCanBeGranted( mozilla::ipc::IPCResult ContentParent::RecvFirstPartyStorageAccessGrantedForOrigin( const Principal& aParentPrincipal, const Principal& aTrackingPrincipal, - const nsCString& aTrackingOrigin, const int& aAllowMode, + const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin, + const int& aAllowMode, FirstPartyStorageAccessGrantedForOriginResolver&& aResolver) { AntiTrackingCommon:: SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess( - aParentPrincipal, aTrackingPrincipal, aTrackingOrigin, aAllowMode) + aParentPrincipal, aTrackingPrincipal, aTrackingOrigin, aGrantedOrigin, + aAllowMode) ->Then(GetCurrentThreadSerialEventTarget(), __func__, [aResolver = std::move(aResolver)]( AntiTrackingCommon::FirstPartyStorageAccessGrantPromise:: diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 3d609f119b57..6b06a653127b 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -1198,7 +1198,8 @@ class ContentParent final mozilla::ipc::IPCResult RecvFirstPartyStorageAccessGrantedForOrigin( const Principal& aParentPrincipal, const Principal& aTrackingPrincipal, - const nsCString& aTrackingOrigin, const int& aAllowMode, + const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin, + const int& aAllowMode, FirstPartyStorageAccessGrantedForOriginResolver&& aResolver); mozilla::ipc::IPCResult RecvStoreUserInteractionAsPermission( diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 2a378abee833..4c67ff092bde 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -1490,6 +1490,7 @@ parent: async FirstPartyStorageAccessGrantedForOrigin(Principal aParentPrincipal, Principal aTrackingPrincipal, nsCString aTrackingOrigin, + nsCString aGrantedOrigin, int aAllowMode) returns (bool unused); diff --git a/extensions/permissions/nsPermissionManager.cpp b/extensions/permissions/nsPermissionManager.cpp index 105ec3b4935d..d0c19b12e545 100644 --- a/extensions/permissions/nsPermissionManager.cpp +++ b/extensions/permissions/nsPermissionManager.cpp @@ -882,7 +882,7 @@ void nsPermissionManager::Startup() { // nsPermissionManager Implementation #define PERMISSIONS_FILE_NAME "permissions.sqlite" -#define HOSTS_SCHEMA_VERSION 11 +#define HOSTS_SCHEMA_VERSION 10 // Default permissions are read from a URL - this is the preference we read // to find that URL. If not set, don't use any default permissions. @@ -1539,25 +1539,6 @@ nsresult nsPermissionManager::InitDB(bool aRemoveFile) { MOZ_FALLTHROUGH; case 9: { - rv = mDBConn->SetSchemaVersion(10); - NS_ENSURE_SUCCESS(rv, rv); - } - - // fall through to the next upgrade - MOZ_FALLTHROUGH; - - case 10: { - // Filter out the rows with storage access API permissions with a - // granted origin, and remove the granted origin part from the - // permission type. - rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( - "UPDATE moz_perms " - "SET type=SUBSTR(type, 0, INSTR(SUBSTR(type, INSTR(type, '^') + " - "1), '^') + INSTR(type, '^')) " - "WHERE INSTR(SUBSTR(type, INSTR(type, '^') + 1), '^') AND " - "SUBSTR(type, 0, 18) == \"storageAccessAPI^\";")); - NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js b/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js index a2d57f2321af..f2464a358874 100644 --- a/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js +++ b/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js @@ -223,9 +223,9 @@ function run_test() { // Initialize the permission manager service var pm = Services.perms; - // The schema should be upgraded to 11, and a 'modificationTime' column should + // The schema should be upgraded to 10, and a 'modificationTime' column should // exist with all records having a value of 0. - Assert.equal(connection.schemaVersion, 11); + Assert.equal(connection.schemaVersion, 10); let select = connection.createStatement( "SELECT modificationTime FROM moz_perms" diff --git a/extensions/permissions/test/unit/test_permmanager_migrate_10-11.js b/extensions/permissions/test/unit/test_permmanager_migrate_10-11.js deleted file mode 100644 index 5ba1d66f7299..000000000000 --- a/extensions/permissions/test/unit/test_permmanager_migrate_10-11.js +++ /dev/null @@ -1,193 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -ChromeUtils.defineModuleGetter( - this, - "PlacesTestUtils", - "resource://testing-common/PlacesTestUtils.jsm" -); - -var PERMISSIONS_FILE_NAME = "permissions.sqlite"; - -function GetPermissionsFile(profile) { - let file = profile.clone(); - file.append(PERMISSIONS_FILE_NAME); - return file; -} - -add_task(async function test() { - /* Create and set up the permissions database */ - let profile = do_get_profile(); - Services.prefs.setCharPref("permissions.manager.defaultsUrl", ""); - - let db = Services.storage.openDatabase(GetPermissionsFile(profile)); - db.schemaVersion = 10; - - let stmt6Insert = db.createStatement( - "INSERT INTO moz_perms (" + - "id, origin, type, permission, expireType, expireTime, modificationTime" + - ") VALUES (" + - ":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" + - ")" - ); - - let id = 0; - - function insertOrigin( - origin, - type, - permission, - expireType, - expireTime, - modificationTime - ) { - let thisId = id++; - - stmt6Insert.bindByName("id", thisId); - stmt6Insert.bindByName("origin", origin); - stmt6Insert.bindByName("type", type); - stmt6Insert.bindByName("permission", permission); - stmt6Insert.bindByName("expireType", expireType); - stmt6Insert.bindByName("expireTime", expireTime); - stmt6Insert.bindByName("modificationTime", modificationTime); - - try { - stmt6Insert.execute(); - } finally { - stmt6Insert.reset(); - } - - return { - id: thisId, - origin, - type, - permission, - expireType, - expireTime, - modificationTime, - }; - } - - insertOrigin( - "https://foo.com", - "storageAccessAPI^https://foo.com", - 2, - 0, - 0, - 0 - ); - insertOrigin( - "http://foo.com", - "storageAccessAPI^https://bar.com^https://foo.com", - 2, - 0, - 0, - 0 - ); - insertOrigin( - "http://foo.com", - "storageAccessAPI^https://bar.com^https://baz.com", - 2, - 0, - 0, - 0 - ); - insertOrigin("http://foo.com^inBrowser=1", "A", 2, 0, 0, 0); - - // CLose the db connection - stmt6Insert.finalize(); - db.close(); - db = null; - - let expected = [ - ["https://foo.com", "storageAccessAPI^https://foo.com", 2, 0, 0, 0], - ["http://foo.com", "storageAccessAPI^https://bar.com", 2, 0, 0, 0], - ["http://foo.com", "storageAccessAPI^https://bar.com", 2, 0, 0, 0], - ["http://foo.com^inBrowser=1", "A", 2, 0, 0, 0], - ]; - - let found = expected.map(it => 0); - - // Add some places to the places database - await PlacesTestUtils.addVisits( - Services.io.newURI("https://foo.com/some/other/subdirectory") - ); - await PlacesTestUtils.addVisits( - Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory") - ); - await PlacesTestUtils.addVisits(Services.io.newURI("ftp://127.0.0.1:8080")); - await PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080")); - - // This will force the permission-manager to reload the data. - Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); - - // Force initialization of the nsPermissionManager - for (let permission of Services.perms.all) { - let isExpected = false; - - expected.forEach((it, i) => { - if ( - permission.principal.origin == it[0] && - permission.type == it[1] && - permission.capability == it[2] && - permission.expireType == it[3] && - permission.expireTime == it[4] - ) { - isExpected = true; - found[i]++; - } - }); - - Assert.ok( - isExpected, - "Permission " + - (isExpected ? "should" : "shouldn't") + - " be in permission database: " + - permission.principal.origin + - ", " + - permission.type + - ", " + - permission.capability + - ", " + - permission.expireType + - ", " + - permission.expireTime - ); - } - - found.forEach((count, i) => { - Assert.ok( - count == 1, - "Expected count = 1, got count = " + - count + - " for permission " + - expected[i] - ); - }); - - // Check to make sure that all of the tables which we care about are present - { - db = Services.storage.openDatabase(GetPermissionsFile(profile)); - Assert.ok(db.tableExists("moz_perms")); - Assert.ok(db.tableExists("moz_hosts")); - Assert.ok(!db.tableExists("moz_perms_v6")); - - let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts"); - try { - mozHostsCount.executeStep(); - Assert.equal(mozHostsCount.getInt64(0), 0); - } finally { - mozHostsCount.finalize(); - } - - let mozPermsCount = db.createStatement("SELECT count(*) FROM moz_perms"); - try { - mozPermsCount.executeStep(); - Assert.equal(mozPermsCount.getInt64(0), expected.length); - } finally { - mozPermsCount.finalize(); - } - - db.close(); - } -}); diff --git a/extensions/permissions/test/unit/xpcshell.ini b/extensions/permissions/test/unit/xpcshell.ini index e76da217824a..ae9c8cc70e11 100644 --- a/extensions/permissions/test/unit/xpcshell.ini +++ b/extensions/permissions/test/unit/xpcshell.ini @@ -30,5 +30,4 @@ skip-if = debug == true [test_permmanager_migrate_4-7_no_history.js] [test_permmanager_migrate_7-8.js] [test_permmanager_migrate_9-10.js] -[test_permmanager_migrate_10-11.js] [test_permmanager_oa_strip.js] diff --git a/netwerk/locales/en-US/necko.properties b/netwerk/locales/en-US/necko.properties index 4b2c2fa9cbf4..dbb88c0190c7 100644 --- a/netwerk/locales/en-US/necko.properties +++ b/netwerk/locales/en-US/necko.properties @@ -44,7 +44,11 @@ CookieBlockedTracker=Request to access cookie or storage on “%1$S” was block CookieBlockedAll=Request to access cookie or storage on “%1$S” was blocked because we are blocking all storage access requests. CookieBlockedForeign=Request to access cookie or storage on “%1$S” was blocked because we are blocking all third-party storage access requests and content blocking is enabled. +# LOCALIZATION NOTE (CookieAllowedForOriginOnTrackerByStorageAccessAPI): %3$S, %2$S and %1$S are URLs. +CookieAllowedForOriginOnTrackerByStorageAccessAPI=Storage access granted for “%3$S” opened by tracker “%2$S” on “%1$S”. # LOCALIZATION NOTE (CookieAllowedForTrackerByStorageAccessAPI): %2$S and %1$S are URLs. CookieAllowedForTrackerByStorageAccessAPI=Storage access granted for tracker “%2$S” on “%1$S”. +# LOCALIZATION NOTE (CookieAllowedForOriginOnTrackerByHeuristic): %3$S, %2$S and %1$S are URLs. +CookieAllowedForOriginOnTrackerByHeuristic=Storage access automatically granted for “%3$S” opened by tracker “%2$S” on “%1$S”. # LOCALIZATION NOTE (CookieAllowedForTrackerByHeuristic): %2$S and %1$S are URLs. CookieAllowedForTrackerByHeuristic=Storage access automatically granted for tracker “%2$S” on “%1$S”. diff --git a/toolkit/components/antitracking/AntiTrackingCommon.cpp b/toolkit/components/antitracking/AntiTrackingCommon.cpp index c338419f8525..aef59c4ac8eb 100644 --- a/toolkit/components/antitracking/AntiTrackingCommon.cpp +++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp @@ -128,6 +128,27 @@ void CreatePermissionKey(const nsCString& aTrackingOrigin, aPermissionKey.Append(aTrackingOrigin); } +void CreatePermissionKey(const nsCString& aTrackingOrigin, + const nsCString& aGrantedOrigin, + nsACString& aPermissionKey) { + MOZ_ASSERT(aPermissionKey.IsEmpty()); + + if (aTrackingOrigin == aGrantedOrigin) { + CreatePermissionKey(aTrackingOrigin, aPermissionKey); + return; + } + + static const nsLiteralCString prefix = + NS_LITERAL_CSTRING(ANTITRACKING_PERM_KEY "^"); + + aPermissionKey.SetCapacity(prefix.Length() + 1 + aTrackingOrigin.Length() + + aGrantedOrigin.Length()); + aPermissionKey.Append(prefix); + aPermissionKey.Append(aTrackingOrigin); + aPermissionKey.AppendLiteral("^"); + aPermissionKey.Append(aGrantedOrigin); +} + // This internal method returns ACCESS_DENY if the access is denied, // ACCESS_DEFAULT if unknown, some other access code if granted. uint32_t CheckCookiePermissionForPrincipal(nsICookieSettings* aCookieSettings, @@ -443,6 +464,7 @@ void ReportBlockingToConsole(nsPIDOMWindowOuter* aWindow, nsIURI* aURI, void ReportUnblockingToConsole( nsPIDOMWindowInner* aWindow, const nsAString& aTrackingOrigin, + const nsAString& aGrantedOrigin, AntiTrackingCommon::StorageAccessGrantedReason aReason) { nsCOMPtr principal = nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); @@ -456,6 +478,7 @@ void ReportUnblockingToConsole( } nsAutoString trackingOrigin(aTrackingOrigin); + nsAutoString grantedOrigin(aGrantedOrigin); nsAutoString sourceLine; uint32_t lineNumber = 0, columnNumber = 0; @@ -466,8 +489,8 @@ void ReportUnblockingToConsole( RefPtr runnable = NS_NewRunnableFunction( "ReportUnblockingToConsoleDelayed", - [doc, principal, trackingOrigin, sourceLine, lineNumber, columnNumber, - aReason]() { + [doc, principal, trackingOrigin, grantedOrigin, sourceLine, lineNumber, + columnNumber, aReason]() { nsAutoString origin; nsresult rv = nsContentUtils::GetUTFOrigin(principal, origin); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -476,24 +499,39 @@ void ReportUnblockingToConsole( // Not adding grantedOrigin yet because we may not want it later. AutoTArray params = {origin, trackingOrigin}; + const char* messageWithDifferentOrigin = nullptr; const char* messageWithSameOrigin = nullptr; switch (aReason) { case AntiTrackingCommon::eStorageAccessAPI: + messageWithDifferentOrigin = + "CookieAllowedForOriginOnTrackerByStorageAccessAPI"; messageWithSameOrigin = "CookieAllowedForTrackerByStorageAccessAPI"; break; case AntiTrackingCommon::eOpenerAfterUserInteraction: MOZ_FALLTHROUGH; case AntiTrackingCommon::eOpener: + messageWithDifferentOrigin = + "CookieAllowedForOriginOnTrackerByHeuristic"; messageWithSameOrigin = "CookieAllowedForTrackerByHeuristic"; break; } - nsContentUtils::ReportToConsole( - nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Content Blocking"), - doc, nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin, - params, nullptr, sourceLine, lineNumber, columnNumber); + if (trackingOrigin == grantedOrigin) { + nsContentUtils::ReportToConsole( + nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("Content Blocking"), doc, + nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin, params, + nullptr, sourceLine, lineNumber, columnNumber); + } else { + params.AppendElement(grantedOrigin); + nsContentUtils::ReportToConsole( + nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("Content Blocking"), doc, + nsContentUtils::eNECKO_PROPERTIES, messageWithDifferentOrigin, + params, nullptr, sourceLine, lineNumber, columnNumber); + } }); RunConsoleReportingRunnable(runnable.forget()); @@ -905,13 +943,16 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor( return StorageAccessGrantPromise::CreateAndReject(false, __func__); } - if (MOZ_LOG_TEST(gAntiTrackingLog, mozilla::LogLevel::Debug)) { - nsAutoCString origin; - Unused << nsContentUtils::GetASCIIOrigin(uri, origin); - LOG(("Adding a first-party storage exception for %s...", - PromiseFlatCString(origin).get())); + nsAutoCString origin; + nsresult rv = nsContentUtils::GetASCIIOrigin(uri, origin); + if (NS_WARN_IF(NS_FAILED(rv))) { + LOG(("Can't get the origin from the URI")); + return StorageAccessGrantPromise::CreateAndReject(false, __func__); } + LOG(("Adding a first-party storage exception for %s...", + PromiseFlatCString(origin).get())); + Document* parentDoc = aParentWindow->GetExtantDoc(); if (!parentDoc) { LOG(("Parent window has no doc")); @@ -955,13 +996,6 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor( // We are a first party resource. if (outerParentWindow->IsTopLevelWindow()) { - nsAutoCString origin; - nsresult rv = nsContentUtils::GetASCIIOrigin(uri, origin); - if (NS_WARN_IF(NS_FAILED(rv))) { - LOG(("Can't get the origin from the URI")); - return StorageAccessGrantPromise::CreateAndReject(false, __func__); - } - trackingOrigin = origin; trackingPrincipal = aPrincipal; rv = trackingPrincipal->GetURI(getter_AddRefs(trackingURI)); @@ -1064,11 +1098,11 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor( } auto storePermission = - [pwin, parentWindow, trackingOrigin, trackingPrincipal, trackingURI, - topInnerWindow, topLevelStoragePrincipal, + [pwin, parentWindow, origin, trackingOrigin, trackingPrincipal, + trackingURI, topInnerWindow, topLevelStoragePrincipal, aReason](int aAllowMode) -> RefPtr { nsAutoCString permissionKey; - CreatePermissionKey(trackingOrigin, permissionKey); + CreatePermissionKey(trackingOrigin, origin, permissionKey); // Let's store the permission in the current parent window. topInnerWindow->SaveStorageAccessGranted(permissionKey); @@ -1084,14 +1118,16 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor( Some(aReason)); ReportUnblockingToConsole(parentWindow, - NS_ConvertUTF8toUTF16(trackingOrigin), aReason); + NS_ConvertUTF8toUTF16(trackingOrigin), + NS_ConvertUTF8toUTF16(origin), aReason); if (XRE_IsParentProcess()) { - LOG(("Saving the permission: trackingOrigin=%s", trackingOrigin.get())); + LOG(("Saving the permission: trackingOrigin=%s, grantedOrigin=%s", + trackingOrigin.get(), origin.get())); return SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess( topLevelStoragePrincipal, trackingPrincipal, trackingOrigin, - aAllowMode) + origin, aAllowMode) ->Then(GetCurrentThreadSerialEventTarget(), __func__, [](FirstPartyStorageAccessGrantPromise::ResolveOrRejectValue&& aValue) { @@ -1109,15 +1145,16 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor( LOG( ("Asking the parent process to save the permission for us: " - "trackingOrigin=%s", - trackingOrigin.get())); + "trackingOrigin=%s, grantedOrigin=%s", + trackingOrigin.get(), origin.get())); // This is not really secure, because here we have the content process // sending the request of storing a permission. return cc ->SendFirstPartyStorageAccessGrantedForOrigin( IPC::Principal(topLevelStoragePrincipal), - IPC::Principal(trackingPrincipal), trackingOrigin, aAllowMode) + IPC::Principal(trackingPrincipal), trackingOrigin, origin, + aAllowMode) ->Then(GetCurrentThreadSerialEventTarget(), __func__, [](const ContentChild:: FirstPartyStorageAccessGrantedForOriginPromise:: @@ -1149,7 +1186,8 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor( RefPtr AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess( nsIPrincipal* aParentPrincipal, nsIPrincipal* aTrackingPrincipal, - const nsCString& aTrackingOrigin, int aAllowMode) { + const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin, + int aAllowMode) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aAllowMode == eAllow || aAllowMode == eAllowAutoGrant); @@ -1162,8 +1200,8 @@ AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess( nsCOMPtr parentPrincipalURI; Unused << aParentPrincipal->GetURI(getter_AddRefs(parentPrincipalURI)); LOG_SPEC(("Saving a first-party storage permission on %s for " - "trackingOrigin=%s", - _spec, aTrackingOrigin.get()), + "trackingOrigin=%s grantedOrigin=%s", + _spec, aTrackingOrigin.get(), aGrantedOrigin.get()), parentPrincipalURI); if (NS_WARN_IF(!aParentPrincipal)) { @@ -1198,7 +1236,7 @@ AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess( } nsAutoCString type; - CreatePermissionKey(aTrackingOrigin, type); + CreatePermissionKey(aTrackingOrigin, aGrantedOrigin, type); LOG( ("Computed permission key: %s, expiry: %u, proceeding to save in the " @@ -1461,8 +1499,15 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor( } Unused << parentPrincipal->GetURI(getter_AddRefs(parentPrincipalURI)); + nsAutoCString grantedOrigin; + nsresult rv = nsContentUtils::GetASCIIOrigin(aURI, grantedOrigin); + if (NS_WARN_IF(NS_FAILED(rv))) { + LOG_SPEC(("Failed to compute the origin from %s", _spec), aURI); + return false; + } + nsAutoCString type; - CreatePermissionKey(trackingOrigin, type); + CreatePermissionKey(trackingOrigin, grantedOrigin, type); if (topInnerWindow->HasStorageAccessGranted(type)) { LOG(("Permission stored in the window. All good.")); @@ -1728,8 +1773,15 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor( return false; } + nsAutoCString origin; + rv = nsContentUtils::GetASCIIOrigin(aURI, origin); + if (NS_WARN_IF(NS_FAILED(rv))) { + LOG_SPEC(("Failed to compute the origin from %s", _spec), aURI); + return false; + } + nsAutoCString type; - CreatePermissionKey(trackingOrigin, type); + CreatePermissionKey(trackingOrigin, origin, type); uint32_t privateBrowsingId = 0; rv = channelPrincipal->GetPrivateBrowsingId(&privateBrowsingId); diff --git a/toolkit/components/antitracking/AntiTrackingCommon.h b/toolkit/components/antitracking/AntiTrackingCommon.h index 4ffc1e75d04a..3e5beb8a13db 100644 --- a/toolkit/components/antitracking/AntiTrackingCommon.h +++ b/toolkit/components/antitracking/AntiTrackingCommon.h @@ -130,7 +130,8 @@ class AntiTrackingCommon final { static RefPtr SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess( nsIPrincipal* aPrincipal, nsIPrincipal* aTrackingPrinciapl, - const nsCString& aTrackingOrigin, int aAllowMode); + const nsCString& aParentOrigin, const nsCString& aGrantedOrigin, + int aAllowMode); // Check whether a top window principal is on the content blocking allow list. static nsresult IsOnContentBlockingAllowList(nsIPrincipal* aTopWinPrincipal, diff --git a/toolkit/components/antitracking/test/browser/antitracking_head.js b/toolkit/components/antitracking/test/browser/antitracking_head.js index 18edba7080c6..aaf11136ef4e 100644 --- a/toolkit/components/antitracking/test/browser/antitracking_head.js +++ b/toolkit/components/antitracking/test/browser/antitracking_head.js @@ -696,31 +696,13 @@ this.AntiTracking = { is(allMessages.length, 0, "No console messages should be generated"); } else { ok(!!allMessages.length, "Some console message should be generated"); - if (options.errorMessageDomains) { - is( - allMessages.length, - options.errorMessageDomains.length, - "Enough items provided in errorMessageDomains" - ); - } } - let index = 0; for (let msg of allMessages) { is( msg.category, expectedCategory, "Message should be of expected category" ); - - if (options.errorMessageDomains) { - ok( - msg.errorMessage.includes(options.errorMessageDomains[index]), - `Error message domain ${ - options.errorMessageDomains[index] - } (${index}) found in "${msg.errorMessage}"` - ); - index++; - } } if (options.allowList) { diff --git a/toolkit/components/antitracking/test/browser/browser.ini b/toolkit/components/antitracking/test/browser/browser.ini index ca154e216ea2..5adc8b408a14 100644 --- a/toolkit/components/antitracking/test/browser/browser.ini +++ b/toolkit/components/antitracking/test/browser/browser.ini @@ -39,9 +39,6 @@ support-files = raptor.jpg !/browser/modules/test/browser/head.js !/browser/base/content/test/general/head.js - !/browser/base/content/test/trackingUI/cookieServer.sjs - !/browser/base/content/test/trackingUI/trackingPage.html - !/browser/base/content/test/trackingUI/trackingAPI.js [browser_allowListNotifications.js] support-files = subResources.sjs @@ -112,8 +109,6 @@ skip-if = fission skip-if = fission [browser_storageAccessSandboxed.js] skip-if = fission -[browser_storageAccessThirdPartyChecks.js] -skip-if = fission [browser_storageAccessWithHeuristics.js] skip-if = fission [browser_networkIsolation.js] diff --git a/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks.js b/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks.js deleted file mode 100644 index 3abcbe3a84b2..000000000000 --- a/toolkit/components/antitracking/test/browser/browser_storageAccessThirdPartyChecks.js +++ /dev/null @@ -1,63 +0,0 @@ -/* import-globals-from antitracking_head.js */ - -AntiTracking._createTask({ - name: - "Test that after a storage access grant we have full first-party access", - cookieBehavior: BEHAVIOR_REJECT_TRACKER, - blockingByContentBlockingRTUI: true, - allowList: false, - callback: async _ => { - /* import-globals-from storageAccessAPIHelpers.js */ - await noStorageAccessInitially(); - - await callRequestStorageAccess(); - - const TRACKING_PAGE = - "http://another-tracking.example.net/browser/browser/base/content/test/trackingUI/trackingPage.html"; - async function runChecks(name) { - let iframe = document.createElement("iframe"); - iframe.src = TRACKING_PAGE; - document.body.appendChild(iframe); - await new Promise(resolve => { - iframe.onload = resolve; - }); - - await SpecialPowers.spawn(iframe, [name], name => { - content.postMessage(name, "*"); - }); - - await new Promise(resolve => { - onmessage = e => { - if (e.data == "done") { - resolve(); - } - }; - }); - } - - await runChecks("image"); - }, - extraPrefs: null, - expectedBlockingNotifications: - Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER, - runInPrivateWindow: false, - iframeSandbox: null, - accessRemoval: null, - callbackAfterRemoval: null, - thirdPartyPage: TEST_3RD_PARTY_PAGE_HTTP, - errorMessageDomains: [ - "http://tracking.example.org", - "http://tracking.example.org", - "http://tracking.example.org", - "http://tracking.example.org", - "http://tracking.example.org", - ], -}); - -add_task(async _ => { - await new Promise(resolve => { - Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => - resolve() - ); - }); -}); diff --git a/toolkit/components/antitracking/test/browser/head.js b/toolkit/components/antitracking/test/browser/head.js index 29b0c5cd0662..84d35ee1072b 100644 --- a/toolkit/components/antitracking/test/browser/head.js +++ b/toolkit/components/antitracking/test/browser/head.js @@ -29,8 +29,6 @@ const TEST_TOP_PAGE_6 = TEST_DOMAIN_6 + TEST_PATH + "page.html"; const TEST_EMBEDDER_PAGE = TEST_DOMAIN + TEST_PATH + "embedder.html"; const TEST_POPUP_PAGE = TEST_DOMAIN + TEST_PATH + "popup.html"; const TEST_3RD_PARTY_PAGE = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdParty.html"; -const TEST_3RD_PARTY_PAGE_HTTP = - TEST_3RD_PARTY_DOMAIN_HTTP + TEST_PATH + "3rdParty.html"; const TEST_3RD_PARTY_PAGE_WO = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdPartyWO.html"; const TEST_3RD_PARTY_PAGE_UI = diff --git a/toolkit/components/cleardata/ClearDataService.jsm b/toolkit/components/cleardata/ClearDataService.jsm index 54b17e6bfb93..2fc2637e1ced 100644 --- a/toolkit/components/cleardata/ClearDataService.jsm +++ b/toolkit/components/cleardata/ClearDataService.jsm @@ -879,14 +879,19 @@ const PermissionsCleaner = { if (!toBeRemoved && perm.type.startsWith("3rdPartyStorage^")) { let parts = perm.type.split("^"); - let uri; - try { - uri = Services.io.newURI(parts[1]); - } catch (ex) { - continue; - } + for (let i = 1; i < parts.length; ++i) { + let uri; + try { + uri = Services.io.newURI(parts[i]); + } catch (ex) { + continue; + } - toBeRemoved = Services.eTLD.hasRootDomain(uri.host, aHost); + toBeRemoved = Services.eTLD.hasRootDomain(uri.host, aHost); + if (toBeRemoved) { + break; + } + } } if (!toBeRemoved) { diff --git a/toolkit/components/cleardata/tests/unit/test_permissions.js b/toolkit/components/cleardata/tests/unit/test_permissions.js index 52f33d144369..d64b6f76885e 100644 --- a/toolkit/components/cleardata/tests/unit/test_permissions.js +++ b/toolkit/components/cleardata/tests/unit/test_permissions.js @@ -133,6 +133,16 @@ add_task(async function test_3rdpartystorage_permissions() { "cookie", Services.perms.ALLOW_ACTION ); + Services.perms.addFromPrincipal( + oneMorePrincipal, + "3rdPartyStorage^https://example.net^https://example.org", + Services.perms.ALLOW_ACTION + ); + Services.perms.addFromPrincipal( + oneMorePrincipal, + "3rdPartyStorage^https://example.org^https://example.net", + Services.perms.ALLOW_ACTION + ); Assert.ok( Services.perms.getPermissionObject(principal, "cookie", true) != null @@ -150,6 +160,20 @@ add_task(async function test_3rdpartystorage_permissions() { Assert.ok( Services.perms.getPermissionObject(oneMorePrincipal, "cookie", true) != null ); + Assert.ok( + Services.perms.getPermissionObject( + oneMorePrincipal, + "3rdPartyStorage^https://example.net^https://example.org", + true + ) != null + ); + Assert.ok( + Services.perms.getPermissionObject( + oneMorePrincipal, + "3rdPartyStorage^https://example.org^https://example.net", + true + ) != null + ); await new Promise(aResolve => { Services.clearData.deleteDataFromPrincipal( @@ -179,6 +203,20 @@ add_task(async function test_3rdpartystorage_permissions() { Assert.ok( Services.perms.getPermissionObject(oneMorePrincipal, "cookie", true) != null ); + Assert.ok( + Services.perms.getPermissionObject( + oneMorePrincipal, + "3rdPartyStorage^https://example.net^https://example.org", + true + ) == null + ); + Assert.ok( + Services.perms.getPermissionObject( + oneMorePrincipal, + "3rdPartyStorage^https://example.org^https://example.net", + true + ) == null + ); await new Promise(aResolve => { Services.clearData.deleteData(