Entwickeln Sie einen Arbeitsplan für die Ausführung von Benutzerskripten, die natürlich erst zur Laufzeit bekannt sind. Kompatibel mit allen drei RunAt-Zeiten - kritisch document_start
.
Siehe https://github.com/arantius/greasemonkey/tree/8a255bde1aa6312715740fd0157d582a2d6cb183 für meine bisherigen Recherchen, wo der Ansatz ist:
tabs.executeScript()
auf, um jedes Benutzerskript abzufeuern.Dies "funktioniert", außer dass ich noch kein Ereignis gefunden habe, das für alle drei Laufzeiten funktioniert. Da ist webNavigation
's onBeforeNavigate
was eigentlich zu früh ist , es feuert (wie der Name schon sagt) vor der Navigation, wenn das aktuelle Dokument noch aktiv ist. Aber der nächste Punkt ist onCommitted
, und an diesem Punkt ist es zu spät für den Start, Inline-Skripte wurden bereits ausgeführt.
Forschen:
webRequest
statt webNavigation
. Gibt uns das einen Griff zur Startzeit?Betreff: https://bugzilla.mozilla.org/show_bug.cgi?id=1332273#c8
Ich möchte in der Lage sein, (im Hintergrund) einen Blob zu speichern, später (nur) seine URL zu erhalten und diese URL (synchron) an Inhaltsskripte weiterzugeben, aber ich kenne keine Möglichkeit, eines dieser Dinge zu tun.
Ich habe nicht alle Details selbst ausgearbeitet, aber ich denke, die Hintergrundseite könnte Blobs in IndexedDB speichern, sie dann zum Startzeitpunkt über URL.createObjectURL() in Blob-URIs konvertieren und sie an die hypothetische synchrone Konfigurations-API übergeben und dann vielleicht lade sie über
Ist IndexedDB im privaten Browsermodus deaktiviert ?
Ich glaube nicht, dass sich das auf die Hintergrundskripte auswirkt?
Dies ist möglich, indem Sie ein Inhaltsskript verwenden, das unter document_start
und ungefähr so aussieht: (funktioniert möglicherweise nicht für bereits geladene Tabs, verwenden Sie dafür jQuery)
// execute `document_start` scripts here...
document.addEventListener("DOMContentLoaded", event => {
// execute `document_end` scripts here...
});
window.addEventListener("load", event => {
// execute `document_idle` scripts here...
});
oder so ähnlich: (könnte fehleranfälliger sein)
let run = [false, false, false];
document_start();
if (document.readyState === "complete") {
document_idle();
} else if (document.readyState === "interactive") {
document_end();
}
document.onreadystatechange = () => {
switch (document.readyState) {
case "loading": break;
case "interactive": document_end();
case "complete": document_idle();
}
};
function document_start() {
if (run[0]) return;
run[0] = true;
// execute `document_start` scripts here...
}
function document_end() {
if (!run[0]) document_start();
if (run[1]) return;
run[1] = true;
// execute `document_end` scripts here...
}
function document_idle() {
if (!run[1]) document_end();
if (run[2]) return;
run[2] = true;
// execute `document_idle` scripts here...
}
Eine andere Möglichkeit besteht darin, drei separate Inhaltsskripte zu verwenden, von denen jedes zu einem anderen Zeitpunkt ausgeführt wird.
Dafür enthält das manifest.json
folgendes: (funktioniert wahrscheinlich (kann eine Race-Bedingung haben))
"content_scripts": [
{
"matches": ["<all_urls>"],
"run_at": "document_start",
"js": ["document_start_handler.js"]
},
{
"matches": ["<all_urls>"],
"run_at": "document_end",
"js": ["document_end_handler.js"]
},
{
"matches": ["<all_urls>"],
"run_at": "document_idle",
"js": ["document_idle_handler.js"]
}
]
Es ist auch möglich, jQuery zu verwenden, was möglicherweise der am wenigsten fehleranfällige Weg ist, aber dies alles erfordert umfangreiche Tests: (läuft wieder bei document_start
, muss aber mit jQuery gebündelt werden)
function document_start() {
// execute `document_start` scripts here...
}
function document_end() {
// execute `document_end` scripts here...
}
function document_idle() {
// execute `document_idle` scripts here...
}
// Use jQuery to execute all the functions:
document_start();
// `$(document).ready(document_end)` is deprecated since 3.0
$(document_end);
// jQuery used to have a method for this: `$(window).load(document_idle)`
if (document.readyState === "complete") {
document_idle();
} else {
$(window).on("load", document_idle);
}
Wie geschrieben, ist dieses Thema zu weit gefasst. Ich teile dies in separate Probleme auf, um leichter nachverfolgt zu werden: