Greasemonkey: In Frames ausführen

Erstellt am 21. Sept. 2017  ·  48Kommentare  ·  Quelle: greasemonkey/greasemonkey

Greasemonkey 4 erkennt ab heute nur Navigationsereignisse auf der obersten Ebene, wendet also effektiv @noframes auf jedes Skript an.

Hilfreichster Kommentar

Hallo,
Wirst du das Problem beheben? Es ist ein ziemlich alter Fehler und wirkt sich auf alle Skripte aus, die auf der iframe-Struktur basieren ...

Alle 48 Kommentare

webNavigation.onCommitted "sieht" die anfängliche Frame-Erstellung / Seitenrendering nicht, aber wenn die Frame-Navigation an einer anderen Stelle als der anfänglichen Seite erfolgt, wird der Listener sie abfangen. Wenn Optionen den Schlüssel 'allFrames': true das Problem _etwas_ gelöst. Bei jedem Frame in der statischen HTML-Seite wird das Skript eingefügt, obwohl Sie dann Probleme beim Abgleich von Ursprung/URL haben. Wenn ein Frame mit Javascript erstellt wird, wird das Skript außerdem nicht injiziert.

Die einfachste Lösung, die mir einfällt, wäre, webNavigation.onCommitted durch webRequest.onResponseStarted mit einem Filter von {'urls': ['<all_urls>'], 'types': ['main_frame', 'sub_frame']} zu ersetzen.

Ich habe einige begrenzte Tests durchgeführt und es waren keine weiteren Änderungen erforderlich. Ich konnte ein Skript innerhalb eines Frames und einen mit Javascript erstellten Frame ausführen.

@arantius Pläne, den Fix von @Sxderp zusammenzuführen ?

Dies betrifft Szenarien, in denen die Iframes ursprungsübergreifende Objekte sind, sodass es unmöglich ist, Änderungen vorzunehmen, ohne GM auf diesen bestimmten Iframes auszuführen.

Vielen Dank !

Habe das verpasst, werde demnächst nachschauen.

Nur eine Beobachtung beim Testen alter Skripte, weiß nicht, ob es hilft...

Bei einem Skript, das auf einem iframe funktionieren soll,
es sieht so aus, als ob es die Änderungen auf der Seite ausführt,
wird dann aber wieder auf die unveränderte Seite aktualisiert.

Ich kann das Flackern nur sehen, wenn ich die Seite sehr schnell aktualisiere.

Nur eine Beobachtung beim Testen alter Skripte, weiß nicht, ob es hilft...

Liegt das an meinem Patch oder an der freigegebenen Version?

Ugh, ich glaube, es war die Version 4.0...
ICH WAR @4.1b3, aber für die Tests bin ich mir ziemlich sicher, dass ich die Release-Version neu installiert habe (bis jetzt!)

Gleiches hier mit iframes, wie es Eselce beschreibt. In gewisser Weise wird es ausgeführt, aber dann gestoppt, nachdem der iframe oder die Seite geladen wurde.

Wenn ich dieses Skript injiziere, bekomme ich nur 1 und "self !== top":

console.log('1');
if (self !== top) {
   console.log('self !== top');
   setTimeout(function() {
      console.log('Timeout');
   }, 2000);  
} else {
   console.log('self === top');
}

"Timeout" wird im Log nicht angezeigt, ebensowenig alle Funktionen und Bindungen.

Ich verwende 4.1b3.

Ich habe das gleiche Problem mit GM 4.0 auf Quantum. Ich habe ein sehr einfaches Dummy-Beispiel mit zwei Seiten geschrieben: main.html und framed.html und einem GM-Skript, das auf jeder Seite geladen wird und die URL der Seite ausgibt, auf der es geladen wird.

Meistens erhalte ich nur Benachrichtigungen über main.html , aber in etwa 5 % der Fälle, insbesondere wenn ich F5 gedrückt halte, erhalte ich möglicherweise auch eine Benachrichtigung über framed.html .

Gibt es einen Hack, um GM 4.0 zuverlässig zu zwingen, innerhalb von iframes auszuführen, bis ein Patch veröffentlicht ist?

Ich habe gerade herausgefunden, dass Userscripts in <embed src="..."> zuverlässig ausgeführt werden, aber nicht in <iframe src="..">
Ich habe ein kleines Testskript geschrieben:
https://openuserjs.org/scripts/cuzi/iframe_embed_Test_Greasemonkey_4

Noch ein paar Details: In manchen Fällen werden meine Skripte komplett im Frame ausgeführt (aber die Ansicht wird später von Seitenskripten überschrieben und so).
Manchmal werden die synchronen Teile meines Skripts beendet, aber die asynchronen Teile werden plötzlich durch Seitenaktivität unterbrochen...
Ich hoffe, das hilft!

Hat jemand mehr Infos dazu?

Nur eine kurze Zusammenfassung dieses Threads (Problem):

  • Vergiss die meisten Postings, sie gelten nicht
  • Wahrscheinlich werden die Skripte ausgeführt immer (aber nicht bis zum Ende)
  • Leider wird die Seite später aktualisiert - Layout wird neu berechnet, Ausführung abgebrochen
  • Dies gilt hauptsächlich (aber nicht vollständig) für asynchrone Teile der Skripte

Ich interessiere mich nicht so sehr für diese Interna, aber wahrscheinlich ist jemand...

Als vorübergehende Lösung habe ich Iframes gegen Einbettungen ausgetauscht ( Beispielskript ), was funktioniert, um ein Skript zu erhalten, das dem auszulösenden Frame entspricht (Gutschrift an @cvzi für die <embed src="..."> funktioniert). .

Es ist erwähnenswert, dass Violentmonkey und Tampermonkey in eingebetteten Frames problemlos funktionieren. Da VM Open Source ist, sehen Sie vielleicht, wie sie es gemacht haben?

Leider verwenden Violentmonkey und Tampermonkey immer noch das alte GM_-Namensschema für die speziellen Funktionen, daher sind Skripte noch nicht portabel.

https://github.com/greasemonkey/gm4-polyfill

Tampermonkey => GM.* ruft an, wenn nicht angegeben
Violentmonkey => GM.* ruft
Greasemonkey -3.17 / FF -56.0 => GM.* ruft
Greasemonkey 4.0+ / FF 57.0+ => eingebaute GM.* Anrufe

// <strong i="11">@grant</strong>        GM.getValue
// <strong i="12">@grant</strong>        GM.setValue
// <strong i="13">@require</strong>      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// <strong i="14">@grant</strong>        GM_getValue
// <strong i="15">@grant</strong>        GM_setValue

Wurde der Fix von @Sxderp schon in den Hauptzweig integriert? Wenn nicht, wie kann ich seine Gabel einbauen?

Wurde der Fix von @Sxderp schon in den Hauptzweig integriert? Wenn nicht, wie kann ich seine Gabel einbauen?

  1. Nein hat es nicht.
  2. Leider ist dies einer meiner PRs, den ich nicht mit Master synchronisiert habe und daher nicht umbasiert wurde. Der Branche selbst fehlen also einige der aktuellen Änderungen.
  3. Auch die in den PR-Kommentaren vorgeschlagenen Änderungen habe ich nie umgesetzt. Ehrlich gesagt, diese Änderungen _sollten_ nicht erforderlich sein, aber da Mozilla ständig die Dinge vermasselt, sind die Änderungen erforderlich.
  4. Wenn Sie es trotzdem verwenden möchten (nicht empfohlen), können Sie die folgenden Schritte ausführen.

  1. git clone -b use-on-response-started-for-execute --single-branch https://github.com/Sxderp/greasemonkey.git [1]
  2. Führen Sie ./package.sh Dadurch wird eine XPI-Datei erstellt.
  3. Gehen Sie in Firefox zu about:config und setzen Sie xpinstall.signatures.required auf false
  4. Gehen Sie in Firefox zu about:addons , klicken Sie auf das Zahnrad und wählen Sie dann aus Datei installieren.
  5. Wählen Sie das in Schritt 2 erstellte XPI aus.

[1] Wenn Ihre Version von git die Flags -b und / oder --single-branch (ältere Version von git) nicht unterstützt, können Sie git clone https://github.com/Sxderp/greasemonkey.git und git checkout use-on-response-started-for-execute .

Hallo,
Wirst du das Problem beheben? Es ist ein ziemlich alter Fehler und wirkt sich auf alle Skripte aus, die auf der iframe-Struktur basieren ...

Zur Erinnerung, dass wir morgen den 13. März haben (siehe Firefox 59.0 )...

Ich möchte auf @Sxderp verweisen:

webNavigation.onCommitted "sieht" die anfängliche Frame-Erstellung / Seitenrendering nicht, aber wenn die Frame-Navigation an einer anderen Stelle als der anfänglichen Seite erfolgt, wird der Listener sie abfangen. Wenn die Optionen den Schlüssel 'allFrames': true enthalten, ist das Problem etwas gelöst. Bei jedem Frame in der statischen HTML-Seite wird das Skript eingefügt, obwohl Sie dann Probleme beim Abgleich von Ursprung/URL haben. Wenn ein Frame mit Javascript erstellt wird, wird das Skript außerdem nicht injiziert.

Tatsächlich habe ich den Beweis, dass (auf meinem System) der Listener executeUserscriptOnNavigation zuverlässig mit chrome.webNavigation.onCommitted aufgerufen wird, so dass chrome.tabs.executeScriptInFrame mit den richtigen frameId aufgerufen wird . Warum löst das nicht alle unsere Probleme mit Rahmen? Wir sollten nicht chrome.webRequest.onResponseStarted brauchen, um auf einen iframe zu reagieren! (Oder meintest du, es reagiert auf das Ereignis, aber der Rahmen ist nicht sichtbar?) Es heißt definitiv...

Gibt es einen bekannten Fehler bei chrome.tabs.executeScriptInFrame und frameId ? Vor Jahren gab es Probleme, aber jetzt sind sie behoben. all_frames ist nicht gesetzt, daher sollte frameId gültig sein. Die Einstellung der Option matchAboutBlank auf true scheint eine Rolle zu spielen (sonst hat executeScript einen Fehler zurückgegeben <unavailable> ), obwohl ich das nicht ganz verstanden habe about:blank Zeug (wo ist es?)...

Irgendwelche Ideen?

Merkmale? Dies ist eine grundlegende Funktionalität, die von Anfang an fehlt ... Ich hoffe, ich habe das falsch interpretiert.

@Eselce , das ist lange her und ich bin mir nicht sicher, ob ich mich ganz daran erinnere, was ich meinte, aber ich werde es versuchen. Außerdem gilt dies nur, wenn mein Verständnis des GM 3.x-Frame-Matchings richtig ist. Das heißt, jeder Frameursprung+Pfad wird einzeln abgeglichen, um zu bestimmen, welche Skripts ausgeführt werden müssen. NICHT nur das übergeordnete Dokument.

Nun zum Thema. Als ich meine ersten Tests durchführte, hatte ich eine statische Seite mit einem gleichen Ursprungs-Frame und einem Remote-Frame. Beim ersten Laden der Seite konnte ich den onCommitted Callback nur einmal auslösen. Es wurde für das Hauptdokument ausgelöst, aber für keinen der statischen Frames im Dokument [1]. Somit würden ihnen keine Skripte injiziert.

Wenn ich jedoch nach dem anfänglichen Laden einen der Frames veranlassen würde, irgendwo zu "navigieren", würde der onCommitted Callback aufgerufen und Skripte wurden an der neuen Position in den Frame eingefügt.

Es wurde versucht, die Optionstaste all_frames zu verwenden, um das obige Problem zu umgehen. Während die Verwendung des Schlüssels dazu führte, dass die Skripts in die Frames auf der Seite eingefügt wurden, bestand der offensichtliche Mangel darin, dass Ursprung und Pfad des Frames nicht richtig mit dem übereinstimmen, auf dem das Skript ausgeführt werden sollte oder nicht.

Nebenbei erwähnte ich auch, dass die Verwendung des all_frames Schlüssels keine Skripte in von Javascript erstellte Frames injizieren würde.

[1] Ob dieses Problem noch besteht, weiß ich nicht. Wenn ich mich erinnere, war dieses Problem in FF 52 ESR nicht vorhanden, aber in 56 (57?) (daher Regression). Vielleicht wurde es behoben.

Ich stimme dir in fast allen Punkten zu.

Und Sie haben Recht, dass jeder Frame separat zugeordnet wird, als ob es ein ganzer Tab wäre (mit seinem eigenen window und seinem eigenen document , eingebettet in einen Frame).

Nun, ich habe fast immer die gleiche Menü-/Rahmenstruktur verwendet, also sollte ich vielleicht eine andere testen.

Meinst du mit "es feuerte" den reinen Ruf des Hörers?

Wie gesagt, ich bin auf einige Beispiele gestoßen, bei denen executeScript eine Fehlerbedingung erzeugt hat, aber der Listener wurde trotzdem aufgerufen.

all_frames kann nicht funktionieren, weil location falsch ist (andere window , andere document ). Übrigens: Das Menü behandelt nur die Mainframe-URLs jedes Tabs - wenn das Menü falsch ist, heißt das nicht, dass das Skript nicht aufgerufen wird...

Meinst du mit "es feuerte" den reinen Ruf des Hörers?

In dieser speziellen Nachricht meinte ich 'Die an onCommitted.addListener wurde aufgerufen.'.

Hallo,

Ich habe diesen Beitrag sorgfältig gelesen, aber ich verstehe nicht, wie Sie Ihre alternative Lösung für mein lokales Skript ".user.js" verwenden sollen. Wie kann ich Ihre Lösung anwenden? Entschuldigung, ich bin neu.

(Seit dem Update von Firefox wird ein generierter Popup-Iframe vom zusätzlichen Skript nicht mehr erkannt, aber wenn ich dasselbe Popup in einem neuen Fenster öffne, wird das Skript angewendet.)

Vielen Dank im Voraus für Ihre Hilfe

Sie haben das Problem genau beschrieben: Es ist, als wäre @noframes aktiviert. Die URL des Frame-Inhalts aktiviert Ihr Skript nicht richtig. Hoffentlich wird dies bald behoben (das Öffnen von Frames in zusätzlichen Fenstern ist nervig)...

Danke Eselce.
Und seit dem Update von Firefox bin ich immer verpflichtet, im Header alle auf der Zielseite bereits verwendeten Scripts '.js' (mit require) anzugeben. (einschließlich jquerry)
Und es ist nicht dasselbe.... Es erzeugt Fehler oder Konflikte.
Kennen Sie dieses Problem auch?

2945 enthält ein weiteres Beispiel für die Beobachtung, dass Skripte in Frames gestartet, aber nach einigen Millisekunden abgebrochen werden.

Ich zögere, die spezifischen URLs, die ich teste, anzugeben, da sie außerhalb meiner Kontrolle liegen, aber ich finde ein konsistentes, aber seltsames Verhalten, das ich weitergeben kann.

Ich habe eine Site, mit der ich interagieren muss. Es lädt zunächst ein Frameset/Frame mit rows="100%),0" (ein Frame zum Ausfüllen des Bildschirms) in einer anderen Domäne. Dieser Rahmen enthält einen Rahmensatz / 3 Rahmen innerhalb der Domäne des Zwischenrahmensatzes/Rahmens.

Einige der GM-Skripte der 1+3-Kind-Frames werden "auftauchen" und verschwinden dann nach dem Anfangszyklus - sie kehren nach keiner asynchronen Operation zurück. Das passt zu einem Verhalten, das in diesem Thread beschrieben wird. Beachten Sie, dass der "Blip" und das unten beschriebene Verhalten je nach Browser / GM-Version variieren, aber nicht zufällig sind; die Muster sind seltsam, aber für jedes gegebene Setup zu 100% wiederholbar.

  1. Das erste Frameset/Frame wird NIEMALS existieren. Ich habe versucht, das Frame-Tag sowohl über window.document als auch unsafeWindow.document zu trennen und neu aufzubauen, sowohl im Anfangszyklus als auch nach einer Verzögerung, aber nichts wird dazu führen, dass das GM-Skript dieses Frames jemals etwas an console.log meldet. (Das @include ist *, ohne @exclude oder andere URL-Filter.)
  2. Einige der späteren Verhaltensweisen unterscheiden sich zwischen Firefox 52.8 / GM 4.1 und Firefox 60.0 / GM 4.3, aber ich kann die GM-Skripte von Frames in jedem Fall zum "Blip" bringen, unabhängig davon, ob @includes *, keine anderen URL-Filter. Diese sollten niemals mit @noframes gesetzt werden. Ich habe überprüft, dass window.top!==window, dh der Browser weiß (oder wissen sollte), dass diese in Frames sind.
  3. In Firefox 52.8 / GM 4.1 wird das nächste Frameset / 3 Frames IMMER existieren. In Firefox 60.0 / GM 4.3 "blip" sie beim anfänglichen Laden von Frames nicht.
  4. In Firefox 60.0 / GM 4.3 wird beim Klicken auf einen Link in einem der 3 Frames, der zu einem anderen der 3 Frames navigiert (über ein "target"-Attribut auf dem Ankerlink, kein Skript), "blip" - nicht die neue URL, sondern die alte URL für den navigierten Frame. (Dies ist einer der Frames, die beim ersten Laden in Element Nr. 3 blinzelten.)
  5. Hier ist der seltsamste Teil. In beiden Browser-Setups --- Nach den Schritten haben wir die erste Seite mit 2 Ebenen von Framesets, 4 Frames insgesamt, geöffnet und auf einen Link in einem Frame geklickt, um zu einem anderen Frame auf derselben Seite zu navigieren. Um dem Namen zu geben, hatte unser ursprünglich angezeigtes Frameset der zweiten Ebene die Frames "top.htm", "menu.htm" und "start,htm". Wir haben auf einen Link im Frame "menu.htm" geklickt, um den Frame mit "start.htm" zu veranlassen, zu "content.htm" zu navigieren, mit ähnlichem, aber leicht unterschiedlichem Verhalten pro Browser-Setup, wie oben erwähnt. Jetzt klicken wir auf einen Link innerhalb des Frames "content.htm", um innerhalb desselben Frames, derselben Domain zu navigieren.

An diesem Punkt wird das Skript für "content.htm" nicht nur "blip" ... es bleibt auch aktiv, nachdem ein GM.xmlHttpRequest abgeschlossen wurde - ein asynchrones Ereignis. Zu diesem Zeitpunkt ist "content.htm" nirgendwo auf der Browseranzeige zu sehen, aber sein Skript wird weiterhin ausgeführt.

Es scheint mir, dass der Grund dafür, dass GM-Skripte auf Seiten innerhalb von Frames nicht funktionieren, darin besteht, dass das Skript beim Entladen der Seite statt beim Laden der Seite geladen wird. Das Setzen von @run-at auf document-start und das Einfügen des Skripts in ein DOMContentReady-Ereignis von unsafeWindow.document brachte keine Verbesserung. (Wenn Sie es auf window.document setzen, wird das Ereignis nie ausgelöst.)

-Ryan

In Firefox 52.8 / GM 4.1 wird das nächste Frameset / 3 Frames IMMER existieren. In Firefox 60.0 / GM 4.3 "blip" sie beim anfänglichen Laden von Frames nicht.

Bei der Umstellung auf Firefox 57 hat Mozilla _etwas_ geändert. Was auch immer es war, es änderte (oder brach) die Art und Weise, wie Frames ausgelöst werden konnten. Darüber wurde in einer anderen Ausgabe kurz gesprochen. Als Ergebnis würden die Skripte beim anfänglichen Laden von Frames (57+) nicht ausgeführt.

Der eventuelle Wechsel zu userScript oder contentScript APIs sollte all dies sowieso lösen.

Die Leute sagen immer wieder, dass Violentmonkey weiterhin in Frames ausgeführt wird. VM trennt Userscripts nicht richtig vom Webseiteninhalt (CSPs blockieren Userscripts, Webseiten können globale Objekte umschreiben usw.), oder ich hätte Greasemonkey schon vor langer Zeit weggeworfen. Vielleicht sind dies verwandte Probleme, aber ich verwende Userscript-Engines, damit ich das Chrome von Firefox nicht tief genug erforschen muss, um es selbst herauszufinden.

Hmm, das ist ein schwieriges Problem, einige meiner Skripte funktionieren nicht mehr, weil sie nicht mit iframes arbeiten können. Es scheint also nicht wirklich möglich zu sein, das Problem zu beheben, und wir müssen Mozilla eine API implementieren? Gibt es nichts, was wir selbst tun können, wie einen Workaround? Ich muss nur einige Dinge mit einer Seite in einem iframe tun, oft sogar von derselben Domäne.

Meine eigene Problemumgehung besteht im Moment darin, Greasemonkey in oberen Frames und Violentmonkey in untergeordneten Frames auszuführen. Ich kann Tampermonkey nicht verwenden, weil es eine mehrdeutige hausgemachte Lizenz hat, aber wenn das für Sie kein Problem ist, funktioniert es möglicherweise besser oder auch nicht.

Beachten Sie, dass die VM das Skript im eigenen Kontext der Seite ablegt. Es ist wie UnsafeWindow von GM ohne das sichere Äquivalent. Eine der denkwürdigsten Zeiten, die ich hatte, war das Debuggen eines Skripts, bei dem der Seiteninhalt eine 'toJSON()"-Methode auf Array.prototype definiert hatte, wodurch JSON.stringify() ungültiges JSON in meinem Skript ausspuckte. Ich musste Fange diese defensiv ein und repariere sie, wie ich sie gefunden habe.

Ein weiteres großes Problem bei der VM besteht darin, dass sie die Inhaltssicherheitsrichtlinie der Inhaltsseite respektiert, sodass jede Anweisung, die Skriptquellen einschränkt, dazu führt, dass das VM-Skript nie ausgeführt wird. Sie können dies in der Browserkonsole (aber nicht in der Webkonsole) sehen. Deshalb kann ich VM nicht vollständig ausführen und einfach GM loswerden. Ich bin noch keinem Kind mit einem CSP-Set begegnet, aber wenn ich es tue, wird es völlig unbrauchbar sein.

@RyanHanekamp Danke für den Tipp! Vielleicht werde ich dann Violentmonkey für einige Skripte verwenden.

Hat Violent auch so etwas wie synchrones GM_getValue? Das ist ein weiteres problematisches Problem, das eine Menge Skripte im neuen Greasemonkey zerstört. Ich vertraue Greasemonkey jedoch aus verschiedenen Gründen immer noch am meisten, also werde ich es nicht verlassen.

Was Iframes betrifft, habe ich versucht, sie durch Objekt-Tags zu ersetzen, auf die man anscheinend direkt mit Javascript zugreifen kann, wie folgt:

myObject= document.createElement('object');
myObject.setAttribute('id', 'myObject'); 
document.body.appendChild(myObject);
myObject.setAttribute('src', 'https://example.com');

Dann, sobald das Objekt geladen ist:
document.querySelector('#myObject').contentDocument.defaultView.document.querySelectorAll('someElementInsideObjectPage')
Zumindest funktioniert das bei mir in einem Skript, bei dem sich das Objekt auf demselben Host befindet wie die Hauptseite. Sie können auch Nachrichten von und zu ( ... contentDocument.defaultView.postMessage('hello, object') ) dem Objekt senden.

Ich bin kein VM-Experte, aber ich glaube, dass es zumindest den größten Teil der ursprünglichen GM_*-API implementiert. Ich würde jedoch denken, dass es besser ist, Ihre Skripte auf asynchrone Weise anzupassen, als langfristig auf eine synchrone Plattform zurückzugreifen. Nach meinem Verständnis hat Greasemonkey dies als Leistungssteigerung innerhalb des neuen Quantum-Frameworks getan, das keine synchronen Aufrufe zwischen Hintergrund- und Inhaltsskripten zulässt.

Was die Objektlösung angeht, wird sie mein spezielles Problem nicht lösen, aber ich bin froh, dass andere sie nützlich gefunden haben. Abgesehen vom Marshalling von CSS / Properties / etc und dafür, dass es sowohl mit Frames als auch mit Iframes funktioniert, muss ich Objekte in einem Capture-Prozess als potenziell unsicher herausfiltern. Es gibt Möglichkeiten, all diese Probleme zu umgehen, aber VM war die einfachere Übergangszeit, bis GM endlich tut, was es verspricht.

Wenn Sie einen Frame/Iframe gleichen Ursprungs haben, können Sie auch direkt auf dessen Inhalt zugreifen. Der schwierigere Teil ist Cross-Origin, weshalb ich Userscripts innerhalb des Frames benötige. Es richtet einen window.postMessage()-Kanal ein, um mit dem übergeordneten Fenster zu kommunizieren.

@RyanHanekamp Gut zu wissen, dass Violent Monkey immer noch das alte, einfache GM_* hat. Ich wünschte wirklich, Greasemonkey hätte den alten, synchronen GM_getValue aus Gründen der Abwärtskompatibilität zusätzlich zur neuen Version beibehalten. Ich könnte versuchen, die neue asynchrone Funktion in einem neuen Skript zu implementieren, aber ich bin kein Programmierer und bin mir nicht sicher, ob ich das zum Laufen bringen könnte. Und ich bin sicherlich nicht in der Lage, die Verwendung des alten GM_getValue in einem alten Skript von 2000 Zeilen, das ich online gefunden habe, umzugestalten ... so viele Skripte sind jetzt kaputt.

Ich verstehe, warum Gewalt die bessere Option für Sie war. Hoffen wir, dass Anthony oder Sxderp oder jemand anderes herausfindet, wie man dies schließlich implementiert. Ich wünschte wirklich, ich könnte etwas beitragen, aber ich bin ein absoluter Laie.

Oh, Sie können direkt auf den Inhalt eines Iframes gleichen Ursprungs zugreifen (ohne postMessage etc.)? Ich erinnere mich, dass ich viel Zeit damit verbracht habe, einen Weg zu finden, aber es schien nicht möglich. Deshalb bin ich auch auf postMessage umgestiegen.

Frames und iframes verfügen über eine contentWindow-Eigenschaft, die der window-Eigenschaft entspricht. Beide verfügen über eine Dokumenteneigenschaft für den Zugriff auf das DOM.

Der schwierigste Teil bei der Arbeit mit iframes (auf demselben Ursprung) besteht darin, zu erkennen, wann der Inhalt geladen wird, da Sie bis dahin keine Kniebeugen ausführen können. onload funktioniert nicht, wie es aussieht. Firefox bietet ein DOMFrameContentLoaded-Ereignis, das für JEDEN geladenen Frame ausgelöst wird, einschließlich Enkel-/Urenkel- usw. Frames, die Sie mit der event.target-Eigenschaft an das ursprüngliche Frame-/iframe-Element anpassen können. Wenn Sie den Inhalt des Frames/Iframes steuern, können Sie ihn auch mit postMessage oder dem Aufruf einer globalen Methode für das window.parent-Objekt mit dem übergeordneten Objekt zurücksprechen.

Apropos ... das ist eine mögliche Problemumgehung für dieses Problem. Wenn es eine Möglichkeit gibt oder geben könnte, ein GM-Skript zu codieren, um ein Benutzerskript manuell in eine domänenübergreifende Fensterreferenz einzufügen, würde es für den Benutzerskript-Ersteller viel mehr Codierung erfordern, aber es könnte die Aufgabe erledigen. Das Muster würde auf DOMFrameContentLoaded hören, prüfen, ob event.target die erste Generation ist, und das Skript in diesem Fall manuell einfügen. (Angenommen, das Skript des Frames der ersten Generation kann DOMContentLoaded für Frames der zweiten Generation abhören und somit eine vollständige Kette erhalten.) Es gibt keine Möglichkeit, das Verhalten von @run-at dom-start zu erhalten, und es könnten auch Timing-Probleme auftreten. aber wir könnten diese wahrscheinlich für die meisten Anwendungsfälle umgehen.

Ich persönlich habe es aufgegeben, dass dieses Problem jemals gelöst wurde, und bin stattdessen dazu übergegangen, eine Erweiterung direkt zu codieren. Was in allen Frames gut funktioniert!

Der Unterschied zwischen Greasemonkey und Violentmonkey in diesem Punkt scheint darin zu bestehen, dass Violentmonkey von Inhaltsskripten ausgelöst wird, bei denen all_frames auf true gesetzt ist, während Greasemonkey keine Inhaltsskripte zur Installationszeit hat und sich ausschließlich auf die zweifelhafte Fähigkeit des Hintergrundskripts verlässt, zu schnüffeln, wenn a Der Rahmen der Registerkarte wurde navigiert. (Und Violentmonkey schlägt auf CSP-Seiten fehl, weil es vorübergehend ein SCRIPT-Tag einfügt, anstatt das weitaus sicherere tabs.executeScript() zu verwenden.)

Fügen Sie ein statisches Inhaltsskript mit all_frames, run_at start, passt auf alles ein, um den Hintergrundprozess für start / document.DOMContentLoaded / document.Idle zu benachrichtigen, um Benutzerskripte für jedes run_at auszulösen, und Sie können loslegen. Ein nicht trivialer, aber überschaubarer Arbeitsaufwand, um dieses Problem zu lösen. Ich würde es selbst reparieren, aber ich habe kein Interesse daran, durch Ihre Dev-Abhängigkeiten zu stapfen und könnte nur den Ausgabecode produzieren.

