36

Ho uno script Greasemonkey che funziona perfettamente in Firefox e Opera. Ho difficoltà a farlo funzionare su Chrome, comunque. Il problema sta iniettando una funzione nella pagina che può essere invocata dal codice dalla pagina. Ecco cosa sto facendo finora:Iniezione di funzioni JS nella pagina da uno script Greasemonkey su Chrome

Per prima cosa, ottengo un riferimento di supporto allo unsafeWindow per Firefox. Questo mi permette di avere lo stesso codice per FF e Opera (e Chrome, pensavo).

var uw = (this.unsafeWindow) ? this.unsafeWindow : window; 

Successivamente, inserisco una funzione nella pagina. E 'davvero solo un involucro molto sottile che non fa altro che invocare la funzione corrispondente nel contesto del mio script GM:

uw.setConfigOption = function(newValue) { 
    setTimeout(setConfigOption, 0, newValue); 
} 

Poi, c'è la funzione corrispondente diritto nel mio script:

setConfigOption = function(newValue) { 
    // do something with it, e.g. store in localStorage 
} 

scorso, Inserisco un codice HTML nella pagina con un link per richiamare la funzione.

var p = document.createElement('p'); 
p.innerHTML = '<a href="javascript:setConfigOption(1)">set config option to 1</a>'; 
document.getElementById('injection-point').appendChild(p); 

In sintesi: In Firefox, quando l'utente fa clic che iniettato link, eseguirà la chiamata di funzione sulla unsafeWindow, che poi innesca un timeout che richiama la funzione corrispondente nel contesto del mio script GM, che poi fa l'elaborazione vera e propria. (Correggimi se ho torto qui.)

In Chrome, ho appena ricevuto un errore "Uncaught ReferenceError: setConfigOption non definito". E infatti, inserire "window.setConfigOption" nella console produce un "indefinito". In Firebug e nella console di sviluppo di Opera, la funzione è disponibile.

Forse c'è un altro modo per farlo, ma alcune delle mie funzioni sono invocate da un oggetto Flash sulla pagina, che a mio avviso rende necessario disporre di funzioni nel contesto della pagina.

Ho dato una rapida occhiata allo alternatives to unsafeWindow sul wiki di Greasemonkey, ma sembrano tutti abbastanza brutti. Sono completamente sulla strada sbagliata qui o dovrei guardare più da vicino a questi?

RISOLUZIONE: Ho seguito Max S.' advice e ora funziona sia in Firefox che in Chrome. Poiché le funzioni che dovevo essere disponibile per la pagina dovevano richiamare quelle normali, spostai il mio intero script sulla pagina, cioè è completamente racchiuso nella funzione che chiamava 'main()'.

Per rendere un po 'più sopportabile la brutta cosa in più di questo hack, potrei almeno eliminare l'utilizzo di Windows non sicuro e spostarlo ora su JSObject.

Non sono ancora riuscito a ottenere il content scope runner dal wiki di Greasemonkey che funziona. Dovrebbe fare lo stesso e sembra funzionare bene, ma le mie funzioni non sono mai accessibili agli elementi <a> dalla pagina, ad esempio. Non ho ancora capito perché sia ​​così.

risposta

58

L'unico modo per comunicare con il codice in esecuzione sulla pagina in Chrome è attraverso il DOM, quindi dovrai usare un hack come inserire un tag <script> con il tuo codice. Tieni presente che questo potrebbe risultare difettoso se lo script deve essere eseguito prima di tutto il resto della pagina.

EDIT: Ecco come the Nice Alert extension fa questo:

function main() { 
    // ... 
    window.alert = function() {/* ... */}; 
    // ... 
} 

var script = document.createElement('script'); 
script.appendChild(document.createTextNode('('+ main +')();')); 
(document.body || document.head || document.documentElement).appendChild(script); 
+1

Ho provato il "content scope runner" (che fa esattamente questo, se non mi sbaglio), e mentre le funzioni erano disponibili per il mio script, non sembravano essere disponibili per la pagina (ad esempio un'ancora etichetta). Hai qualche codice di esempio o qualcosa a cui puoi collegarti? Non sono molto preoccupato per l'ordine di esecuzione. Posso aggirare il problema quando riesco a chiamare una funzione iniettata dalla pagina. :) –

+0

L'esecuzione di script di contenuto può essere definita tramite l'istruzione 'run_at' http://code.google.com/chrome/extensions/content_scripts.html – NVI

+0

re run_at: non sto scrivendo un'estensione di Chrome, tuttavia (e io non intendo, troppo lavoro per mantenere due script). Questo è solo uno script di Greasemonkey che sto cercando di rendere abbastanza compatibile in modo che Chrome possa fare la sua "auto-conversione" degli script GM alle estensioni. –

4

I took a quick look at the alternatives to unsafeWindow on the Greasemonkey wiki, but they all look pretty ugly. Am I completely on the wrong track here or should I look more closely into these?

Si dovrebbe guardare, perché è unica opzione disponibile. Preferirei usare location hack.

myscript.user.js:

function myFunc(){ 
    alert('Hello World!'); 
} 

location.href="javascript:(function(){" + myFunc + "})()" 

example.com/mypage.html

<script> 
myFunc() // Hello World! 
</script> 

Certo, è brutto. Ma sta funzionando bene.


Il metodo Content Scope Runner, menzionato da Max S., è migliore della modifica della posizione, perché è più facile eseguire il debug.

+0

Potresti per favore pubblicare un esempio di come può essere usato per definire una funzione che può essere invocata da un ancoraggio o da un oggetto Flash? –

+0

Cosa intendi con "un'ancora"? – NVI

15

ho questo:

contentscript.js:

function injectJs(link) { 
var scr = document.createElement('script'); 
scr.type="text/javascript"; 
scr.src=link; 
document.getElementsByTagName('head')[0].appendChild(scr) 
//document.body.appendChild(scr); 
} 

injectJs(chrome.extension.getURL('injected.js')); 

injected.js:

function main() { 
    alert('Hello World!'); 
} 

main(); 
+2

Questo è fantastico! Scorciatoia anche per le persone che usano jQuery: 'function injectjs (link) { $ ('

Problemi correlati