Kann das Fensterobjekt von einer Chrome-Erweiterung geändert werden? [duplicate]
Lesezeit: 8 Minuten
Ich möchte eine Chrome-Erweiterung erstellen, die ein neues Objekt enthält window. Wenn eine Webseite in einem Browser mit geladener Erweiterung angezeigt wird, möchte ich window.mything über Javascript verfügbar sein. Das window.mything Das Objekt wird einige Funktionen haben, die ich in der Erweiterung definieren werde, und diese Funktionen sollten aufrufbar sein console.log oder eine beliebige Javascript-Datei, wenn die Seite in einem Browser mit aktivierter Erweiterung angezeigt wird.
Ich konnte erfolgreich eine Javascript-Datei in die Seite einfügen, indem ich a verwendete Inhaltsskript:
var s = document.createElement("script");
s.src = chrome.extension.getURL("mything.js");
document.getElementsByTagName("head")[0].appendChild(s);
Immer wenn eine Seite geladen wird, sehe ich das Ganze window Objekt so, wie ich es in der Konsole erwarte. Allerdings kann ich nicht mit dem interagieren window.mything Objekt aus der Konsole. Es scheint, als hätte das injizierte Skript die Datei global nicht wirklich geändert window Objekt.
Wie kann ich die globale ändern window Objekt aus einer Chrome-Erweiterung?
Das ist unmöglich. Sehen Sie die richtige Konsole, wird das Skript wirklich ausgeführt (Dokument prüfen und nach Skript-Tag suchen / auf Syntaxfehler prüfen)? Das Skript wird sicherlich im Kontext der Seite ausgeführt und daher mything muss vorhanden sein.
Inhaltsskripte haben jedoch einige Einschränkungen. Sie können nicht:
Chrome.*-APIs verwenden (mit Ausnahme von Teilen der chrome.extension)
Verwenden Sie Variablen oder Funktionen, die auf den Seiten ihrer Erweiterung definiert sind
Verwenden Sie Variablen oder Funktionen, die von Webseiten oder anderen Inhaltsskripten definiert werden
(Betonung hinzugefügt)
Das window Objekt, das das Inhaltsskript sieht, ist nicht dasselbe window Objekt, das die Seite sieht.
Sie können jedoch Nachrichten über das DOM übergeben, indem Sie die verwenden window.postMessage Methode. Sowohl Ihre Seite als auch Ihr Inhaltsskript hören auf die Botschaft Ereignis und wann immer Sie anrufen window.postMessage von einem dieser Orte wird der andere es empfangen. Dort ist ein Beispiel dafür auf der Dokumentationsseite “Content Scripts”.
Bearbeiten: Sie könnten möglicherweise einige Methoden zur Seite hinzufügen, indem Sie ein Skript aus dem Inhaltsskript einfügen. Es wäre jedoch immer noch nicht in der Lage, mit dem Rest der Erweiterung zu kommunizieren, ohne etwas wie zu verwenden postMessageaber Sie könnten zumindest einige Dinge zu den Seiten hinzufügen window
var elt = document.createElement("script");
elt.innerHTML = "window.foo = {bar:function(){/*whatever*/}};"
document.head.appendChild(elt);
Danke, ich habe Ihren Vorschlag nicht wörtlich verwendet, aber das Konzept hat mir geholfen, mich auf das eigentliche Problem zu konzentrieren.
– Zach Rattner
12. September 2012 um 23:25 Uhr
Sie können auch eval(“window.foo = {bar:function(){/*whatever*/}};”);
– Benutzer
26. Mai 2014 um 16:22 Uhr
Das <script> element hack hat super funktioniert. Ich bin gespannt, ob diese Javascript-Tags ausgeführt werden, sobald sie hinzugefügt werden <head>auch wenn die Seite bereits geladen ist?
– cprcrack
22. Januar 2015 um 19:46 Uhr
Wenn es sich um ein Inline-Skript handelt, dh <script>//do something</script> dann ja, es wird sofort (synchron) ausgeführt. Wenn es sich um ein Remote-Skript handelt <script src="foo.js"></script> dann wird es ausgeführt, nachdem das Skript heruntergeladen wurde. Vor der Zugabe von async -Tag wäre dies eine gängige Methode, um zu verhindern, dass ein Skript-Download das Rendern der Seite blockiert.
– nynexman4464
28. Januar 2015 um 3:47 Uhr
Sie können die ändern window Objekt mit eigenen Mutatoren wie addEventListener. Keine Dokumentenelement-Injektion erforderlich.
– Josef Lust
23. Oktober 2017 um 11:28 Uhr
Bruno Lemos
Nachdem ich stundenlang verschiedene Versuche unternommen hatte und Sicherheitsproblemen wie CORS begegnet war, fand ich Möglichkeiten, die window Objekt an Chrome, Firefox und Safari. Sie müssen jeweils unterschiedliche Strategien anwenden:
Chrom
Fügen Sie Ihr Skript hinzu content_scripts.
Fügen Sie in Ihrer Skriptdatei a script auf die Seite und lassen Sie Ihren benutzerdefinierten Code inline ausführen. So was:
;(function() {
function script() {
// your main code here
window.foo = 'bar'
}
function inject(fn) {
const script = document.createElement('script')
script.text = `(${fn.toString()})();`
document.documentElement.appendChild(script)
}
inject(script)
})()
Feuerfuchs
Unter Firefox funktioniert die obige Lösung nicht aufgrund von a Content-Security-Policy Error. Aber die folgende Problemumgehung funktioniert derzeit zumindest vorerst:
Fügen Sie 2 Skripte hinzu content_scriptsz.B inject.js und script.js
Das inject Skript wird die volle erhalten Absolute URL des script.js Datei und lade sie:
Danke für die Lösung, ist das sicher? oder gibt es einen anderen sicheren Weg?
– Mohit Bhatia
18. Mai 2020 um 3:53 Uhr
das ist scheitern mit Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-2hqy/01Xj3kkdA60wVjY8N6m2WXv5URv1rhk3jCDyHY='), or a nonce ('nonce-...') is required to enable inline execution.
– Christian
26. August 2021 um 6:43 Uhr
Lucio Paiva
Wie andere bereits betont haben, werden Kontextskripte nicht im selben Kontext wie die Seite ausgeführt, um auf das richtige zuzugreifen windowmüssen Sie Code in die Seite einfügen.
Hier ist meine Meinung dazu:
function codeToInject() {
// Do here whatever your script requires. For example:
window.foo = "bar";
}
function embed(fn) {
const script = document.createElement("script");
script.text = `(${fn.toString()})();`;
document.documentElement.appendChild(script);
}
embed(codeToInject);
Sauber und einfach zu bedienen. Was auch immer Sie brauchen, um im Kontext der Seite ausgeführt zu werden, fügen Sie es ein codeToInject() (Sie können es nennen, wie Sie es bevorzugen). Das embed() function kümmert sich um das Verpacken Ihrer Funktion und das Senden zur Ausführung auf der Seite.
Was zum embed() Funktion ist es, a zu erstellen script -Tag auf der Seite und betten Sie die Funktion ein codeToInject() hinein als ein IIFE. Der Browser führt die neue Datei sofort aus script -Tag, sobald es an das Dokument angehängt wird, und Ihr eingefügter Code wird wie beabsichtigt im Kontext der Seite ausgeführt.
Eine Chrome-Erweiterung content_script läuft in einem eigenen Kontext, der vom Fenster getrennt ist. Sie können jedoch ein Skript in die Seite einfügen, sodass es im selben Kontext wie das Fenster der Seite ausgeführt wird, wie hier: Chrome-Erweiterung – Abrufen einer globalen Variable von einer Webseite
Ich konnte Methoden für das Fensterobjekt aufrufen und Fenstereigenschaften ändern, indem ich im Wesentlichen a hinzufügte script.js zum DOM der Seite:
var s = document.createElement('script');
s.src = chrome.extension.getURL('script.js');
(document.head||document.documentElement).appendChild(s);
s.onload = function() {
s.remove();
};
und Erstellen benutzerdefinierter Ereignis-Listener in dieser eingefügten Skriptdatei:
document.addEventListener('_my_custom_event', function(e) {
// do whatever you'd like! Like access the window obj
window.myData = e.detail.my_event_data;
})
und das Versenden dieses Ereignisses im content_script:
oder umgekehrt; Ereignisse versenden in script.js und hören Sie im content_script Ihrer Erweiterung darauf (wie der obige Link gut veranschaulicht).
Stellen Sie einfach sicher, dass Sie Ihr eingefügtes Skript in die Dateien Ihrer Erweiterung einfügen, und fügen Sie den Pfad der Skriptdatei zu Ihrer hinzu innen manifestieren "web_accessible_resources" oder Sie erhalten eine Fehlermeldung.
Hoffe das hilft jemandem \ (•◡•) /
Ich habe damit herumgespielt. Ich habe festgestellt, dass ich mit dem Fensterobjekt des Browsers interagieren kann, indem ich mein Javascript in einen window.location=-Aufruf verpacke.
var myInjectedJs = "window.foo='This exists in the \'real\' window object';"
window.location = "javascript:" + myInjectedJs;
var myInjectedJs2 = "window.bar="So does this.";"
window.location = "javascript:" + myInjectedJs2;
Es funktioniert, aber nur für die letzte Instanz von window.location, die festgelegt wird. Wenn Sie auf das Fensterobjekt des Dokuments zugreifen, hat es eine Variable “bar”, aber nicht “foo”.
010011100101
Dank der anderen Antworten hier verwende ich Folgendes:
((source)=>{
const script = document.createElement("script");
script.text = `(${source.toString()})();`;
document.documentElement.appendChild(script);
})(function (){
// Your code here
// ...
})
Funktioniert super, keine Probleme.
Josef Lust
Inhaltsskripte kann Anruf window Methoden, die dann verwendet werden können, um die zu mutieren window Objekt. Das ist einfacher als <script> Tag-Injection und funktioniert auch dann, wenn die <head> und <body> wurden noch nicht geparst (z. B. bei der Verwendung von run_at: document_start).
// In Content Script
window.addEventListener('load', loadEvent => {
let window = loadEvent.currentTarget;
window.document.title="You changed me!";
});
Dies scheint nur für vorhandene Variablen zu funktionieren, nicht für neue, kann das jemand überprüfen?
– Jdruwe
19. Februar 2020 um 17:21 Uhr
Dieses Fensterobjekt, auf das in diesem Skript verwiesen wird, ist Teil des Inhaltsskripts und nicht der einbettenden Seite, daher ist es nicht die richtige Lösung für die Frage
– Muhammad Usmann
29. August 2020 um 8:55 Uhr
Erweiterung und Seite verwenden unterschiedliche Kontexte, diese Antwort ist irreführend.
– brunocoelho
13. Januar um 22:32 Uhr
10152400cookie-checkKann das Fensterobjekt von einer Chrome-Erweiterung geändert werden? [duplicate]yes
Das ist unmöglich. Sehen Sie die richtige Konsole, wird das Skript wirklich ausgeführt (Dokument prüfen und nach Skript-Tag suchen / auf Syntaxfehler prüfen)? Das Skript wird sicherlich im Kontext der Seite ausgeführt und daher
mything
muss vorhanden sein.– Rob W
12. September 2012 um 21:01 Uhr