summaryrefslogtreecommitdiffstats
path: root/browser/components/preferences/tests/siteData/browser_clearSiteData.js
blob: 217656707eaedae5ff2a3ea4a82c8dfc70a4d90f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

const { PermissionTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/PermissionTestUtils.sys.mjs"
);

async function testClearData(clearSiteData, clearCache) {
  PermissionTestUtils.add(
    TEST_QUOTA_USAGE_ORIGIN,
    "persistent-storage",
    Services.perms.ALLOW_ACTION
  );

  // Open a test site which saves into appcache.
  await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_OFFLINE_URL);
  BrowserTestUtils.removeTab(gBrowser.selectedTab);

  // Fill indexedDB with test data.
  // Don't wait for the page to load, to register the content event handler as quickly as possible.
  // If this test goes intermittent, we might have to tell the page to wait longer before
  // firing the event.
  BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL, false);
  await BrowserTestUtils.waitForContentEvent(
    gBrowser.selectedBrowser,
    "test-indexedDB-done",
    false,
    null,
    true
  );
  BrowserTestUtils.removeTab(gBrowser.selectedTab);

  // Register some service workers.
  await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL);
  await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL);

  await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });

  // Test the initial states.
  let cacheUsage = await SiteDataManager.getCacheSize();
  let quotaUsage = await SiteDataTestUtils.getQuotaUsage(
    TEST_QUOTA_USAGE_ORIGIN
  );
  let totalUsage = await SiteDataManager.getTotalUsage();
  Assert.greater(cacheUsage, 0, "The cache usage should not be 0");
  Assert.greater(quotaUsage, 0, "The quota usage should not be 0");
  Assert.greater(totalUsage, 0, "The total usage should not be 0");

  let initialSizeLabelValue = await SpecialPowers.spawn(
    gBrowser.selectedBrowser,
    [],
    async function () {
      let sizeLabel = content.document.getElementById("totalSiteDataSize");
      return sizeLabel.textContent;
    }
  );

  let doc = gBrowser.selectedBrowser.contentDocument;
  let clearSiteDataButton = doc.getElementById("clearSiteDataButton");

  let dialogOpened = promiseLoadSubDialog(
    "chrome://browser/content/preferences/dialogs/clearSiteData.xhtml"
  );
  clearSiteDataButton.doCommand();
  let dialogWin = await dialogOpened;

  // Convert the usage numbers in the same way the UI does it to assert
  // that they're displayed in the dialog.
  let [convertedTotalUsage] = DownloadUtils.convertByteUnits(totalUsage);
  // For cache we just assert that the right unit (KB, probably) is displayed,
  // since we've had cache intermittently changing under our feet.
  let [, convertedCacheUnit] = DownloadUtils.convertByteUnits(cacheUsage);

  let clearSiteDataCheckbox =
    dialogWin.document.getElementById("clearSiteData");
  let clearCacheCheckbox = dialogWin.document.getElementById("clearCache");
  // The usage details are filled asynchronously, so we assert that they're present by
  // waiting for them to be filled in.
  await Promise.all([
    TestUtils.waitForCondition(
      () =>
        clearSiteDataCheckbox.label &&
        clearSiteDataCheckbox.label.includes(convertedTotalUsage),
      "Should show the quota usage"
    ),
    TestUtils.waitForCondition(
      () =>
        clearCacheCheckbox.label &&
        clearCacheCheckbox.label.includes(convertedCacheUnit),
      "Should show the cache usage"
    ),
  ]);

  // Check the boxes according to our test input.
  clearSiteDataCheckbox.checked = clearSiteData;
  clearCacheCheckbox.checked = clearCache;

  // Some additional promises/assertions to wait for
  // when deleting site data.
  let acceptPromise;
  let updatePromise;
  let cookiesClearedPromise;
  if (clearSiteData) {
    acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
    updatePromise = promiseSiteDataManagerSitesUpdated();
    cookiesClearedPromise = promiseCookiesCleared();
  }

  let dialogClosed = BrowserTestUtils.waitForEvent(dialogWin, "unload");

  let clearButton = dialogWin.document
    .querySelector("dialog")
    .getButton("accept");
  if (!clearSiteData && !clearCache) {
    // Simulate user input on one of the checkboxes to trigger the event listener for
    // disabling the clearButton.
    clearCacheCheckbox.doCommand();
    // Check that the clearButton gets disabled by unchecking both options.
    await TestUtils.waitForCondition(
      () => clearButton.disabled,
      "Clear button should be disabled"
    );
    let cancelButton = dialogWin.document
      .querySelector("dialog")
      .getButton("cancel");
    // Cancel, since we can't delete anything.
    cancelButton.click();
  } else {
    // Delete stuff!
    clearButton.click();
  }

  // For site data we display an extra warning dialog, make sure
  // to accept it.
  if (clearSiteData) {
    await acceptPromise;
  }

  await dialogClosed;

  if (clearCache) {
    TestUtils.waitForCondition(async function () {
      let usage = await SiteDataManager.getCacheSize();
      return usage == 0;
    }, "The cache usage should be removed");
  } else {
    Assert.greater(
      await SiteDataManager.getCacheSize(),
      0,
      "The cache usage should not be 0"
    );
  }

  if (clearSiteData) {
    await updatePromise;
    await cookiesClearedPromise;
    await promiseServiceWorkersCleared();

    TestUtils.waitForCondition(async function () {
      let usage = await SiteDataManager.getTotalUsage();
      return usage == 0;
    }, "The total usage should be removed");
  } else {
    quotaUsage = await SiteDataTestUtils.getQuotaUsage(TEST_QUOTA_USAGE_ORIGIN);
    totalUsage = await SiteDataManager.getTotalUsage();
    Assert.greater(quotaUsage, 0, "The quota usage should not be 0");
    Assert.greater(totalUsage, 0, "The total usage should not be 0");
  }

  if (clearCache || clearSiteData) {
    // Check that the size label in about:preferences updates after we cleared data.
    await SpecialPowers.spawn(
      gBrowser.selectedBrowser,
      [{ initialSizeLabelValue }],
      async function (opts) {
        let sizeLabel = content.document.getElementById("totalSiteDataSize");
        await ContentTaskUtils.waitForCondition(
          () => sizeLabel.textContent != opts.initialSizeLabelValue,
          "Site data size label should have updated."
        );
      }
    );
  }

  let permission = PermissionTestUtils.getPermissionObject(
    TEST_QUOTA_USAGE_ORIGIN,
    "persistent-storage"
  );
  is(
    clearSiteData ? permission : permission.capability,
    clearSiteData ? null : Services.perms.ALLOW_ACTION,
    "Should have the correct permission state."
  );

  BrowserTestUtils.removeTab(gBrowser.selectedTab);
  await SiteDataManager.removeAll();
}

// Test opening the "Clear All Data" dialog and cancelling.
add_task(async function () {
  await testClearData(false, false);
});

// Test opening the "Clear All Data" dialog and removing all site data.
add_task(async function () {
  await testClearData(true, false);
});

// Test opening the "Clear All Data" dialog and removing all cache.
add_task(async function () {
  await testClearData(false, true);
});

// Test opening the "Clear All Data" dialog and removing everything.
add_task(async function () {
  await testClearData(true, true);
});