@RyanHanekamp

und sind stattdessen dazu übergegangen, eine Erweiterung direkt zu codieren. Was in allen Frames gut funktioniert!

Wären Sie bereit, Ihren Erweiterungscode zu teilen?

Meine Erweiterung ist nicht universell. Der Punkt ist, dass bei Verwendung eines statischen content_script im Manifest mit all_urls all_frames das Skript jedes Mal ausführen wird, wenn ein Frame geladen oder navigiert wird, und sogar den Code des Funktionskonstruktors unabhängig von der Inhaltssicherheitsrichtlinie der Seite gut auswerten kann.

Ich habe nicht mit programmatisch konstruierten Frames / Fenstern getestet, aber ich könnte mir vorstellen, dass sie unabhängig von der run_at-Einstellung bei der ersten Erstellung ausgeführt werden, da solche Frames zunächst leer erstellt und dann aufgefüllt werden - die Engine würde wahrscheinlich nur die anfängliche Erstellung sehen. Ich habe auch keine Daten getestet: URLs, die möglicherweise eine explizite Übereinstimmung erfordern - ich bin mir nicht sicher, ob all_urls sie abdeckt oder nur http/https.

Es muss möglicherweise auch keine statische content_script-Referenz sein, aber es scheint aus der Dokumentation unsicher zu sein, ob dynamisch aufgerufene Inhaltsskripts beim Navigieren auf der Seite automatisch geladen werden. Mein Eindruck ist, dass sie nur in aktuell übereinstimmende Tabs / Frames gemäß dem bereitgestellten Übereinstimmungsmuster injiziert werden und die Navigation keine erneute Injektion auslöst. Aber ich sehe keinen Nachteil darin, zu diesem Zweck ein statisches content_script zu verwenden.

Greasemonkey kann offensichtlich keine Benutzerskripte als statische Ressourcen in das Manifest aufnehmen, und Inhaltsskripte scheinen keinen direkten Zugriff auf tabs.executeScript zu haben (obwohl ich diesbezüglich kaum ein Experte bin, da ich erst seit ein paar Tagen bin), Ein Skript mit statischem Inhalt KANN jedoch den Hintergrundprozess mitteilen, um ihn wissen zu lassen, dass die FrameId navigiert wurde und zu welcher URL. Dies wäre zuverlässiger, als ich die in diesem Thread erwähnten Versuche wahrnehme, das richtige Ereignis in webRequest oder webNavigation einzuhaken. Das Signal vom statischen content_script wird zu dem Ereignis, nach dem wir suchen, um den Userscript-Loader/Injektor von Greasemonkey auszulösen.

Es würde möglicherweise eine Verzögerung für Benutzerskripte geben, die unbedingt run_at document_start MÜSSEN. Der Aufruf des Hintergrundskripts ist asynchron, und das Dokument wird zum Zeitpunkt des Aufrufs des Benutzerskripts verarbeitet. Dies ist möglicherweise der Grund, warum Violentmonkey ein temporäres Skript-Tag anstelle von tabs.executeScript verwendet, da die Skript-Tag-Injektion direkt aus dem content_script synchron erfolgen kann. Ich würde es als mühsam empfinden, die Unsicherheit des Dokumentstatus für run_at document_start umgehen zu müssen, aber es ist vorzuziehen, dass das Skript überhaupt nicht ausgeführt wird.

Greasemonkey ... KANN [ein Skript mit statischem Inhalt verwenden, um] den Hintergrundprozess zu benachrichtigen, um ihm mitzuteilen, dass die FrameId navigiert wurde und zu welcher URL ...

Dies ist, was wir früher gemacht haben, um .user.js Navigationen zu erkennen. Scheint eine naheliegende und gute Lösung zu sein: Erkennen Sie Inhalte, indem Sie ein Inhaltsskript ausführen!

Aber es stellte sich heraus, dass selbst Inhaltsskripte von Erweiterungen von CSP geknackt werden können (#2631 und http://bugzil.la/1267027 und http://bugzil.la/1411641).

Ich kann mein eigenes Plugin, einschließlich eines Function()-Konstruktors direkt im content_script, auf Firefox 60.0.1 und 52.8.1ESR mit dem folgenden CSP-Set ausführen:

Frame-src-Daten:; Objekt-src 'keine'; script-src 'keine'; style-src 'unsichere-inline'-Daten:; connect-src 'keine'; media-src 'keine';

2631 wurde geschlossen, anscheinend weil Firefox den zugrunde liegenden Fehler behoben hat. Der erste Bugzilla bezieht sich auf das Einfügen von script-Tags (die Violentmonkey-Methode), nicht auf das content_script selbst. Die zweite bezieht sich auf das Sandbox-Attribut für CSP, was nicht verwunderlich ist, da es die Domäne zwingt, einen Domänenabgleich nicht einmal mit sich selbst erfolgreich abzuschließen. Ein bisschen wie NaN!==NaN.

Als dies vor einigen Monaten zum ersten Mal eingereicht wurde, haben wir die Dinge anders gemacht. Heute verwenden wir webNavigation.onCommitted , um die Navigation zu erkennen, und in dem Test, den ich gerade

Hallo, ist das jetzt gelöst?

Ich konnte ein Skript, das ich für Tampermonkey erstellt habe, nicht auf einem iframe mit Greasemonkey starten.

Der Code zur Ausführung wurde von unserer Seite nicht verändert. Es sei denn, Mozilla hat an ihrer Seite etwas geändert, dies ist immer noch pleite. #2663 sollte es jedoch lösen.

Es ist erwähnenswert, dass Violentmonkey und Tampermonkey in eingebetteten Frames problemlos funktionieren.

Tampermonkey hat zumindest bei mir Probleme mit iframes in Chrome.

Es ist erwähnenswert, dass Violentmonkey und Tampermonkey in eingebetteten Frames problemlos funktionieren.

Tampermonkey hat zumindest bei mir Probleme mit iframes in Chrome.

Aber bei mir funktioniert es in Firefox Violentmonkey. Da frage ich mich, wie das dort funktionieren kann?

Mir ist gerade aufgefallen, dass ein Skript, das den alten Sync GM_GetValue verwendet, auch in Violentmonkey noch gut funktioniert. Wie ist das möglich? Ich dachte, Firefox hätte asynchrones GM.GetValue erzwungen? Ich bin jetzt so verwirrt: Vermutlich musste Violentmonkey etwas anderes opfern, um noch Sync und das andere Zeug zu unterstützen?

@Cerberus-tm Die Änderung in Firefox hat dazu geführt, dass Daten nur asynchron aus dem Erweiterungsspeicher oder dem Hintergrundkontext angefordert werden können (die Benutzerskripte selbst werden asynchron an das Inhaltsskript gesendet). Die Daten könnten jedoch synchron an Benutzerskripts bereitgestellt werden, wenn jedes GM4-Inhaltsskript die Daten, die für jedes auf dieser Seite geladene Benutzerskript gespeichert sind, im Inhaltsskript im Voraus abruft und zwischenspeichert.

Ein solcher Cache würde es dem Inhaltsskript ermöglichen, synchron auf die Datenanforderungen des Benutzerskripts zu antworten. Beim Implementieren eines Caches treten Probleme mit der Aufrechterhaltung der Konsistenz zwischen den verschiedenen Inhaltsskripten auf, aber das kann behoben werden, indem die Inhaltsskripte auf alle Änderungen am Erweiterungsspeicher von GM4 warten. Wenn ein Benutzerskript eine große Datenmenge speichert, erhöht das Zwischenspeichern in jedem Inhaltsskript, in dem das Benutzerskript ausgeführt wird, außerdem den für jedes Inhaltsskript erforderlichen Speicher erheblich.

TM und VM haben sich für etwas Ähnliches wie oben entschieden, um die Kompatibilität mit den ursprünglichen Greasemonkey-APIs nicht zu beeinträchtigen, als diese Userscript-Manager für Chrome implementiert wurden, was die gleichen Einschränkungen bzgl. asynchrone Kommunikation mit Erweiterungsspeicher usw. Da sie dies bereits für Chrome tun, gab es keinen Grund, sie bei der Implementierung für Firefox zu ändern.

So haben die FF57 cut-over zu WebExtensions zwingen , ein Umschreiben von GM, aber es hat nicht mit Gewalt die Annahme des asynchronen APIs für GM.getValue , GM.setValue usw. WebExtensions haben noch keinen Einsatz async-basierte APIs sind einfacher zu implementieren als synchrone, aber es war nicht erforderlich.

Persönlich denke ich, dass die Wahl und andere Entscheidungen, um die Kompatibilität zu unterbrechen, unglücklich waren/sind. Die fehlende Abwärtskompatibilität mit Skripten, die in GM3 einwandfrei liefen, und/oder Kompatibilität mit TM führten dazu, dass viele Leute sich entschieden, GM4 nicht zu verwenden. Meine Erfahrung ist, dass weit mehr als 30 der von mir verwendeten Benutzerskripte, die alle in GM3 gut funktionierten, mit GM4 nicht funktionieren (oder zumindest nicht funktionierten, bevor sie umgeschrieben wurden, um mit GM4 kompatibel zu sein). Es gibt immer noch 28 Benutzerskripte, die ich täglich benutze, die unter GM3 gut liefen, die mit GM4 nicht funktionieren.

Ich habe auf Stack Overflow eine Problemumgehung für dieses Problem gepostet, um zu Sie ein Greasemonkey/‌Tampermonkey/‌userscript auf einen iframe anwenden . Im Grunde warte ich darauf, dass der Frame geladen wird, und arbeite dann window.frames Array

Vielleicht könnte Greasemonkey eine ähnliche Lösung implementieren?

Es wäre toll, wenn wir auch ein GM.waitFor(css_selector, action_function) wie waitForKeyElements() hätten , aber das ist eine

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen