зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1722502 - P4 Update the test for quota usage mitigation. r=dom-worker-reviewers,asuth
Depends on D122189 Differential Revision: https://phabricator.services.mozilla.com/D122190
This commit is contained in:
Родитель
432ced9589
Коммит
902453ab34
|
@ -25,6 +25,11 @@ const SWM = Cc["@mozilla.org/serviceworkers/manager;1"].getService(
|
|||
Ci.nsIServiceWorkerManager
|
||||
);
|
||||
|
||||
// The expected minimum usage for an origin that has any Cache API storage in
|
||||
// use. Currently, the DB uses a page size of 4k and a minimum growth size of
|
||||
// 32k and has enough tables/indices for this to round up to 64k.
|
||||
const kMinimumOriginUsageBytes = 65536;
|
||||
|
||||
function getPrincipal(url, attrs) {
|
||||
const uri = Services.io.newURI(url);
|
||||
if (!attrs) {
|
||||
|
@ -47,6 +52,13 @@ async function _qm_requestFinished(request) {
|
|||
return request.result;
|
||||
}
|
||||
|
||||
async function qm_reset_storage() {
|
||||
return new Promise(resolve => {
|
||||
let request = Services.qms.reset();
|
||||
request.callback = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
async function get_qm_origin_usage(origin) {
|
||||
return new Promise(resolve => {
|
||||
const principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
|
@ -70,7 +82,7 @@ async function clear_qm_origin_group_via_clearData(origin) {
|
|||
|
||||
// Initiate group clearing and wait for it.
|
||||
await new Promise((resolve, reject) => {
|
||||
Services.clearData.deleteDataFromHost(
|
||||
Services.clearData.deleteDataFromBaseDomain(
|
||||
baseDomain,
|
||||
false,
|
||||
Services.clearData.CLEAR_DOM_QUOTA,
|
||||
|
@ -165,6 +177,12 @@ async function consume_storage(origin, storageDesc) {
|
|||
);
|
||||
}
|
||||
|
||||
// Check if the origin is effectively empty, but allowing for the minimum size
|
||||
// Cache API database to be present.
|
||||
function is_minimum_origin_usage(originUsageBytes) {
|
||||
return originUsageBytes <= kMinimumOriginUsageBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a navigation, waiting until the navigation stops, then returning
|
||||
* the `textContent` of the body node. The expectation is this will be used
|
||||
|
@ -253,6 +271,23 @@ function waitForUnregister(scope) {
|
|||
});
|
||||
}
|
||||
|
||||
// Be careful using this helper function, please make sure QuotaUsageCheck must
|
||||
// happen, otherwise test would be stucked in this function.
|
||||
function waitForQuotaUsageCheckFinish(scope) {
|
||||
return new Promise(function(resolve) {
|
||||
let listener = {
|
||||
onQuotaUsageCheckFinish(registration) {
|
||||
if (registration.scope !== scope) {
|
||||
return;
|
||||
}
|
||||
SWM.removeListener(listener);
|
||||
resolve(registration);
|
||||
},
|
||||
};
|
||||
SWM.addListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForServiceWorkerRegistrationChange(registration, callback) {
|
||||
return new Promise(function(resolve) {
|
||||
let listener = {
|
||||
|
|
|
@ -104,8 +104,8 @@ const TEST_SW_SETUP = {
|
|||
};
|
||||
|
||||
const TEST_STORAGE_SETUP = {
|
||||
cacheBytes: 4 * 1024 * 1024,
|
||||
idbBytes: 4 * 1024 * 1024,
|
||||
cacheBytes: 4 * 1024 * 1024, // 4 MiB
|
||||
idbBytes: 4 * 1024 * 1024, // 4 MiB
|
||||
};
|
||||
|
||||
const FAULTS_BEFORE_MITIGATION = 3;
|
||||
|
@ -139,7 +139,7 @@ async function do_fault_injection_test({
|
|||
|
||||
// ## Generate quota usage if appropriate
|
||||
if (consumeQuotaOrigin) {
|
||||
await consume_storage(consumeQuotaOrigin, TEST_SW_SETUP);
|
||||
await consume_storage(consumeQuotaOrigin, TEST_STORAGE_SETUP);
|
||||
}
|
||||
|
||||
// ## Verify normal navigation is served by the SW.
|
||||
|
@ -164,13 +164,17 @@ async function do_fault_injection_test({
|
|||
// we expect it happens after navigation fault threshold reached.
|
||||
const unregisteredPromise = waitForUnregister(reg.scope);
|
||||
|
||||
// Make sure the test is listening on the finish of quota checking, since we
|
||||
// expect it happens after navigation fault threshold reached.
|
||||
const quotaUsageCheckFinishPromise = waitForQuotaUsageCheckFinish(reg.scope);
|
||||
|
||||
// ## Inject faults in a loop until expected mitigation.
|
||||
sw.testingInjectCancellation = useError;
|
||||
for (let iFault = 0; iFault < FAULTS_BEFORE_MITIGATION; iFault++) {
|
||||
info(`## Testing with injected fault number ${iFault + 1}`);
|
||||
// We should never have triggered an origin quota usage check before the
|
||||
// final fault injection.
|
||||
is(reg.quotaUsageCheckCount, 0, "No quota usage check yet.");
|
||||
is(reg.quotaUsageCheckCount, 0, "No quota usage check yet");
|
||||
|
||||
// Make sure our loads encode the specific
|
||||
const debugTag = `err=${name}&fault=${iFault + 1}`;
|
||||
|
@ -194,17 +198,23 @@ async function do_fault_injection_test({
|
|||
}
|
||||
|
||||
await unregisteredPromise;
|
||||
is(reg.unregistered, true, "registration should not exist.");
|
||||
is(reg.unregistered, true, "registration should be unregistered");
|
||||
|
||||
//is(reg.quotaUsageCheckCount, 1, "Quota usage check must be started");
|
||||
await quotaUsageCheckFinishPromise;
|
||||
|
||||
if (consumeQuotaOrigin) {
|
||||
// Check that there is no longer any storage usaged by the origin in this
|
||||
// case.
|
||||
const originUsage = await get_qm_origin_usage(TEST_ORIGIN);
|
||||
ok(originUsage > 0, "origin should still have usage until mitigated");
|
||||
ok(
|
||||
is_minimum_origin_usage(originUsage),
|
||||
"origin usage should be mitigated"
|
||||
);
|
||||
|
||||
if (consumeQuotaOrigin === SAME_GROUP_ORIGIN) {
|
||||
const sameGroupUsage = await get_qm_origin_usage(SAME_GROUP_ORIGIN);
|
||||
ok(sameGroupUsage > 0, "same group should still have usage for now");
|
||||
ok(sameGroupUsage === 0, "same group usage should be mitigated");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,6 +226,8 @@ add_task(async function test_navigation_fetch_fault_handling() {
|
|||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.serviceWorkers.mitigations.bypass_on_fault", true],
|
||||
["dom.serviceWorkers.mitigations.group_usage_headroom_kb", 5 * 1024],
|
||||
["dom.quotaManager.testing", true],
|
||||
// We want the temporary global limit to be 10 MiB (the pref is in KiB).
|
||||
// This will result in the group limit also being 10 MiB because on small
|
||||
// disks we provide a group limit value of min(10 MiB, global limit).
|
||||
|
@ -223,6 +235,10 @@ add_task(async function test_navigation_fetch_fault_handling() {
|
|||
],
|
||||
});
|
||||
|
||||
// Need to reset the storages to make dom.quotaManager.temporaryStorage.fixedLimit
|
||||
// works.
|
||||
await qm_reset_storage();
|
||||
|
||||
const quotaOriginVariations = [
|
||||
// Don't put us near the storage limit.
|
||||
undefined,
|
||||
|
|
|
@ -94,7 +94,18 @@ async function unregisterAll() {
|
|||
*/
|
||||
function makeRandomBlob(size) {
|
||||
const arr = new Uint8Array(size);
|
||||
window.crypto.getRandomValues(arr);
|
||||
let offset = 0;
|
||||
/**
|
||||
* getRandomValues will only provide a maximum of 64k of data at a time and
|
||||
* will error if we ask for more, so using a while loop for get a random value
|
||||
* which much larger than 64k.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions
|
||||
*/
|
||||
while (offset < size) {
|
||||
const nextSize = Math.min(size - offset, 65536);
|
||||
window.crypto.getRandomValues(new Uint8Array(arr.buffer, offset, nextSize));
|
||||
offset += nextSize;
|
||||
}
|
||||
return new Blob([arr], { type: "application/octet-stream" });
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче