browser_clearSiteData.js (7881B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { PermissionTestUtils } = ChromeUtils.importESModule( 7 "resource://testing-common/PermissionTestUtils.sys.mjs" 8 ); 9 10 async function testClearData(clearSiteData, clearCache) { 11 PermissionTestUtils.add( 12 TEST_QUOTA_USAGE_ORIGIN, 13 "persistent-storage", 14 Services.perms.ALLOW_ACTION 15 ); 16 17 // Open a test site which saves into appcache. 18 await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_OFFLINE_URL); 19 BrowserTestUtils.removeTab(gBrowser.selectedTab); 20 21 // Fill indexedDB with test data. 22 // Don't wait for the page to load, to register the content event handler as quickly as possible. 23 // If this test goes intermittent, we might have to tell the page to wait longer before 24 // firing the event. 25 BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL, false); 26 await BrowserTestUtils.waitForContentEvent( 27 gBrowser.selectedBrowser, 28 "test-indexedDB-done", 29 false, 30 null, 31 true 32 ); 33 BrowserTestUtils.removeTab(gBrowser.selectedTab); 34 35 // Register some service workers. 36 await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL); 37 await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL); 38 39 await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); 40 41 // Test the initial states. 42 let cacheUsage = await SiteDataManager.getCacheSize(); 43 let quotaUsage = await SiteDataTestUtils.getQuotaUsage( 44 TEST_QUOTA_USAGE_ORIGIN 45 ); 46 let totalUsage = await SiteDataManager.getTotalUsage(); 47 Assert.greater(cacheUsage, 0, "The cache usage should not be 0"); 48 Assert.greater(quotaUsage, 0, "The quota usage should not be 0"); 49 Assert.greater(totalUsage, 0, "The total usage should not be 0"); 50 51 let initialSizeLabelValue = await SpecialPowers.spawn( 52 gBrowser.selectedBrowser, 53 [], 54 async function () { 55 let siteDataSizeItem = content.document.getElementById("siteDataSize"); 56 // The <strong> element contains the data size. 57 let usage = siteDataSizeItem.querySelector("strong"); 58 return usage.textContent; 59 } 60 ); 61 62 let doc = gBrowser.selectedBrowser.contentDocument; 63 let clearSiteDataButton = doc.getElementById("clearSiteDataButton"); 64 65 let url = "chrome://browser/content/preferences/dialogs/clearSiteData.xhtml"; 66 let dialogOpened = promiseLoadSubDialog(url); 67 clearSiteDataButton.scrollIntoView(); 68 EventUtils.synthesizeMouseAtCenter( 69 clearSiteDataButton.buttonEl, 70 {}, 71 doc.ownerGlobal 72 ); 73 let dialogWin = await dialogOpened; 74 75 // Convert the usage numbers in the same way the UI does it to assert 76 // that they're displayed in the dialog. 77 let [convertedTotalUsage] = DownloadUtils.convertByteUnits(totalUsage); 78 // For cache we just assert that the right unit (KB, probably) is displayed, 79 // since we've had cache intermittently changing under our feet. 80 let [, convertedCacheUnit] = DownloadUtils.convertByteUnits(cacheUsage); 81 82 let cookiesCheckboxId = "clearSiteData"; 83 let cacheCheckboxId = "clearCache"; 84 let clearSiteDataCheckbox = 85 dialogWin.document.getElementById(cookiesCheckboxId); 86 let clearCacheCheckbox = dialogWin.document.getElementById(cacheCheckboxId); 87 // The usage details are filled asynchronously, so we assert that they're present by 88 // waiting for them to be filled in. 89 await Promise.all([ 90 TestUtils.waitForCondition( 91 () => 92 clearSiteDataCheckbox.label && 93 clearSiteDataCheckbox.label.includes(convertedTotalUsage), 94 "Should show the quota usage" 95 ), 96 TestUtils.waitForCondition( 97 () => 98 clearCacheCheckbox.label && 99 clearCacheCheckbox.label.includes(convertedCacheUnit), 100 "Should show the cache usage" 101 ), 102 ]); 103 104 // Check the boxes according to our test input. 105 clearSiteDataCheckbox.checked = clearSiteData; 106 clearCacheCheckbox.checked = clearCache; 107 108 // Some additional promises/assertions to wait for 109 // when deleting site data. 110 let acceptPromise; 111 let updatePromise; 112 let cookiesClearedPromise; 113 if (clearSiteData) { 114 acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept"); 115 updatePromise = promiseSiteDataManagerSitesUpdated(); 116 cookiesClearedPromise = promiseCookiesCleared(); 117 } 118 119 let dialogClosed = BrowserTestUtils.waitForEvent(dialogWin, "unload"); 120 121 let clearButton = dialogWin.document 122 .querySelector("dialog") 123 .getButton("accept"); 124 if (!clearSiteData && !clearCache) { 125 // Simulate user input on one of the checkboxes to trigger the event listener for 126 // disabling the clearButton. 127 clearCacheCheckbox.doCommand(); 128 // Check that the clearButton gets disabled by unchecking both options. 129 await TestUtils.waitForCondition( 130 () => clearButton.disabled, 131 "Clear button should be disabled" 132 ); 133 let cancelButton = dialogWin.document 134 .querySelector("dialog") 135 .getButton("cancel"); 136 // Cancel, since we can't delete anything. 137 cancelButton.click(); 138 } else { 139 // Delete stuff! 140 clearButton.click(); 141 } 142 143 // For site data we display an extra warning dialog, make sure 144 // to accept it. 145 if (clearSiteData) { 146 await acceptPromise; 147 } 148 149 await dialogClosed; 150 151 if (clearCache) { 152 TestUtils.waitForCondition(async function () { 153 let usage = await SiteDataManager.getCacheSize(); 154 return usage == 0; 155 }, "The cache usage should be removed"); 156 } else { 157 Assert.greater( 158 await SiteDataManager.getCacheSize(), 159 0, 160 "The cache usage should not be 0" 161 ); 162 } 163 164 if (clearSiteData) { 165 await updatePromise; 166 await cookiesClearedPromise; 167 await promiseServiceWorkersCleared(); 168 169 TestUtils.waitForCondition(async function () { 170 let usage = await SiteDataManager.getTotalUsage(); 171 return usage == 0; 172 }, "The total usage should be removed"); 173 } else { 174 quotaUsage = await SiteDataTestUtils.getQuotaUsage(TEST_QUOTA_USAGE_ORIGIN); 175 totalUsage = await SiteDataManager.getTotalUsage(); 176 Assert.greater(quotaUsage, 0, "The quota usage should not be 0"); 177 Assert.greater(totalUsage, 0, "The total usage should not be 0"); 178 } 179 180 if (clearCache || clearSiteData) { 181 // Check that the size label in about:preferences updates after we cleared data. 182 await SpecialPowers.spawn( 183 gBrowser.selectedBrowser, 184 [{ initialSizeLabelValue }], 185 async function (opts) { 186 let siteDataSizeItem = content.document.getElementById("siteDataSize"); 187 let usage = siteDataSizeItem.querySelector("strong"); 188 let siteDataSizeText = usage.textContent; 189 await ContentTaskUtils.waitForCondition(() => { 190 return siteDataSizeText != opts.initialSizeLabelValue; 191 }, "Site data size label should have updated."); 192 } 193 ); 194 } 195 196 let permission = PermissionTestUtils.getPermissionObject( 197 TEST_QUOTA_USAGE_ORIGIN, 198 "persistent-storage" 199 ); 200 is( 201 clearSiteData ? permission : permission.capability, 202 clearSiteData ? null : Services.perms.ALLOW_ACTION, 203 "Should have the correct permission state." 204 ); 205 206 BrowserTestUtils.removeTab(gBrowser.selectedTab); 207 await SiteDataManager.removeAll(); 208 } 209 210 add_setup(function () { 211 SpecialPowers.pushPrefEnv({ 212 set: [["privacy.sanitize.useOldClearHistoryDialog", true]], 213 }); 214 }); 215 216 // Test opening the "Clear All Data" dialog and cancelling. 217 add_task(async function () { 218 await testClearData(false, false); 219 }); 220 221 // Test opening the "Clear All Data" dialog and removing all site data. 222 add_task(async function () { 223 await testClearData(true, false); 224 }); 225 226 // Test opening the "Clear All Data" dialog and removing all cache. 227 add_task(async function () { 228 await testClearData(false, true); 229 }); 230 231 // Test opening the "Clear All Data" dialog and removing everything. 232 add_task(async function () { 233 await testClearData(true, true); 234 });