Greasemonkey: Laufzeit des Dokumentstartskripts unterstützen

Erstellt am 25. Juli 2017  ·  17Kommentare  ·  Quelle: greasemonkey/greasemonkey

Unterstützen Sie document-start für @run-at .

Siehe #2483 für weitere Details. Dies kann "unmöglich" sein.

Alle 17 Kommentare

Sie können die Eigenschaft run_at des Manifestschlüssels content_scripts .

Ich habe das Mitleid mit Chrome vor 4 Jahren mit Ihnen geteilt. Jetzt nochmal für Firefox. 😭.

Ich möchte meinen Vorschlag in https://bugs.chromium.org/p/chromium/issues/detail?id=257956 umformulieren

tabs.insertCSS/executeScript sollte CSS/JS einfügen, bis die URL des Tabs nicht leer ist (nicht null, nicht undefiniert, nicht leerer String ""), und abgebrochen werden, wenn der Tab entfernt/geändert wird

Die WebExtension-APIs sollten verbessert werden.

@iology Warum hast du meinen Vorschlag abgelehnt? Es ist vollkommen gültig. Außerdem kann man einfach das Inhaltsskript verwenden, um Skript-Tags in das Dokument einzufügen, das die Benutzerskripts enthält.

Folgendes soll mit meiner Methode erklären, wie das geht: (sollte zuverlässig funktionieren)

/**
 * <strong i="8">@typedef</strong> UserScript
 * <strong i="9">@property</strong> {Object} header The parsed header of a script
 * <strong i="10">@property</strong> {String} script The raw script data
 * <strong i="11">@property</strong> {String} type The script media type (in case a script is WebAssembly
 *                         or something other than JavaScript)
 */

/** The load state of this script. Used by the `matches()` function */
const READY_STATE = document.readyState;

(async () => {
    (await (browser.storage.local.get({scripts: []}) // Excuse this horrible code style
        .then(ret => ret.scripts)))                  // of combining `await` and `.then()`
        .forEach(/* <strong i="12">@param</strong> {UserScript} script */ script => {
            if (matches(script.header)) {
                let scriptTag = document.createElement("script");
                scriptTag.setAttribute("type", script.type)
                scriptTag.textContent = script.script;
                document.appendChild(scriptTag);
            }
        });
})();

/**
 * Checks if this script matches this page and @run-at property.
 * 
 * <strong i="13">@param</strong> {Object} scriptHeader The parsed header of a script
 * <strong i="14">@return</strong> {boolean} `true` if this page matches, `false` otherwise
 */
function matches(scriptHeader) {
    // Uses window.location and READY_STATE.
    // TODO: Implement
}

@ExE-Boss Wenn Sie Skripte aus dem Erweiterungsspeicher abrufen, wäre ein Teil der Seite bereits geladen.

Das ist mir bewusst, aber ich sehe keine andere Möglichkeit, dies zu tun, da WebExtensions von Natur aus asynchron sind.

@ExE-Boss, es gibt einen Bugzilla, https://bugzilla.mozilla.org/show_bug.cgi?id=1332273 , der gut vorankommt und dazu beitragen sollte, das @document-start-Problem zu lösen. Ob es für FF57 landen wird, bin ich mir nicht sicher.

Das ist mir bewusst, aber ich sehe keine andere Möglichkeit, dies zu tun, da WebExtensions von Natur aus asynchron sind.

@ExE-Boss Das ist buchstäblich das Problem, das wir zu lösen versuchen.

Ich versuche es auch zu lösen, aber meine Lösung funktioniert wirklich nur gut genug für #2525, da zu diesem Zeitpunkt die gesamte Seite vollständig geladen ist.

Violentmonkey hat dieses Problem auch, nicht sicher, welche schwarze Magie Tampermonkey verwendet, aber es ist in der Lage, Skripte zuverlässig auf dem echten document-start zu injizieren.

Tampermonkey 2.9 und früher war GPL-3.0 und wurde auf GitHub veröffentlicht . Ich habe versucht, es zu untersuchen, und zuerst dachte ich, es würde sync XHR verwenden , aber nachdem ich es ein wenig untersucht habe, habe ich keine Ahnung, wie es das erreicht, aber es tut es irgendwie, weil die Unterstützung dafür in Version 2.6 hinzugefügt wurde .2767 .

Sehen Sie hier, warum Tampermonekey Closed Source wurde:

Ich bin nicht an Piraterie interessiert, es wird nicht allzu schwer sein, die Logik von Tampermonkey umzukehren, aber das ist nicht legal.

@Sxderp Das ist nur für Firefox 57, dieser Fehler könnte in 58+ noch behoben sein.

Zu Ihrer Information, Tampermonkey ist auch beim Dokumentstart nicht zuverlässig. Es gibt eine "sofortige" Injektionsoption (die extrem hackig ist), die die Dinge beschleunigt, aber auf einfachen Seiten wie xkcd.com erhalte ich immer noch einen Flash, bevor mein CSS (das immer beim Start des Dokuments injiziert wird) geladen wird. Ich bekomme auch gelegentlich einen Flash auf anderen Seiten.

Das Umkehren des Codes von Tampermonkey ist keine Möglichkeit, dies herauszufinden. Außerdem können die von ihnen verwendeten Methoden in ihren Foren gefunden werden, die von anderen Benutzern vorgeschlagen wurden. Das Kopieren einer Methode ist kein Copy-Vio, sondern nur das Kopieren des Codes selbst.

Aber wir wissen, dass es eine unvollkommene Lösung ist, und wir wollen eine perfekte.

Wenn eine Methode gefunden wird, mit der dies funktioniert, könnte es für ein Skript eine Möglichkeit geben, zumindest eine Teilmenge seiner Konfigurationsoptionen synchron zu lesen? Ein Beispiel für die Art von Problemen, die dadurch gelöst werden könnten, finden Sie unter https://github.com/ccd0/4chan-x/issues/1627. Hier muss ich etwas Code auf der Seite deaktivieren, aber ich möchte auch eine Option haben, den Code nicht zu deaktivieren. Und viele Benutzer löschen localStorage am Ende jeder Browsersitzung.

Wenn eine Methode gefunden wird, mit der dies funktioniert, könnte es für ein Skript eine Möglichkeit geben, zumindest eine Teilmenge seiner Konfigurationsoptionen synchron zu lesen?

Kurzfristig nicht. Es gibt keine Möglichkeit, synchron mit dem (get|set)Value-Speicher zu kommunizieren. Vielleicht eine Art Injektion von GM, bei der Variablen mit Konfigurationswerten in den globalen Geltungsbereich des Skripts eingefügt werden. Das ist das Beste, was mir einfällt, und das ist nicht sehr schön.

Vielleicht eine Art Injektion von GM, bei der Variablen mit Konfigurationswerten in den globalen Geltungsbereich des Skripts eingefügt werden. Das ist das Beste, was mir einfällt, und das ist nicht sehr schön.

Vermutlich wäre es Teil des GM Objekts. Etwas wie GM.initValues.yourVariable .

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen