From def92d1b8e9d373e2f6f27c366d578d97d8960c6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:34:50 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- .../components/cleardata/ClearDataService.sys.mjs | 100 ++++++-- .../cleardata/PrincipalsCollector.sys.mjs | 8 +- .../components/cleardata/SiteDataTestUtils.sys.mjs | 8 +- .../components/cleardata/nsIClearDataService.idl | 28 ++- .../cleardata/tests/browser/browser.toml | 3 - .../cleardata/tests/browser/browser_css_cache.js | 1 + .../cleardata/tests/browser/browser_image_cache.js | 2 + .../tests/browser/browser_preflight_cache.js | 8 +- .../test_moved_origin_directory_cleanup.py | 9 + .../cleardata/tests/unit/test_permissions.js | 4 +- .../tests/unit/test_storage_permission.js | 8 +- .../tests/unit/test_storage_permission_clearing.js | 271 +++++++++++++++++++++ .../components/cleardata/tests/unit/xpcshell.toml | 2 + 13 files changed, 405 insertions(+), 47 deletions(-) create mode 100644 toolkit/components/cleardata/tests/unit/test_storage_permission_clearing.js (limited to 'toolkit/components/cleardata') diff --git a/toolkit/components/cleardata/ClearDataService.sys.mjs b/toolkit/components/cleardata/ClearDataService.sys.mjs index ba34558f7e..5df5c03f58 100644 --- a/toolkit/components/cleardata/ClearDataService.sys.mjs +++ b/toolkit/components/cleardata/ClearDataService.sys.mjs @@ -193,7 +193,7 @@ const CookieCleaner = { }); }, - deleteByRange(aFrom, aTo) { + deleteByRange(aFrom) { return Services.cookies.removeAllSince(aFrom); }, @@ -584,7 +584,7 @@ const DownloadsCleaner = { }; const PasswordsCleaner = { - deleteByHost(aHost, aOriginAttributes) { + deleteByHost(aHost) { // Clearing by host also clears associated subdomains. return this._deleteInternal(aLogin => Services.eTLD.hasRootDomain(aLogin.hostname, aHost) @@ -630,7 +630,7 @@ const PasswordsCleaner = { }; const MediaDevicesCleaner = { - async deleteByRange(aFrom, aTo) { + async deleteByRange(aFrom) { let mediaMgr = Cc["@mozilla.org/mediaManagerService;1"].getService( Ci.nsIMediaManagerService ); @@ -799,7 +799,7 @@ const QuotaCleaner = { } }, - async deleteByHost(aHost, aOriginAttributes) { + async deleteByHost(aHost) { // XXX: The aOriginAttributes is expected to always be empty({}). Maybe have // a debug assertion here to ensure that? @@ -872,7 +872,7 @@ const QuotaCleaner = { _ => /* exceptionThrown = */ false, _ => /* exceptionThrown = */ true ) - .then(exceptionThrown => { + .then(() => { // QuotaManager: In the event of a failure, we call reject to propagate // the error upwards. return new Promise((aResolve, aReject) => { @@ -1002,7 +1002,7 @@ const PushNotificationsCleaner = { }); }, - deleteByHost(aHost, aOriginAttributes) { + deleteByHost(aHost) { // Will also clear entries for subdomains of aHost. Data is cleared across // all origin attributes. return this._deleteByRootDomain(aHost); @@ -1078,7 +1078,7 @@ const StorageAccessCleaner = { }); }, - async deleteByHost(aHost, aOriginAttributes) { + async deleteByHost(aHost) { // Clearing by host also clears associated subdomains. this._deleteInternal(({ principal }) => { let toBeRemoved = false; @@ -1095,7 +1095,7 @@ const StorageAccessCleaner = { ); }, - async deleteByRange(aFrom, aTo) { + async deleteByRange(aFrom) { Services.perms.removeByTypeSince("storageAccessAPI", aFrom / 1000); }, @@ -1105,7 +1105,7 @@ const StorageAccessCleaner = { }; const HistoryCleaner = { - deleteByHost(aHost, aOriginAttributes) { + deleteByHost(aHost) { if (!AppConstants.MOZ_PLACES) { return Promise.resolve(); } @@ -1142,7 +1142,7 @@ const HistoryCleaner = { }; const SessionHistoryCleaner = { - async deleteByHost(aHost, aOriginAttributes) { + async deleteByHost(aHost) { // Session storage and history also clear subdomains of aHost. Services.obs.notifyObservers(null, "browser:purge-sessionStorage", aHost); Services.obs.notifyObservers( @@ -1160,7 +1160,7 @@ const SessionHistoryCleaner = { return this.deleteByHost(aBaseDomain, {}); }, - async deleteByRange(aFrom, aTo) { + async deleteByRange(aFrom) { Services.obs.notifyObservers( null, "browser:purge-session-history", @@ -1275,7 +1275,7 @@ const PermissionsCleaner = { } }, - deleteByHost(aHost, aOriginAttributes) { + deleteByHost(aHost) { return this._deleteInternal({ host: aHost }); }, @@ -1287,7 +1287,7 @@ const PermissionsCleaner = { return this._deleteInternal({ baseDomain: aBaseDomain }); }, - async deleteByRange(aFrom, aTo) { + async deleteByRange(aFrom) { Services.perms.removeAllSince(aFrom / 1000); }, @@ -1301,7 +1301,7 @@ const PermissionsCleaner = { }; const PreferencesCleaner = { - deleteByHost(aHost, aOriginAttributes) { + deleteByHost(aHost) { // Also clears subdomains of aHost. return new Promise((aResolve, aReject) => { let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService( @@ -1328,7 +1328,7 @@ const PreferencesCleaner = { return this.deleteByHost(aBaseDomain, {}); }, - async deleteByRange(aFrom, aTo) { + async deleteByRange(aFrom) { let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService( Ci.nsIContentPrefService2 ); @@ -1477,7 +1477,7 @@ const EMECleaner = { }; const ReportsCleaner = { - deleteByHost(aHost, aOriginAttributes) { + deleteByHost(aHost) { // Also clears subdomains of aHost. return new Promise(aResolve => { Services.obs.notifyObservers(null, "reporting:purge-host", aHost); @@ -1520,7 +1520,7 @@ const ContentBlockingCleaner = { await this.deleteAll(); }, - deleteByRange(aFrom, aTo) { + deleteByRange(aFrom) { return lazy.TrackingDBService.clearSince(aFrom); }, }; @@ -1616,7 +1616,7 @@ const IdentityCredentialStorageCleaner = { } }, - async deleteByPrincipal(aPrincipal, aIsUserRequest) { + async deleteByPrincipal(aPrincipal) { if ( Services.prefs.getBoolPref( "dom.security.credentialmanagement.identity.enabled", @@ -1698,7 +1698,7 @@ const BounceTrackingProtectionStateCleaner = { await lazy.bounceTrackingProtection.clearAll(); }, - async deleteByPrincipal(aPrincipal, aIsUserRequest) { + async deleteByPrincipal(aPrincipal) { if (!lazy.isBounceTrackingProtectionEnabled) { return; } @@ -1709,7 +1709,7 @@ const BounceTrackingProtectionStateCleaner = { ); }, - async deleteByBaseDomain(aBaseDomain, aIsUserRequest) { + async deleteByBaseDomain(aBaseDomain) { if (!lazy.isBounceTrackingProtectionEnabled) { return; } @@ -1723,7 +1723,7 @@ const BounceTrackingProtectionStateCleaner = { await lazy.bounceTrackingProtection.clearByTimeRange(aFrom, aTo); }, - async deleteByHost(aHost, aOriginAttributes) { + async deleteByHost(aHost) { if (!lazy.isBounceTrackingProtectionEnabled) { return; } @@ -1741,6 +1741,59 @@ const BounceTrackingProtectionStateCleaner = { }, }; +const StoragePermissionsCleaner = { + async deleteByRange(aFrom) { + // We lack the ability to clear by range, but can clear from a certain time to now + // We have to divice aFrom by 1000 to convert the time from ms to microseconds + Services.perms.removeByTypeSince("storage-access", aFrom / 1000); + Services.perms.removeByTypeSince("persistent-storage", aFrom / 1000); + }, + + async deleteByPrincipal(aPrincipal) { + Services.perms.removeFromPrincipal(aPrincipal, "storage-access"); + Services.perms.removeFromPrincipal(aPrincipal, "persistent-storage"); + }, + + async deleteByHost(aHost) { + let permissions = this._getStoragePermissions(); + for (let perm of permissions) { + if (Services.eTLD.hasRootDomain(perm.principal.host, aHost)) { + Services.perms.removePermission(perm); + } + } + }, + + async deleteByBaseDomain(aBaseDomain) { + let permissions = this._getStoragePermissions(); + for (let perm of permissions) { + if (perm.principal.baseDomain == aBaseDomain) { + Services.perms.removePermission(perm); + } + } + }, + + async deleteByLocalFiles() { + let permissions = this._getStoragePermissions(); + for (let perm of permissions) { + if (perm.principal.schemeIs("file")) { + Services.perms.removePermission(perm); + } + } + }, + + async deleteAll() { + Services.perms.removeByType("storage-access"); + Services.perms.removeByType("persistent-storage"); + }, + + _getStoragePermissions() { + return Services.perms.getAllByTypes([ + "storage-access", + "persistent-storage", + ]); + }, +}; + // Here the map of Flags-Cleaners. const FLAGS_MAP = [ { @@ -1875,6 +1928,11 @@ const FLAGS_MAP = [ flag: Ci.nsIClearDataService.CLEAR_BOUNCE_TRACKING_PROTECTION_STATE, cleaners: [BounceTrackingProtectionStateCleaner], }, + + { + flag: Ci.nsIClearDataService.CLEAR_STORAGE_PERMISSIONS, + cleaners: [StoragePermissionsCleaner], + }, ]; export function ClearDataService() { diff --git a/toolkit/components/cleardata/PrincipalsCollector.sys.mjs b/toolkit/components/cleardata/PrincipalsCollector.sys.mjs index e4f5e827f6..a79da86757 100644 --- a/toolkit/components/cleardata/PrincipalsCollector.sys.mjs +++ b/toolkit/components/cleardata/PrincipalsCollector.sys.mjs @@ -66,8 +66,8 @@ export class PrincipalsCollector { /** * Fetches and collects all principals with cookies and/or site data (see module - * description). Originally for usage in Sanitizer.jsm to compute principals to be - * cleared on shutdown based on user settings. + * description). Originally for usage in Sanitizer.sys.mjs to compute principals + * to be cleared on shutdown based on user settings. * * This operation might take a while to complete on big profiles. * DO NOT call or await this in a way that makes it block user interaction, or you @@ -76,8 +76,8 @@ export class PrincipalsCollector { * This function will cache its result and return the same list on second call, * even if the actual number of principals with cookies and site data changed. * - * @param {Object} [optional] progress A Sanitizer.jsm progress object that will be - * updated to reflect the current step of fetching principals. + * @param {Object} [optional] progress A Sanitizer.sys.mjs progress object that + * will be updated to reflect the current step of fetching principals. * @returns {Array} the list of principals */ async getAllPrincipals(progress = {}) { diff --git a/toolkit/components/cleardata/SiteDataTestUtils.sys.mjs b/toolkit/components/cleardata/SiteDataTestUtils.sys.mjs index a777a19b7d..99bd1f72b0 100644 --- a/toolkit/components/cleardata/SiteDataTestUtils.sys.mjs +++ b/toolkit/components/cleardata/SiteDataTestUtils.sys.mjs @@ -244,10 +244,10 @@ export var SiteDataTestUtils = { return new Promise(resolve => { let data = true; let request = indexedDB.openForPrincipal(principal, "TestDatabase", 1); - request.onupgradeneeded = function (e) { + request.onupgradeneeded = function () { data = false; }; - request.onsuccess = function (e) { + request.onsuccess = function () { resolve(data); }; }); @@ -276,11 +276,11 @@ export var SiteDataTestUtils = { CacheListener.prototype = { QueryInterface: ChromeUtils.generateQI(["nsICacheEntryOpenCallback"]), - onCacheEntryCheck(entry) { + onCacheEntryCheck() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; }, - onCacheEntryAvailable(entry, isnew, status) { + onCacheEntryAvailable() { resolve(); }, }; diff --git a/toolkit/components/cleardata/nsIClearDataService.idl b/toolkit/components/cleardata/nsIClearDataService.idl index ea17059bbe..babbc8f05b 100644 --- a/toolkit/components/cleardata/nsIClearDataService.idl +++ b/toolkit/components/cleardata/nsIClearDataService.idl @@ -31,7 +31,7 @@ interface nsIClearDataService : nsISupports * @param aCallback this callback will be executed when the operation is * completed. */ - void deleteDataFromLocalFiles(in bool aIsUserRequest, + void deleteDataFromLocalFiles(in boolean aIsUserRequest, in uint32_t aFlags, in nsIClearDataCallback aCallback); @@ -50,7 +50,7 @@ interface nsIClearDataService : nsISupports * @deprecated Use deleteDataFromBaseDomain instead. */ void deleteDataFromHost(in AUTF8String aHost, - in bool aIsUserRequest, + in boolean aIsUserRequest, in uint32_t aFlags, in nsIClearDataCallback aCallback); @@ -76,7 +76,7 @@ interface nsIClearDataService : nsISupports * may fall back to clearing by principal or host. */ void deleteDataFromBaseDomain(in AUTF8String aDomainOrHost, - in bool aIsUserRequest, + in boolean aIsUserRequest, in uint32_t aFlags, in nsIClearDataCallback aCallback); @@ -93,7 +93,7 @@ interface nsIClearDataService : nsISupports * completed. */ void deleteDataFromPrincipal(in nsIPrincipal aPrincipal, - in bool aIsUserRequest, + in boolean aIsUserRequest, in uint32_t aFlags, in nsIClearDataCallback aCallback); @@ -111,7 +111,7 @@ interface nsIClearDataService : nsISupports * completed. */ void deleteDataInTimeRange(in PRTime aFrom, in PRTime aTo, - in bool aIsUserRequest, + in boolean aIsUserRequest, in uint32_t aFlags, in nsIClearDataCallback aCallback); @@ -307,6 +307,11 @@ interface nsIClearDataService : nsISupports */ const uint32_t CLEAR_BOUNCE_TRACKING_PROTECTION_STATE = 1 << 28; + /** + * Clear permissions of type "persistent-storage" and "storage-access" + */ + const uint32_t CLEAR_STORAGE_PERMISSIONS = 1 << 29; + /** * Use this value to delete all the data. */ @@ -340,6 +345,19 @@ interface nsIClearDataService : nsISupports CLEAR_CREDENTIAL_MANAGER_STATE | CLEAR_COOKIE_BANNER_EXCEPTION | CLEAR_COOKIE_BANNER_EXECUTED_RECORD | CLEAR_FINGERPRINTING_PROTECTION_STATE | CLEAR_BOUNCE_TRACKING_PROTECTION_STATE; + + /** + * Helper flag for clearing cookies and site data. + * This flag groups state that we consider site data + * from the user perspective. If you implement UI that + * offers site data clearing this is almost always what you want. + * If you need more granular control please use more specific + * flags like CLEAR_COOKIES and CLEAR_DOM_STORAGES. + */ + const uint32_t CLEAR_COOKIES_AND_SITE_DATA = + CLEAR_COOKIES | CLEAR_COOKIE_BANNER_EXECUTED_RECORD | CLEAR_DOM_STORAGES | CLEAR_HSTS | + CLEAR_EME | CLEAR_AUTH_TOKENS | CLEAR_AUTH_CACHE | CLEAR_FINGERPRINTING_PROTECTION_STATE | + CLEAR_BOUNCE_TRACKING_PROTECTION_STATE | CLEAR_STORAGE_PERMISSIONS; }; /** diff --git a/toolkit/components/cleardata/tests/browser/browser.toml b/toolkit/components/cleardata/tests/browser/browser.toml index 16ecffce02..d13f4f4f32 100644 --- a/toolkit/components/cleardata/tests/browser/browser.toml +++ b/toolkit/components/cleardata/tests/browser/browser.toml @@ -3,21 +3,18 @@ ["browser_auth_tokens.js"] ["browser_css_cache.js"] -https_first_disabled = true support-files = [ "file_css_cache.css", "file_css_cache.html" ] ["browser_image_cache.js"] -https_first_disabled = true support-files = [ "file_image_cache.html", "file_image_cache.jpg" ] ["browser_preflight_cache.js"] -https_first_disabled = true support-files = ["file_cors_preflight.sjs"] ["browser_quota.js"] diff --git a/toolkit/components/cleardata/tests/browser/browser_css_cache.js b/toolkit/components/cleardata/tests/browser/browser_css_cache.js index 47088e5011..61cee8b8d9 100644 --- a/toolkit/components/cleardata/tests/browser/browser_css_cache.js +++ b/toolkit/components/cleardata/tests/browser/browser_css_cache.js @@ -74,6 +74,7 @@ async function cleanupTestTabs() { } add_task(async function test_deleteByPrincipal() { + await SpecialPowers.setBoolPref("dom.security.https_first", false); await addTestTabs(); // Clear data for content principal of A diff --git a/toolkit/components/cleardata/tests/browser/browser_image_cache.js b/toolkit/components/cleardata/tests/browser/browser_image_cache.js index d7116d2502..947d4aba3e 100644 --- a/toolkit/components/cleardata/tests/browser/browser_image_cache.js +++ b/toolkit/components/cleardata/tests/browser/browser_image_cache.js @@ -114,6 +114,7 @@ add_setup(function () { }); add_task(async function test_deleteByPrincipal() { + await SpecialPowers.setBoolPref("dom.security.https_first", false); await addTestTabs(); // Clear data for content principal of A @@ -152,6 +153,7 @@ add_task(async function test_deleteByPrincipal() { }); add_task(async function test_deleteByBaseDomain() { + await SpecialPowers.setBoolPref("dom.security.https_first", false); await addTestTabs(); // Clear data for base domain of A. diff --git a/toolkit/components/cleardata/tests/browser/browser_preflight_cache.js b/toolkit/components/cleardata/tests/browser/browser_preflight_cache.js index d3eabb9e38..8973cc981c 100644 --- a/toolkit/components/cleardata/tests/browser/browser_preflight_cache.js +++ b/toolkit/components/cleardata/tests/browser/browser_preflight_cache.js @@ -9,8 +9,8 @@ const { SiteDataTestUtils } = ChromeUtils.importESModule( const uuidGenerator = Services.uuid; -const ORIGIN_A = "http://example.net"; -const ORIGIN_B = "http://example.org"; +const ORIGIN_A = "https://example.net"; +const ORIGIN_B = "https://example.org"; const PREFLIGHT_URL_PATH = "/browser/toolkit/components/cleardata/tests/browser/file_cors_preflight.sjs"; @@ -45,7 +45,7 @@ async function testDeleteAll( clearDataFlag, { deleteBy = "all", hasUserInput = false } = {} ) { - await BrowserTestUtils.withNewTab("http://example.com", async browser => { + await BrowserTestUtils.withNewTab("https://example.com", async browser => { let token = uuidGenerator.generateUUID().toString(); // Populate the preflight cache. @@ -132,7 +132,7 @@ add_task(async function test_deletePrivateBrowsingCache() { const tab = (browser.gBrowser.selectedTab = BrowserTestUtils.addTab( browser.gBrowser, - "http://example.com" + "https://example.com" )); await BrowserTestUtils.browserLoaded(tab.linkedBrowser); diff --git a/toolkit/components/cleardata/tests/marionette/test_moved_origin_directory_cleanup.py b/toolkit/components/cleardata/tests/marionette/test_moved_origin_directory_cleanup.py index 50f4c93f65..d30cf438e1 100644 --- a/toolkit/components/cleardata/tests/marionette/test_moved_origin_directory_cleanup.py +++ b/toolkit/components/cleardata/tests/marionette/test_moved_origin_directory_cleanup.py @@ -16,6 +16,7 @@ class MovedOriginDirectoryCleanupTestCase(MarionetteTestCase): "privacy.sanitize.sanitizeOnShutdown": True, "privacy.clearOnShutdown.offlineApps": True, "dom.quotaManager.backgroundTask.enabled": False, + "browser.sanitizer.loglevel": "All", } ) self.moved_origin_directory = ( @@ -30,6 +31,13 @@ class MovedOriginDirectoryCleanupTestCase(MarionetteTestCase): with self.marionette.using_context("chrome"): self.marionette.execute_script( """ + let promise = new Promise(resolve => { + function observer() { + Services.obs.removeObserver(observer, "cookie-saved-on-disk"); + resolve(); + } + Services.obs.addObserver(observer, "cookie-saved-on-disk"); + }); Services.cookies.add( "example.local", "path", @@ -43,6 +51,7 @@ class MovedOriginDirectoryCleanupTestCase(MarionetteTestCase): Ci.nsICookie.SAMESITE_NONE, Ci.nsICookie.SCHEME_UNSET ); + return promise; """ ) diff --git a/toolkit/components/cleardata/tests/unit/test_permissions.js b/toolkit/components/cleardata/tests/unit/test_permissions.js index 1f46ab5015..450476183a 100644 --- a/toolkit/components/cleardata/tests/unit/test_permissions.js +++ b/toolkit/components/cleardata/tests/unit/test_permissions.js @@ -88,7 +88,7 @@ add_task(async function test_principal_permissions() { await new Promise(aResolve => { Services.clearData.deleteData( Ci.nsIClearDataService.CLEAR_PERMISSIONS, - value => aResolve() + () => aResolve() ); }); }); @@ -465,7 +465,7 @@ add_task(async function test_3rdpartystorage_permissions() { await new Promise(aResolve => { Services.clearData.deleteData( Ci.nsIClearDataService.CLEAR_PERMISSIONS, - value => aResolve() + () => aResolve() ); }); }); diff --git a/toolkit/components/cleardata/tests/unit/test_storage_permission.js b/toolkit/components/cleardata/tests/unit/test_storage_permission.js index a44e9f2c6a..5ff3e6d15c 100644 --- a/toolkit/components/cleardata/tests/unit/test_storage_permission.js +++ b/toolkit/components/cleardata/tests/unit/test_storage_permission.js @@ -62,7 +62,7 @@ add_task(async function test_removing_storage_permission() { await new Promise(aResolve => { Services.clearData.deleteData( Ci.nsIClearDataService.CLEAR_PERMISSIONS, - value => aResolve() + () => aResolve() ); }); }); @@ -138,7 +138,7 @@ add_task(async function test_removing_storage_permission_from_principal() { await new Promise(aResolve => { Services.clearData.deleteData( Ci.nsIClearDataService.CLEAR_PERMISSIONS, - value => aResolve() + () => aResolve() ); }); }); @@ -240,7 +240,7 @@ add_task(async function test_removing_storage_permission_from_base_domainl() { await new Promise(aResolve => { Services.clearData.deleteData( Ci.nsIClearDataService.CLEAR_PERMISSIONS, - value => aResolve() + () => aResolve() ); }); }); @@ -392,7 +392,7 @@ add_task(async function test_deleteUserInteractionForClearingHistory() { await new Promise(aResolve => { Services.clearData.deleteData( Ci.nsIClearDataService.CLEAR_PERMISSIONS, - value => aResolve() + () => aResolve() ); }); }); diff --git a/toolkit/components/cleardata/tests/unit/test_storage_permission_clearing.js b/toolkit/components/cleardata/tests/unit/test_storage_permission_clearing.js new file mode 100644 index 0000000000..9285236958 --- /dev/null +++ b/toolkit/components/cleardata/tests/unit/test_storage_permission_clearing.js @@ -0,0 +1,271 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/*** + * Tests clearing storage access and persistent storage permissions + */ + +"use strict"; + +const baseDomain = "example.net"; +const baseDomain2 = "host.org"; +const uri = Services.io.newURI(`https://` + baseDomain); +const uri2 = Services.io.newURI(`https://` + baseDomain2); +const uri3 = Services.io.newURI(`https://www.` + baseDomain); +const principal = Services.scriptSecurityManager.createContentPrincipal( + uri, + {} +); +const principal2 = Services.scriptSecurityManager.createContentPrincipal( + uri2, + {} +); +const principal3 = Services.scriptSecurityManager.createContentPrincipal( + uri3, + {} +); + +add_task(async function test_clearing_by_principal() { + Services.perms.addFromPrincipal( + principal, + "storage-access", + Services.perms.ALLOW_ACTION + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "There is a storage-access permission set for principal 1" + ); + + Services.perms.addFromPrincipal( + principal, + "persistent-storage", + Services.perms.ALLOW_ACTION + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "persistent-storage" + ), + Services.perms.ALLOW_ACTION, + "There is a persistent-storage permission set for principal 1" + ); + + // Add a principal that shouldn't get cleared + Services.perms.addFromPrincipal( + principal2, + "storage-access", + Services.perms.ALLOW_ACTION + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal2, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "There is a storage-access permission set for principal 2" + ); + + // Add an unrelated permission which we don't expect to be cleared + Services.perms.addFromPrincipal( + principal, + "desktop-notification", + Services.perms.ALLOW_ACTION + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "desktop-notification" + ), + Services.perms.ALLOW_ACTION, + "There is a desktop-notification permission set for principal 1" + ); + + await new Promise(aResolve => { + Services.clearData.deleteDataFromPrincipal( + principal, + true, + Ci.nsIClearDataService.CLEAR_STORAGE_PERMISSIONS, + value => { + Assert.equal(value, 0); + aResolve(); + } + ); + }); + + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "storage-access" + ), + Services.perms.UNKNOWN_ACTION, + "storage-access permission for principal 1 has been removed" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "persistent-storage" + ), + Services.perms.UNKNOWN_ACTION, + "persistent-storage permission for principal 1 should be removed" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal2, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "storage-access permission for principal 2 should not be removed" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "desktop-notification" + ), + Services.perms.ALLOW_ACTION, + "desktop-notification permission for principal should not be removed" + ); +}); + +add_task(async function test_clearing_by_baseDomain() { + Services.perms.addFromPrincipal( + principal, + "storage-access", + Services.perms.ALLOW_ACTION + ); + Services.perms.addFromPrincipal( + principal2, + "storage-access", + Services.perms.ALLOW_ACTION + ); + Services.perms.addFromPrincipal( + principal3, + "storage-access", + Services.perms.ALLOW_ACTION + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "There is a storage-access permission set for principal 1" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal2, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "There is a storage-access permission set for principal 2" + ); + + await new Promise(aResolve => { + Services.clearData.deleteDataFromBaseDomain( + baseDomain, + true, + Ci.nsIClearDataService.CLEAR_STORAGE_PERMISSIONS, + value => { + Assert.equal(value, 0); + aResolve(); + } + ); + }); + + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "storage-access" + ), + Services.perms.UNKNOWN_ACTION, + "storage-access permission for principal 1 has been removed" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal2, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "storage-access permission for principal 2 should not be removed" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal3, + "storage-access" + ), + Services.perms.UNKNOWN_ACTION, + "storage-access permission for principal 3 should be removed" + ); +}); + +add_task(async function test_clearing_by_range() { + let currTime = Date.now(); + let modificationTimeTwoHoursAgo = new Date(currTime - 2 * 60 * 60 * 1000); + let modificationTimeThirtyMinsAgo = new Date(currTime - 30 * 60 * 1000); + + Services.perms.testAddFromPrincipalByTime( + principal, + "storage-access", + Services.perms.ALLOW_ACTION, + modificationTimeTwoHoursAgo + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "There is a storage-access permission set for principal 1" + ); + + Services.perms.testAddFromPrincipalByTime( + principal2, + "persistent-storage", + Services.perms.ALLOW_ACTION, + modificationTimeThirtyMinsAgo + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal2, + "persistent-storage" + ), + Services.perms.ALLOW_ACTION, + "There is a persistent-storage permission set for principal 2" + ); + + let modificationTimeOneHourAgo = new Date(currTime - 60 * 60 * 1000); + // We need to pass in microseconds to the clear data service + // so we multiply the ranges by 1000 + await new Promise(aResolve => { + Services.clearData.deleteDataInTimeRange( + modificationTimeOneHourAgo * 1000, + Date.now() * 1000, + true, + Ci.nsIClearDataService.CLEAR_STORAGE_PERMISSIONS, + value => { + Assert.equal(value, 0); + aResolve(); + } + ); + }); + + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal, + "storage-access" + ), + Services.perms.ALLOW_ACTION, + "storage-access permission for principal 1 should not be removed" + ); + Assert.equal( + Services.perms.testExactPermissionFromPrincipal( + principal2, + "persistent-storage" + ), + Services.perms.UNKNOWN_ACTION, + "persistent-storage permission for principal 2 should be removed" + ); +}); diff --git a/toolkit/components/cleardata/tests/unit/xpcshell.toml b/toolkit/components/cleardata/tests/unit/xpcshell.toml index 2df07abcea..bf2813a401 100644 --- a/toolkit/components/cleardata/tests/unit/xpcshell.toml +++ b/toolkit/components/cleardata/tests/unit/xpcshell.toml @@ -38,3 +38,5 @@ skip-if = ["condprof"] # Bug 1769154 - expected fail w/condprof ["test_security_settings.js"] ["test_storage_permission.js"] + +["test_storage_permission_clearing.js"] -- cgit v1.2.3