browser_sanitizeDialog_v2_dataSizes.js (11152B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * This tests the new clear history dialog's data size display functionality 7 */ 8 ChromeUtils.defineESModuleGetters(this, { 9 sinon: "resource://testing-common/Sinon.sys.mjs", 10 Sanitizer: "resource:///modules/Sanitizer.sys.mjs", 11 }); 12 13 const LARGE_USAGE_NUM = 100000000000000000000000000000000000000000000000000; 14 15 function isIframeOverflowing(win) { 16 return ( 17 win.scrollWidth > win.clientWidth || win.scrollHeight > win.clientHeight 18 ); 19 } 20 21 add_setup(async function () { 22 await blankSlate(); 23 requestLongerTimeout(2); 24 registerCleanupFunction(async function () { 25 await blankSlate(); 26 await PlacesTestUtils.promiseAsyncUpdates(); 27 await SiteDataTestUtils.clear(); 28 }); 29 await SpecialPowers.pushPrefEnv({ 30 set: [["privacy.sanitize.useOldClearHistoryDialog", false]], 31 }); 32 }); 33 34 /** 35 * Helper function to validate the data sizes shown for each time selection 36 * 37 * @param {ClearHistoryDialogHelper} dh - dialog object to access window and timespan 38 */ 39 async function validateDataSizes(ClearHistoryDialogHelper) { 40 let timespans = [ 41 "TIMESPAN_HOUR", 42 "TIMESPAN_2HOURS", 43 "TIMESPAN_4HOURS", 44 "TIMESPAN_TODAY", 45 "TIMESPAN_EVERYTHING", 46 ]; 47 48 // get current data sizes from siteDataManager 49 let cacheUsage = await SiteDataManager.getCacheSize(); 50 let quotaUsage = await SiteDataManager.getQuotaUsageForTimeRanges(timespans); 51 52 for (let i = 0; i < timespans.length; i++) { 53 // select timespan to check 54 ClearHistoryDialogHelper.selectDuration(Sanitizer[timespans[i]]); 55 56 // get the elements 57 let clearCookiesAndSiteDataCheckbox = 58 ClearHistoryDialogHelper.win.document.getElementById("cookiesAndStorage"); 59 let clearCacheCheckbox = 60 ClearHistoryDialogHelper.win.document.getElementById("cache"); 61 62 let [convertedQuotaUsage] = DownloadUtils.convertByteUnits( 63 quotaUsage[timespans[i]] 64 ); 65 let [, convertedCacheUnit] = DownloadUtils.convertByteUnits(cacheUsage); 66 67 // Ensure l10n is finished before inspecting the category labels. 68 await ClearHistoryDialogHelper.win.document.l10n.translateElements([ 69 clearCookiesAndSiteDataCheckbox, 70 clearCacheCheckbox, 71 ]); 72 ok( 73 clearCacheCheckbox.label.includes(convertedCacheUnit), 74 "Should show the cache usage" 75 ); 76 ok( 77 clearCookiesAndSiteDataCheckbox.label.includes(convertedQuotaUsage), 78 `Should show the quota usage as ${convertedQuotaUsage}` 79 ); 80 } 81 } 82 83 /** 84 * Helper function to simulate switching timespan selections and 85 * validate data sizes before and after clearing 86 * 87 * @param {object} 88 * clearCookies - boolean 89 * clearDownloads - boolean 90 * clearCaches - boolean 91 * timespan - one of Sanitizer.TIMESPAN_* 92 */ 93 async function clearAndValidateDataSizes({ 94 clearCache, 95 clearDownloads, 96 clearCookies, 97 timespan, 98 }) { 99 await blankSlate(); 100 101 await addToSiteUsage(); 102 let promiseSanitized = promiseSanitizationComplete(); 103 104 await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); 105 106 let dh = new ClearHistoryDialogHelper({ checkingDataSizes: true }); 107 dh.onload = async function () { 108 await validateDataSizes(this); 109 this.checkPrefCheckbox("cache", clearCache); 110 this.checkPrefCheckbox("cookiesAndStorage", clearCookies); 111 this.checkPrefCheckbox("browsingHistoryAndDownloads", clearDownloads); 112 this.selectDuration(timespan); 113 this.acceptDialog(); 114 }; 115 dh.onunload = async function () { 116 await promiseSanitized; 117 }; 118 dh.open(); 119 await dh.promiseClosed; 120 121 let dh2 = new ClearHistoryDialogHelper({ checkingDataSizes: true }); 122 // Check if the newly cleared values are reflected 123 dh2.onload = async function () { 124 await validateDataSizes(this); 125 this.acceptDialog(); 126 }; 127 dh2.open(); 128 await dh2.promiseClosed; 129 130 await SiteDataTestUtils.clear(); 131 BrowserTestUtils.removeTab(gBrowser.selectedTab); 132 } 133 134 add_task(async function test_cookie_sizes() { 135 await clearAndValidateDataSizes({ 136 clearCookies: true, 137 clearCache: false, 138 clearDownloads: false, 139 timespan: Sanitizer.TIMESPAN_HOUR, 140 }); 141 await clearAndValidateDataSizes({ 142 clearCookies: true, 143 clearCache: false, 144 clearDownloads: false, 145 timespan: Sanitizer.TIMESPAN_4HOURS, 146 }); 147 await clearAndValidateDataSizes({ 148 clearCookies: true, 149 clearCache: false, 150 clearDownloads: false, 151 timespan: Sanitizer.TIMESPAN_EVERYTHING, 152 }); 153 }); 154 155 add_task(async function test_cache_sizes() { 156 await clearAndValidateDataSizes({ 157 clearCookies: false, 158 clearCache: true, 159 clearDownloads: false, 160 timespan: Sanitizer.TIMESPAN_HOUR, 161 }); 162 await clearAndValidateDataSizes({ 163 clearCookies: false, 164 clearCache: true, 165 clearDownloads: false, 166 timespan: Sanitizer.TIMESPAN_4HOURS, 167 }); 168 await clearAndValidateDataSizes({ 169 clearCookies: false, 170 clearCache: true, 171 clearDownloads: false, 172 timespan: Sanitizer.TIMESPAN_EVERYTHING, 173 }); 174 }); 175 176 add_task(async function test_all_data_sizes() { 177 await clearAndValidateDataSizes({ 178 clearCookies: true, 179 clearCache: true, 180 clearDownloads: true, 181 timespan: Sanitizer.TIMESPAN_HOUR, 182 }); 183 await clearAndValidateDataSizes({ 184 clearCookies: true, 185 clearCache: true, 186 clearDownloads: true, 187 timespan: Sanitizer.TIMESPAN_4HOURS, 188 }); 189 await clearAndValidateDataSizes({ 190 clearCookies: true, 191 clearCache: true, 192 clearDownloads: true, 193 timespan: Sanitizer.TIMESPAN_EVERYTHING, 194 }); 195 }); 196 197 // This test makes sure that the user can change their timerange option 198 // even if the data sizes are not loaded yet. 199 add_task(async function testUIWithDataSizesLoading() { 200 await blankSlate(); 201 await addToSiteUsage(); 202 203 let origGetQuotaUsageForTimeRanges = 204 SiteDataManager.getQuotaUsageForTimeRanges.bind(SiteDataManager); 205 let resolveStubFn; 206 let resolverAssigned = false; 207 208 let dh = new ClearHistoryDialogHelper(); 209 // Create a sandbox for isolated stubbing within the test 210 let sandbox = sinon.createSandbox(); 211 sandbox 212 .stub(SiteDataManager, "getQuotaUsageForTimeRanges") 213 .callsFake(async (...args) => { 214 info("stub called"); 215 216 let dataSizesReadyToLoadPromise = new Promise(resolve => { 217 resolveStubFn = resolve; 218 info("Sending message to notify dialog that the resolver is assigned"); 219 window.postMessage("resolver-assigned", "*"); 220 resolverAssigned = true; 221 }); 222 await dataSizesReadyToLoadPromise; 223 return origGetQuotaUsageForTimeRanges(...args); 224 }); 225 dh.onload = async function () { 226 // we add this event listener in the case where init finishes before the resolver is assigned 227 if (!resolverAssigned) { 228 await new Promise(resolve => { 229 let listener = event => { 230 if (event.data === "resolver-assigned") { 231 window.removeEventListener("message", listener); 232 // we are ready to test the dialog without any data sizes loaded 233 resolve(); 234 } 235 }; 236 window.addEventListener("message", listener); 237 }); 238 } 239 240 ok( 241 !this.win.gSanitizePromptDialog._dataSizesUpdated, 242 "Data sizes should not have loaded yet" 243 ); 244 this.selectDuration(Sanitizer.TIMESPAN_2HOURS); 245 246 info("triggering loading state end"); 247 resolveStubFn(); 248 249 await this.win.gSanitizePromptDialog.dataSizesFinishedUpdatingPromise; 250 251 validateDataSizes(this); 252 this.cancelDialog(); 253 }; 254 dh.open(); 255 await dh.promiseClosed; 256 257 // Restore the sandbox after the test is complete 258 sandbox.restore(); 259 }); 260 261 add_task(async function testClearingBeforeDataSizesLoad() { 262 await blankSlate(); 263 await addToSiteUsage(); 264 265 // add site data that we can verify if it gets cleared 266 await createDummyDataForHost("example.org"); 267 await createDummyDataForHost("example.com"); 268 269 ok( 270 await SiteDataTestUtils.hasIndexedDB("https://example.org"), 271 "We have indexedDB data for example.org" 272 ); 273 ok( 274 await SiteDataTestUtils.hasIndexedDB("https://example.com"), 275 "We have indexedDB data for example.com" 276 ); 277 278 let dh = new ClearHistoryDialogHelper(); 279 let promiseSanitized = promiseSanitizationComplete(); 280 // Create a sandbox for isolated stubbing within the test 281 let sandbox = sinon.createSandbox(); 282 sandbox 283 .stub(SiteDataManager, "getQuotaUsageForTimeRanges") 284 .callsFake(async () => { 285 info("stub called"); 286 287 info("This promise should never resolve"); 288 await new Promise(() => {}); 289 }); 290 dh.onload = async function () { 291 // we don't need to initiate a event listener to wait for the resolver to be assigned for this 292 // test since we do not want the data sizes to load 293 ok( 294 !this.win.gSanitizePromptDialog._dataSizesUpdated, 295 "Data sizes should not be loaded yet" 296 ); 297 this.selectDuration(Sanitizer.TIMESPAN_2HOURS); 298 this.checkPrefCheckbox("cookiesAndStorage", true); 299 this.acceptDialog(); 300 }; 301 dh.onunload = async () => { 302 await promiseSanitized; 303 }; 304 dh.open(); 305 await dh.promiseClosed; 306 307 // Data for example.org should be cleared 308 ok( 309 !(await SiteDataTestUtils.hasIndexedDB("https://example.org")), 310 "We don't have indexedDB data for example.org" 311 ); 312 // Data for example.com should be cleared 313 ok( 314 !(await SiteDataTestUtils.hasIndexedDB("https://example.com")), 315 "We don't have indexedDB data for example.com" 316 ); 317 318 // Restore the sandbox after the test is complete 319 sandbox.restore(); 320 }); 321 322 // tests the dialog resizing upon wrapping of text 323 // so that the clear buttons do not get cut out of the dialog. 324 add_task(async function testPossibleWrappingOfDialog() { 325 await blankSlate(); 326 327 let dh = new ClearHistoryDialogHelper({ 328 checkingDataSizes: true, 329 }); 330 // Create a sandbox for isolated stubbing within the test 331 let sandbox = sinon.createSandbox(); 332 sandbox 333 .stub(SiteDataManager, "getQuotaUsageForTimeRanges") 334 .callsFake(async () => { 335 info("stubbed getQuotaUsageForTimeRanges called"); 336 337 return { 338 TIMESPAN_HOUR: 0, 339 TIMESPAN_2HOURS: 0, 340 TIMESPAN_4HOURS: LARGE_USAGE_NUM, 341 TIMESPAN_TODAY: 0, 342 TIMESPAN_EVERYTHING: 0, 343 }; 344 }); 345 346 dh.onload = async function () { 347 let windowObj = 348 window.browsingContext.topChromeWindow.gDialogBox._dialog._frame 349 .contentWindow; 350 let promise = new Promise(resolve => { 351 windowObj.addEventListener("resize", resolve); 352 }); 353 this.selectDuration(Sanitizer.TIMESPAN_4HOURS); 354 355 await promise; 356 ok( 357 !isIframeOverflowing(windowObj.document.getElementById("SanitizeDialog")), 358 "There should be no overflow on wrapping in the dialog" 359 ); 360 361 this.selectDuration(Sanitizer.TIMESPAN_2HOURS); 362 await promise; 363 ok( 364 !isIframeOverflowing(windowObj.document.getElementById("SanitizeDialog")), 365 "There should be no overflow on wrapping in the dialog" 366 ); 367 368 this.cancelDialog(); 369 }; 370 dh.open(); 371 await dh.promiseClosed; 372 373 // Restore the sandbox after the test is complete 374 sandbox.restore(); 375 });