Greasemonkey: WebExt : exécuter des scripts aux trois fois runAt

Créé le 27 févr. 2017  ·  6Commentaires  ·  Source: greasemonkey/greasemonkey

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 :

  • Utilisez un script d'arrière-plan. (Il aura accès au stockage/à toutes les API, où les scripts sont stockés, afin de pouvoir connaître le contenu des scripts à exécuter.)
  • Observer quelque chose ( quoi ? ) pour déclencher ..
  • .. appelez 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.

wontfix

Tous les 6 commentaires

Rechercher:

  • Observez webRequest au lieu de webNavigation . Cela nous donne-t-il une idée de l'heure de début ?
  • Injectez un script de contenu webext, à document_start, pour chaque page. Faites-lui savoir quels scripts exécuter, de manière synchrone. (Parce que tout ce qui est asynchrone nous pousserait au-delà 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 :

2525, #2526

Cette page vous a été utile?
0 / 5 - 0 notes