mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-07 11:48:19 +02:00
Storage events are fired either directly after getting response from synchronous SetItem call or through observers. When a new onstorage event listener is added, we sycnhronously register an observer in the parent process. There's always only one observer actor per content process. PBackgroundLSDatabase is now managed by a new PBackgroundLSObject protocol. PBackgroundLSObject is needed to eliminate the need to pass the principal info and document URI everytime a write operation occurs. Preparation of an observer shares some states with preparation of a datastore, so common stuff now lives in LSRequestBase and preparation of a datastore now implements a nested state machine. This patch was enhanced by asuth to drop observers only when the last storage listener is removed. EventListenerRemoved is invoked on any removal, not just the final removal, so we need to make sure it's the final removal before dropping observer.
68 lines
1.7 KiB
HTML
68 lines
1.7 KiB
HTML
<h1>Here a tracker!</h1>
|
|
<script>
|
|
|
|
if (window.opener) {
|
|
SpecialPowers.wrap(document).userInteractionForTesting();
|
|
localStorage.foo = "opener" + Math.random();
|
|
// Don't call window.close immediatelly. It can happen that adding the
|
|
// "storage" event listener below takes more time than usual (it may need to
|
|
// synchronously subscribe in the parent process to receive storage
|
|
// notifications). Spending more time in the initial script can prevent
|
|
// the "load" event from being fired for the window opened by "open and test".
|
|
setTimeout(() => {
|
|
window.close();
|
|
}, 0);
|
|
}
|
|
|
|
if (parent) {
|
|
window.onmessage = e => {
|
|
if (e.data == "test") {
|
|
let status;
|
|
try {
|
|
localStorage.foo = "value" + Math.random();
|
|
status = true;
|
|
} catch (e) {
|
|
status = false;
|
|
}
|
|
|
|
parent.postMessage({type: "test", status }, "*");
|
|
return;
|
|
}
|
|
|
|
if (e.data == "open") {
|
|
window.open("localStorage.html");
|
|
return;
|
|
}
|
|
|
|
if (e.data == "open and test") {
|
|
let w = window.open("localStorage.html");
|
|
w.addEventListener("load", _ => {
|
|
let status;
|
|
try {
|
|
localStorage.foo = "value" + Math.random();
|
|
status = true;
|
|
} catch (e) {
|
|
status = false;
|
|
}
|
|
|
|
parent.postMessage({type: "test", status }, "*");
|
|
}, {once: true});
|
|
}
|
|
};
|
|
|
|
window.addEventListener("storage", e => {
|
|
let fromOpener = localStorage.foo.startsWith("opener");
|
|
|
|
let status;
|
|
try {
|
|
localStorage.foo = "value" + Math.random();
|
|
status = true;
|
|
} catch (e) {
|
|
status = false;
|
|
}
|
|
|
|
parent.postMessage({type: "test", status: status && fromOpener }, "*");
|
|
});
|
|
}
|
|
|
|
</script>
|