/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * This tests the new clear history dialog's data size display functionality */ ChromeUtils.defineESModuleGetters(this, { sinon: "resource://testing-common/Sinon.sys.mjs", Sanitizer: "resource:///modules/Sanitizer.sys.mjs", }); add_setup(async function () { await blankSlate(); registerCleanupFunction(async function () { await blankSlate(); await PlacesTestUtils.promiseAsyncUpdates(); }); await SpecialPowers.pushPrefEnv({ set: [["privacy.sanitize.useOldClearHistoryDialog", false]], }); }); /** * Helper function to validate the data sizes shown for each time selection * * @param {ClearHistoryDialogHelper} dh - dialog object to access window and timespan */ async function validateDataSizes(ClearHistoryDialogHelper) { let timespans = [ "TIMESPAN_HOUR", "TIMESPAN_2HOURS", "TIMESPAN_4HOURS", "TIMESPAN_TODAY", "TIMESPAN_EVERYTHING", ]; // get current data sizes from siteDataManager let cacheUsage = await SiteDataManager.getCacheSize(); let quotaUsage = await SiteDataManager.getQuotaUsageForTimeRanges(timespans); for (let i = 0; i < timespans.length; i++) { // select timespan to check ClearHistoryDialogHelper.selectDuration(Sanitizer[timespans[i]]); // get the elements let clearCookiesAndSiteDataCheckbox = ClearHistoryDialogHelper.win.document.getElementById("cookiesAndStorage"); let clearCacheCheckbox = ClearHistoryDialogHelper.win.document.getElementById("cache"); let [convertedQuotaUsage] = DownloadUtils.convertByteUnits( quotaUsage[timespans[i]] ); let [, convertedCacheUnit] = DownloadUtils.convertByteUnits(cacheUsage); // Ensure l10n is finished before inspecting the category labels. await ClearHistoryDialogHelper.win.document.l10n.translateElements([ clearCookiesAndSiteDataCheckbox, clearCacheCheckbox, ]); ok( clearCacheCheckbox.label.includes(convertedCacheUnit), "Should show the cache usage" ); ok( clearCookiesAndSiteDataCheckbox.label.includes(convertedQuotaUsage), `Should show the quota usage as ${convertedQuotaUsage}` ); } } /** * Helper function to simulate switching timespan selections and * validate data sizes before and after clearing * * @param {Object} * clearCookies - boolean * clearDownloads - boolean * clearCaches - boolean * timespan - one of Sanitizer.TIMESPAN_* */ async function clearAndValidateDataSizes({ clearCache, clearDownloads, clearCookies, timespan, }) { await blankSlate(); await addToSiteUsage(); let promiseSanitized = promiseSanitizationComplete(); await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); let dh = new ClearHistoryDialogHelper({ checkingDataSizes: true }); dh.onload = async function () { await validateDataSizes(this); this.checkPrefCheckbox("cache", clearCache); this.checkPrefCheckbox("cookiesAndStorage", clearCookies); this.checkPrefCheckbox("historyFormDataAndDownloads", clearDownloads); this.selectDuration(timespan); this.acceptDialog(); }; dh.onunload = async function () { await promiseSanitized; }; dh.open(); await dh.promiseClosed; let dh2 = new ClearHistoryDialogHelper({ checkingDataSizes: true }); // Check if the newly cleared values are reflected dh2.onload = async function () { await validateDataSizes(this); this.acceptDialog(); }; dh2.open(); await dh2.promiseClosed; await SiteDataTestUtils.clear(); BrowserTestUtils.removeTab(gBrowser.selectedTab); } add_task(async function test_cookie_sizes() { await clearAndValidateDataSizes({ clearCookies: true, clearCache: false, clearDownloads: false, timespan: Sanitizer.TIMESPAN_HOUR, }); await clearAndValidateDataSizes({ clearCookies: true, clearCache: false, clearDownloads: false, timespan: Sanitizer.TIMESPAN_4HOURS, }); await clearAndValidateDataSizes({ clearCookies: true, clearCache: false, clearDownloads: false, timespan: Sanitizer.TIMESPAN_EVERYTHING, }); }); add_task(async function test_cache_sizes() { await clearAndValidateDataSizes({ clearCookies: false, clearCache: true, clearDownloads: false, timespan: Sanitizer.TIMESPAN_HOUR, }); await clearAndValidateDataSizes({ clearCookies: false, clearCache: true, clearDownloads: false, timespan: Sanitizer.TIMESPAN_4HOURS, }); await clearAndValidateDataSizes({ clearCookies: false, clearCache: true, clearDownloads: false, timespan: Sanitizer.TIMESPAN_EVERYTHING, }); }); add_task(async function test_all_data_sizes() { await clearAndValidateDataSizes({ clearCookies: true, clearCache: true, clearDownloads: true, timespan: Sanitizer.TIMESPAN_HOUR, }); await clearAndValidateDataSizes({ clearCookies: true, clearCache: true, clearDownloads: true, timespan: Sanitizer.TIMESPAN_4HOURS, }); await clearAndValidateDataSizes({ clearCookies: true, clearCache: true, clearDownloads: true, timespan: Sanitizer.TIMESPAN_EVERYTHING, }); }); // This test makes sure that the user can change their timerange option // even if the data sizes are not loaded yet. add_task(async function testUIWithDataSizesLoading() { await blankSlate(); await addToSiteUsage(); let origGetQuotaUsageForTimeRanges = SiteDataManager.getQuotaUsageForTimeRanges.bind(SiteDataManager); let resolveStubFn; let resolverAssigned = false; let dh = new ClearHistoryDialogHelper(); // Create a sandbox for isolated stubbing within the test let sandbox = sinon.createSandbox(); sandbox .stub(SiteDataManager, "getQuotaUsageForTimeRanges") .callsFake(async (...args) => { info("stub called"); let dataSizesReadyToLoadPromise = new Promise(resolve => { resolveStubFn = resolve; info("Sending message to notify dialog that the resolver is assigned"); window.postMessage("resolver-assigned", "*"); resolverAssigned = true; }); await dataSizesReadyToLoadPromise; return origGetQuotaUsageForTimeRanges(...args); }); dh.onload = async function () { // we add this event listener in the case where init finishes before the resolver is assigned if (!resolverAssigned) { await new Promise(resolve => { let listener = event => { if (event.data === "resolver-assigned") { window.removeEventListener("message", listener); // we are ready to test the dialog without any data sizes loaded resolve(); } }; window.addEventListener("message", listener); }); } ok( !this.win.gSanitizePromptDialog._dataSizesUpdated, "Data sizes should not have loaded yet" ); this.selectDuration(Sanitizer.TIMESPAN_2HOURS); info("triggering loading state end"); resolveStubFn(); await this.win.gSanitizePromptDialog.dataSizesFinishedUpdatingPromise; validateDataSizes(this); this.cancelDialog(); }; dh.open(); await dh.promiseClosed; // Restore the sandbox after the test is complete sandbox.restore(); }); add_task(async function testClearingBeforeDataSizesLoad() { await blankSlate(); await addToSiteUsage(); // add site data that we can verify if it gets cleared await createDummyDataForHost("example.org"); await createDummyDataForHost("example.com"); ok( await SiteDataTestUtils.hasIndexedDB("https://example.org"), "We have indexedDB data for example.org" ); ok( await SiteDataTestUtils.hasIndexedDB("https://example.com"), "We have indexedDB data for example.com" ); let dh = new ClearHistoryDialogHelper(); let promiseSanitized = promiseSanitizationComplete(); // Create a sandbox for isolated stubbing within the test let sandbox = sinon.createSandbox(); sandbox .stub(SiteDataManager, "getQuotaUsageForTimeRanges") .callsFake(async () => { info("stub called"); info("This promise should never resolve"); await new Promise(resolve => {}); }); dh.onload = async function () { // we don't need to initiate a event listener to wait for the resolver to be assigned for this // test since we do not want the data sizes to load ok( !this.win.gSanitizePromptDialog._dataSizesUpdated, "Data sizes should not be loaded yet" ); this.selectDuration(Sanitizer.TIMESPAN_2HOURS); this.checkPrefCheckbox("cookiesAndStorage", true); this.acceptDialog(); }; dh.onunload = async () => { await promiseSanitized; }; dh.open(); await dh.promiseClosed; // Data for example.org should be cleared ok( !(await SiteDataTestUtils.hasIndexedDB("https://example.org")), "We don't have indexedDB data for example.org" ); // Data for example.com should be cleared ok( !(await SiteDataTestUtils.hasIndexedDB("https://example.com")), "We don't have indexedDB data for example.com" ); // Restore the sandbox after the test is complete sandbox.restore(); });