Proposez un plan de travail sur la façon d'exécuter les scripts utilisateur, bien sûr inconnu avant l'exécution. Compatible avec les trois runAt times - de manière critique document_start
.
Voir https://github.com/arantius/greasemonkey/tree/8a255bde1aa6312715740fd0157d582a2d6cb183 pour mes recherches jusqu'à présent, où l'approche est :
tabs.executeScript()
pour lancer chaque script utilisateur.Cela "fonctionne", sauf qu'il n'y a aucun événement que j'ai encore trouvé à observer qui fonctionne pour les trois temps d'exécution. Il y a webNavigation
de onBeforeNavigate
qui est en fait trop tôt , il (comme son nom l'indique) se déclenche avant la navigation, lorsque le document en cours est toujours actif. Mais le point suivant est onCommitted
, et à ce stade, il est trop tard pour commencer, les scripts en ligne ont déjà été exécutés.
Rechercher:
webRequest
au lieu de webNavigation
. Cela nous donne-t-il une idée de l'heure de début ?Re : https://bugzilla.mozilla.org/show_bug.cgi?id=1332273#c8
J'aimerais pouvoir stocker (en arrière-plan) un blob, obtenir plus tard (seulement) son URL et transmettre cette URL (de manière synchrone) au(x) script(s) de contenu, mais je ne connais aucun moyen de faire l'une de ces choses.
Je n'ai pas réglé tous les détails moi-même, mais je pense que la page d'arrière-plan pourrait stocker des blobs dans IndexedDB, puis les convertir en URI de blobs via URL.createObjectURL() au démarrage et les transmettre à l'API de configuration synchrone hypothétique, puis peut-être les charger via
IndexedDB n'est-il pas désactivé en mode de
Je ne pense pas que cela affecte le(s) script(s) d'arrière-plan ?
Ceci est possible en utilisant un script de contenu qui s'exécute à document_start
et ressemble à ceci : (ne fonctionnera peut-être pas pour les onglets déjà chargés, utilisez jQuery pour cela)
// execute `document_start` scripts here...
document.addEventListener("DOMContentLoaded", event => {
// execute `document_end` scripts here...
});
window.addEventListener("load", event => {
// execute `document_idle` scripts here...
});
ou quelque chose comme ça : (peut-être plus sujet aux erreurs)
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...
}
Une autre façon consiste à utiliser trois scripts de contenu distincts, chacun d'eux s'exécutant à un moment différent.
Pour cela, le manifest.json
contient les éléments suivants : (garantit de fonctionner probablement (peut avoir une condition de concurrence))
"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"]
}
]
Il est également possible d'utiliser jQuery, ce qui pourrait être le moyen le moins sujet aux erreurs, mais tout cela nécessite des tests approfondis : (encore une fois, fonctionne à document_start
mais doit être associé à jQuery)
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);
}
Tel qu'il est écrit, cette question est trop large. Je divise cela en problèmes distincts pour être suivis plus facilement :