tor-browser

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

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