36

Tengo un script de Greasemonkey que funciona bien en Firefox y Opera. Sin embargo, me cuesta hacerlo funcionar en Chrome. El problema es inyectar una función en la página que puede invocarse mediante el código de la página. Esto es lo que estoy haciendo hasta ahora:funciones Inyectar JS en la página de un script de Greasemonkey en Chrome

En primer lugar, obtengo una referencia de ayuda para el unsafeWindow para Firefox. Esto me permite tener el mismo código para FF y Opera (y Chrome, pensé).

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

A continuación, inyectar una función en la página. Es realmente sólo un envoltorio muy delgada que no hace nada, pero la invocación de la función correspondiente en el contexto de mi guión GM:

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

Luego, está la función correspondiente a la derecha en mi guión:

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

pasado, Inyerto algo de HTML en la página con un enlace para invocar la función.

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

En resumen: En Firefox, cuando el usuario hace clic, lo que inyectaba enlace, se ejecutará la llamada de función en la unsafeWindow, lo cual dispara un tiempo de espera que invoca a la función correspondiente en el contexto de mi guión GM, que luego hace el procesamiento real. (Corrígeme si estoy equivocado aquí.)

En Chrome, acabo de recibir un "no detectada ReferenceError: setConfigOption no está definido" error. Y de hecho, ingresar "window.setConfigOption" en la consola produce un "indefinido". En Firebug y la consola de desarrollador de Opera, la función está ahí.

Quizás haya otra manera de hacerlo, pero algunas de mis funciones son invocadas por un objeto Flash en la página, lo que creo que hace necesario que tenga funciones en el contexto de la página.

Eché un vistazo rápido al alternatives to unsafeWindow en la wiki de Greasemonkey, pero todos se ven bastante feos. ¿Estoy completamente en el camino equivocado aquí o debería mirar más de cerca en estos?

RESOLUCIÓN: Seguí Max S.' advice y ahora funciona en Firefox y Chrome. Debido a las funciones que tenía que estar a disposición de la página tuvieron que llamar de nuevo en las normales, que se trasladó toda mi guión a la página, es decir que está completamente envuelto en la función que llamó 'main()'.

Para hacer que la fealdad adicional de ese truco sea un poco más soportable, al menos podría dejar de usar el uso de ventanas inseguras y envolver JSObject ahora.

todavía no he logrado conseguir el content scope runner del trabajo wiki de Greasemonkey. Debería hacer lo mismo y parece funcionar bien, pero mis funciones nunca son accesibles a los elementos <a> de la página, por ejemplo. Todavía no he descubierto por qué es eso.

Respuesta

58

La única manera de comunicarse con el código que se ejecuta en la página en Chrome es a través del DOM, por lo que tendrá que usar un truco como insertar una etiqueta <script> con su código. Tenga en cuenta que esto puede resultar problemático si su secuencia de comandos debe ejecutarse antes que cualquier otra cosa en la página.

EDIT: Así es como the Nice Alert extension hace esto:

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

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

He probado el 'corredor alcance el contenido' (que hace exactamente eso, si no me equivoco), y mientras que las funciones estaban disponibles para mi guión, que no parecía estar a disposición de la página (por ejemplo, un ancla etiqueta). ¿Tiene algún código de ejemplo o algo a lo que pueda vincular? No estoy muy preocupado por el orden de ejecución. Puedo evitarlo cuando consigo llamar a una función inyectada desde la página. :) –

+0

Orden de ejecución del script contenido se puede definir a través de declaración 'run_at' http://code.google.com/chrome/extensions/content_scripts.html – NVI

+0

re run_at: No estoy escribiendo una extensión de Chrome, aunque (y yo no pretendo, demasiado trabajo para mantener dos scripts). Esta es solo una secuencia de comandos de Greasemonkey que estoy tratando de hacer lo suficientemente compatible para que Chrome pueda hacer su 'auto-conversión' de scripts GM a extensiones. –

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?

Debe buscar, porque es la única opción disponible. Prefiero usar location hack.

myscript.user.js:

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

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

example.com/mypage.html

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

Claro, es feo. Pero está funcionando bien.


método Alcance Runner contenido, citado por Max S. es mejor que la ubicación de corte, debido a que es más fácil de depurar.

+0

¿Podría por favor publicar un ejemplo de cómo se puede usar para definir una función que pueda ser invocada por un ancla o un objeto Flash? –

+0

¿Qué quiere decir "por un ancla"? – NVI

15

tengo esto:

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

¡Este es genial! También acceso directo para personas que usan jQuery: 'function injectjs (link) { $ ('

Cuestiones relacionadas