let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helper_localStorage.js", this);
/* import-globals-from helper_localStorage.js */
// We spin up a ton of child processes.
requestLongerTimeout(4);
/** *Verifythebasicsofourmulti-e10slocalStoragesupport.Wearefocusedon *whiteboxtestingtwothings.Whenthisisbeingwritten,broadcastfiltering *isnotinplace,butthetestisintendedtoattempttoverifythatits *implementationdoesnotbreakthings. * *1)ThatpagesseethesamelocalStoragestateinatimelyfashionwhen *engaginginnon-conflictingoperations.Wearenottestingracesor *conflictresolution;thespecdoesnotcoverthat. * *2)Thattherearenoedge-casesrelatedtowhentheStorageinstanceis *createdforthepageortheStorageCachefortheorigin.(StorageCacheis *whatactuallybackstheStoragebindingexposedtothepage.)This *mattersbecausethefollowingreasonscanexistforthemtobecreated: *-Preload,onthebasisofknowingtheoriginuseslocalStorage.The *interestingedgecaseiswhenwehavethesameoriginopenindifferent *processesandtheoriginstartsusinglocalStoragewhenitdidnot *before.Preloadwillnothaveinstantiatedbindings,whichcouldimpact *correctness. *-ThepageaccessinglocalStorageforreadorwritepurposes.Thisisthe *obvious,boringone. *-Thepageaddinga"storage"listener.Thisislessobviousand *interactswiththepreloadedge-casementionedabove.Thepageneedsto *hear"storage"eventsevenifthepagehasnottouchedlocalStorage *itselfanditsoriginhadnothingstoredinlocalStoragewhenthepage *wascreated. * *Weusethesamesimplechildpageinalltabsthat: *-canbeinstructedtolistenforandrecord"storage"events *-canbeinstructedtoissueaseriesoflocalStoragewrites *-canbeinstructedtoreturnthecurrententirelocalStoragecontents * *Weopenthe5followingtabs: *-Opena"writer"tabthatdoesnotlistenfor"storage"eventsandwill *issueonlywrites. *-Opena"listener"tabinstructedtolistenfor"storage"events *immediately.Weexpectittocaptureallevents. *-Openan"reader"tabthatdoesnotlistenfor"storage"eventsandwill *onlyissuereadswheninstructed. *-Opena"lateWriteThenListen"tabthatinitiallydoesnothing.Wewill *latertellittoissueawriteandthenlistenforeventstomakesureit *capturesthelaterevents. *-Open"lateOpenSeesPreload"tabafterwe'vedoneeverythingandensurethat *itpreloads/precachesthedatawithoutushavingtouchedlocalStorageor *addedaneventlistener.
*/
add_task(async function () {
await SpecialPowers.pushPrefEnv({
set: [ // Stop the preallocated process manager from speculatively creating // processes. Our test explicitly asserts on whether preload happened or // not for each tab's process. This information is loaded and latched by // the StorageDBParent constructor which the child process's // LocalStorageManager() constructor causes to be created via a call to // LocalStorageCache::StartDatabase(). Although the service is lazily // created and should not have been created prior to our opening the tab, // it's safest to ensure the process simply didn't exist before we ask for // it. // // This is done in conjunction with our use of forceNewProcess when // opening tabs. There would be no point if we weren't also requesting a // new process.
["dom.ipc.processPrelaunch.enabled", false], // Enable LocalStorage's testing API so we can explicitly trigger a flush // when needed.
["dom.storage.testing", true],
],
});
// Ensure that there is no localstorage data or potential false positives for // localstorage preloads by forcing the origin to be cleared prior to the // start of our test.
await clearOriginStorageEnsuringNoPreload(HELPER_PAGE_ORIGIN);
// Make sure mOriginsHavingData gets updated.
await triggerAndWaitForLocalStorageFlush();
// Sanity check that preloading did not occur in the tabs.
await verifyTabPreload(writerTab, false, HELPER_PAGE_ORIGIN);
await verifyTabPreload(listenerTab, false, HELPER_PAGE_ORIGIN);
await verifyTabPreload(readerTab, false, HELPER_PAGE_ORIGIN);
// We expect the writer tab to have the correct state because it just did the // writes. We do not perform a sentinel-check because the writes should be // locally available and consistent.
await verifyTabStorageState(writerTab, initialWriteState, noSentinelCheck); // We expect the listener tab to have heard all events despite preload not // having occurred and despite not issuing any reads or writes itself. We // intentionally check the events before the state because we're most // interested in adding the listener having had a side-effect of subscribing // to changes for the process. // // We ensure it had a chance to hear all of the events because we told // recordTabStorageEvents to listen for the given sentinel. The state check // then does not need to do a sentinel check.
await verifyTabStorageEvents(
listenerTab,
initialWriteMutations,
initialSentinel
);
await verifyTabStorageState(listenerTab, initialWriteState, noSentinelCheck); // We expect the reader tab to retrieve the current localStorage state from // the database. Because of the above checks, we are confident that the // writes have hit PBackground and therefore that the (synchronous) state // retrieval contains all the data we need. No sentinel-check is required.
await verifyTabStorageState(readerTab, initialWriteState, noSentinelCheck);
// - Issue second set of writes from lateWriteThenListen // This tests that our new tab that begins by issuing only writes is building // on top of the existing state (although we don't verify that until after the // next set of mutations). We also verify that the initial "writerTab" that // was our first tab and started with only writes sees the writes, even though // it did not add an event listener.
// Verify the writer tab saw the writes. It has to wait for the sentinel to // appear before checking.
await verifyTabStorageState(writerTab, lateWriteState, lateWriteSentinel); // Wait for the sentinel event before checking the events and then the state.
await verifyTabStorageEvents(
listenerTab,
lateWriteMutations,
lateWriteSentinel
);
await verifyTabStorageState(listenerTab, lateWriteState, noSentinelCheck); // We need to wait for the sentinel to show up for the reader.
await verifyTabStorageState(readerTab, lateWriteState, lateWriteSentinel);
// - Issue last set of writes from writerTab.
info("last set of writes"); const lastWriteSentinel = "lastWrite"; const lastWriteMutations = [
["lastStays", "20", null],
["lastDeleted", "21", null],
["lastClobbered", "lastPre", null],
["lastClobbered", "lastPost", "lastPre"],
["lastDeleted", null, "21"],
]; const lastWriteState = Object.assign({}, lateWriteState, {
lastStays: "20",
lastClobbered: "lastPost",
});
// The writer performed the writes, no need to wait for the sentinel.
await verifyTabStorageState(writerTab, lastWriteState, noSentinelCheck); // Wait for the sentinel event to be received, then check.
await verifyTabStorageEvents(
listenerTab,
lastWriteMutations,
lastWriteSentinel
);
await verifyTabStorageState(listenerTab, lastWriteState, noSentinelCheck); // We need to wait for the sentinel to show up for the reader.
await verifyTabStorageState(readerTab, lastWriteState, lastWriteSentinel); // Wait for the sentinel event to be received, then check.
await verifyTabStorageEvents(
lateWriteThenListenTab,
lastWriteMutations,
lastWriteSentinel
);
await verifyTabStorageState(
lateWriteThenListenTab,
lastWriteState,
noSentinelCheck
);
// - Force a LocalStorage DB flush so mOriginsHavingData is updated. // mOriginsHavingData is only updated when the storage thread runs its // accumulated operations during the flush. If we don't initiate and ensure // that a flush has occurred before moving on to the next step, // mOriginsHavingData may not include our origin when it's sent down to the // child process.
info("flush to make preload check work");
await triggerAndWaitForLocalStorageFlush();
// - Open a fresh tab and make sure it sees the precache/preload
info("late open preload check"); const lateOpenSeesPreload = await openTestTab(
HELPER_PAGE_URL, "lateOpenSeesPreload",
knownTabs, true
);
await verifyTabPreload(lateOpenSeesPreload, true, HELPER_PAGE_ORIGIN);
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.