tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });