// To use this file, explicitly import it via: // // Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/dom/serviceworkers/test/browser_head.js", this);
// Find the current parent directory of the test context we're being loaded into // such that one can do `${originNoTrailingSlash}/${DIR_PATH}/file_in_dir.foo`. const DIR_PATH = getRootDirectory(gTestPath)
.replace("chrome://mochitests/content/", "")
.slice(0, -1);
// 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 use 15 pages (61440) which // rounds up to 64k. However, we also have to allow for the incremental // vacuum heuristic only firing if we have more than the growth increment's // worth of free pages, so we need to set the threshold at 32k * 3. const kMinimumOriginUsageBytes = 98304;
function getPrincipal(url, attrs) { const uri = Services.io.newURI(url); if (!attrs) {
attrs = {};
} return Services.scriptSecurityManager.createContentPrincipal(uri, attrs);
}
async function _qm_requestFinished(request) {
await new Promise(function (resolve) {
request.callback = function () {
resolve();
};
});
if (request.resultCode !== Cr.NS_OK) { thrownew RequestError(request.resultCode, request.resultName);
}
return request.result;
}
async function qm_reset_storage() { returnnew Promise(resolve => {
let request = Services.qms.reset();
request.callback = resolve;
});
}
async function get_qm_origin_usage(origin) { returnnew Promise(resolve => { const principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(origin);
Services.qms.getUsageForPrincipal(principal, request => {
info(`QM says usage of ${origin} is ${request.result.usage}`);
resolve(request.result.usage);
});
});
}
/** *ClearthegroupassociatedwiththegivenoriginviansIClearDataService.We *areusingnsIClearDataServiceherebecausensIQuotaManagerServicedoesn't *(directly)provideameansofclearingagroup.
*/
async function clear_qm_origin_group_via_clearData(origin) { const uri = Services.io.newURI(origin); const baseDomain = Services.eTLD.getBaseDomain(uri);
info(`Clearing storage on domain ${baseDomain} (from origin ${origin})`);
// Initiate group clearing and wait for it.
await new Promise((resolve, reject) => {
Services.clearData.deleteDataFromSite(
baseDomain,
{}, false,
Services.clearData.CLEAR_DOM_QUOTA,
failedFlags => { if (failedFlags) {
reject(failedFlags);
} else {
resolve();
}
}
);
});
}
/** *LookupthensIServiceWorkerRegistrationInfoforagivenSWdescriptor.
*/ function swm_lookup_reg(swDesc) { // Scopes always include the full origin. const fullScope = `${swDesc.origin}/${DIR_PATH}/${swDesc.scope}`; const principal = getPrincipal(fullScope);
async function createMessagingHelperTab(origin, channelName) { const pageUrlStr = `${origin}/${DIR_PATH}/empty_with_utils.html`;
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrlStr);
// For hygiene reasons we make sure the helper establishes its message channel // in a task distinct from any of the tasks that will initiate events.
await SpecialPowers.spawn(tab.linkedBrowser, [channelName], channelName => {
content.wrappedJSObject.setupMessagingChannel(channelName);
});
// 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;
}
/** *Performanavigation,waitinguntilthenavigationstops,thenreturning *the`textContent`ofthebodynode.Theexpectationisthiswillbeused *withServiceWorkersthatreturnabodythatindicatestheServiceWorker *providedtheresult(possiblyderivedfromtherequest)versusif *interceptiondidn'thappen.
*/
async function navigate_and_get_body(swDesc, debugTag) {
let pageUrlStr = `${swDesc.origin}/${DIR_PATH}/${swDesc.scope}`; if (debugTag) {
pageUrlStr += "?" + debugTag;
}
info(`Navigating to ${pageUrlStr}`);
const tabResult = await BrowserTestUtils.withNewTab(
{
gBrowser,
url: pageUrlStr, // In the event of an aborted navigation, the load event will never // happen...
waitForLoad: false, // ...but the stop will.
waitForStateStop: true,
},
async browser => {
info(` Tab opened, querying body content.`); const spawnResult = await SpecialPowers.spawn(browser, [], function () { const controlled = !!content.navigator.serviceWorker.controller; // Special-case about: URL's.
let loc = content.document.documentURI; if (loc.startsWith("about:")) { // about:neterror is parameterized by query string, so truncate that // off because our tests just care if we're seeing the neterror page. const idxQuestion = loc.indexOf("?"); if (idxQuestion !== -1) {
loc = loc.substring(0, idxQuestion);
} return { controlled, body: loc };
} return {
controlled,
body: content.document?.body?.textContent?.trim(),
};
});
function waitForUnregister(scope) { returnnew Promise(function (resolve) {
let listener = {
onUnregister(registration) { if (registration.scope !== scope) { return;
}
SWM.removeListener(listener);
resolve(registration);
},
};
SWM.addListener(listener);
});
}
// Be careful using this helper function, please make sure QuotaUsageCheck must // happen, otherwise test would be stucked in this function. function waitForQuotaUsageCheckFinish(scope) { returnnew Promise(function (resolve) {
let listener = {
onQuotaUsageCheckFinish(registration) { if (registration.scope !== scope) { return;
}
SWM.removeListener(listener);
resolve(registration);
},
};
SWM.addListener(listener);
});
}
function waitForServiceWorkerRegistrationChange(registration, callback) { returnnew Promise(function (resolve) {
let listener = {
onChange() {
registration.removeListener(listener); if (callback) {
callback();
}
resolve(callback ? callback() : undefined);
},
};
registration.addListener(listener);
});
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.