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);

mything.js sieht so aus:

window.mything = {thing: true};
console.log(window);

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.

    – Rob W

    12. September 2012 um 21:01 Uhr

Benutzer-Avatar
nynexman4464

Sie können nicht, nicht direkt. Von dem Inhaltsskriptdokumentation:

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

Benutzer-Avatar
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

  1. Fügen Sie Ihr Skript hinzu content_scripts.
  2. 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:

  1. Fügen Sie 2 Skripte hinzu content_scriptsz.B inject.js und script.js
  2. Das inject Skript wird die volle erhalten Absolute URL des script.js Datei und lade sie:
;(function() {
  const b = typeof browser !== 'undefined' ? browser : chrome

  const script = document.createElement('script')
  script.src = b.runtime.getURL('script.js')
  document.documentElement.appendChild(script)
})()
  1. Dein script.js enthält Ihren Hauptcode:
;(function() {
  // your main code here
  window.foo = 'bar'
})()

Safari

Es ist Firefox sehr ähnlich.

  1. Erstellen Sie 2 Javascript-Dateien, z inject.js und script.js
  2. Das inject Skript wird die volle erhalten Absolute URL des script.js Datei und lade sie:
;(function() {
  const script = document.createElement('script')
  script.src = safari.extension.baseURI + 'script.js'
  document.documentElement.appendChild(script)
})()
  1. Dein script.js enthält Ihren Hauptcode:
;(function() {
  // your main code here
  window.foo = 'bar'
})()

Quellcode

Siehe vollständigen Code hier: https://github.com/brunolemos/simplified-twitter

  • Ich habe es in Firefox mit dem Befehl cloneInto geschafft: developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/… In Chrome geht das leider nicht…

    – Mladen Mihajlovic

    27. August 2019 um 12:53 Uhr

  • 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

Benutzer-Avatar
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:

var foo = 'bar'
document.dispatchEvent(new CustomEvent('_save_OG_Editor', {
  'detail': {
    'my_event_data': foo
  }
}))

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”.

Benutzer-Avatar
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.

Benutzer-Avatar
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

1015240cookie-checkKann das Fensterobjekt von einer Chrome-Erweiterung geändert werden? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy