Perché window (e unsafeWindow) non sono gli stessi di un userscript come di un tag ?

Stavo affrontando un problema mentre sviluppavo questo piccolo userscript . Quando volevo bloccare ogni XMLHttpRequest dal sito Web in esecuzione con il mio script, non stava accadendo nulla (almeno con Chrome):

 function main() { // Override XHR.open with a custom function window.XMLHttpRequest.prototype.open = function() { // Nothing... so it's supposed to block every xhr.open() call } } main(); 

Stessa cosa quando si sostituisce la window con unsafeWindow .

Tuttavia, quando ho usato questo piccolo trucco, tutto ha funzionato come un fascino:

 // No more call to main(), and: var script = document.createElement("script"); script.textContent = "(" + main.toString() + ")();"; document.body.appendChild(script); 

Ogni chiamata a xhr.open viene sostituita dalla mia funzione personalizzata, non più AJAX.

Quindi suppongo che l’elemento della window non sia lo stesso quando viene chiamato main dall’interno dello script rispetto a quando viene chiamato da un contenitore . Qualcuno può spiegarmi perché?

Vedi “Gli script utente di Chrome sono separati dallo spazio dei nomi globale come gli script di Greasemonkey?” . Sia gli script userscripts / content-script di Chrome che gli script Greasemonkey sono isolati dal javascript della pagina. Questo viene fatto per aiutarti a impedirti di essere hackerato, ma riduce anche i conflitti e gli effetti collaterali inaspettati.

Tuttavia, i metodi sono diversi per ogni browser …

Firefox:

  1. Esegue script in una sandbox XPCNativeWrapper , a meno che @grant none sia in vigore (a partire da GM 1.0).
  2. Avvolge lo script in una funzione anonima per impostazione predefinita.
  3. Fornisce una unsafeWindow per accedere al javascript della pagina di destinazione. Ma attenzione che è ansible per i webmaster ostili seguire unsafeWindow utilizzo di unsafeWindow non unsafeWindow nel contesto del copione e quindi ottenere privilegi elevati per farvi fuggire.

Cromo:

  1. Esegue script in un “mondo isolato” .
  2. Avvolge lo script in una funzione anonima.
  3. Blocca severamente qualsiasi accesso al JS della pagina da parte dello script e viceversa.
    Le versioni recenti di Chrome forniscono ora un object denominato unsafeWindow , per compatibilità molto limitata, ma questo object non fornisce alcun accesso al JS della pagina di destinazione. È lo stesso della window nell’ambito dello script (che non è la window dell’ambito della pagina).

Detto questo, la versione del tuo script che usava unsafeWindow dovrebbe funzionare su / in Firefox se implementata correttamente. Potrebbe funzionare utilizzando l’estensione Tampermonkey su Chrome, ma non lo verificherò in questo momento.

Quando fai quel “trucco” ( var script = document.createElement("script"); ... ), stai iniettando il codice nella pagina di destinazione. Ciò scavalca la sandbox ed è l’unico modo su un normale userscript di Chrome affinché uno script possa interagire con il JS della pagina.

Vantaggi dell’iniezione:

  1. L’unico modo per gli utenti non-Tampermonkey di accedere agli oggetti o alle funzioni fornite dalla pagina di destinazione.
  2. Quasi sempre completamente compatibile tra Chrome, Firefox, Opera, ecc. (IE è, come sempre, qualcos’altro).
  3. Spesso è più facile eseguire il debug dell’intero script; gli strumenti di sviluppo funzionano normalmente.

Injection inconvenienti:

  1. Lo script, almeno le parti iniettate, non può utilizzare i privilegi avanzati (in particolare il dominio incrociato) forniti dalle funzioni GM_ , in particolare GM_xmlhttpRequest() .
    Nota che al momento Chrome supporta solo GM_addStyle , GM_xmlhttpRequest , GM_log e GM_openInTab , completamente, in modo nativo.
    Tampermonkey supporta GM_ funzioni GM_ quasi completamente, tuttavia.

  2. Può causare effetti collaterali o conflitti con il JS della pagina.

  3. L’uso di librerie esterne introduce ancora più conflitti e problemi di temporizzazione. Non è neanche lontanamente facile come @require .
    @require , esegue anche il JS esterno da una copia locale – velocizzando l’esecuzione e tutto tranne eliminando la dipendenza da un server esterno.

  4. La pagina può vedere, utilizzare, modificare o bloccare lo script.

  5. Richiede JS per essere abilitato. Firefox Greasemonkey, in particolare, può essere eseguito su una pagina che ha bloccato JS. Questo può essere una manna dal cielo su pagine gonfie, schifose e / o invadenti.