javascript firefox greasemonkey

javascript - ¿Cómo acceder a los objetos `window`(página de destino) cuando se establecen los valores @grant?



firefox greasemonkey (1)

Cuando establece un valor @grant distinto de ninguno, Greasemonkey activa su sandbox y Greasemonkey 2.0 cambió radicalmente el manejo inseguro de Windows .

Ahora, para crear o sobrescribir variables en el ámbito de la página de destino, debe elegir correctamente de un menú de técnicas. P.EJ:

Leer:

  • Una variable simple:

    Target page sets: var foo = "bar"; GM script can read: unsafeWindow.foo //-- "bar"

  • Un objeto simple:

    Target page sets: var obj = {A: 1}; GM script can read: unsafeWindow.obj //-- Object { A: 1 }

  • Un objeto complejo: esto no siempre es posible.

Llamar:

  • Una función simple:

    Target page sets: function func () {console.log (''Hi'');} GM script can call: unsafeWindow.func() //-- "Hi"

  • Una función compleja: esto no siempre es posible.

Para escribir / configurar:

  • Una variable simple:

    unsafeWindow.foo = "Apple";

  • Un objeto simple:

    var gmObject = {X: "123"}; unsafeWindow.obj = cloneInto (gmObject, unsafeWindow);

  • Una función simple:

    function gmFunc () { console.log ("Lorem ipsum"); //-- Can use GM_ functions in here! :) } unsafeWindow.func = exportFunction (gmFunc, unsafeWindow);

Considera este HTML:

<button id="helloBtn">Say "Hello".</button>

Y este javascript:

var simpleGlobalVar = "A simple, global var in the page scope."; var globalObject = {Letter: "A", Number: 2}; function simpleFunction () { console.log ("The target page''s simpleFunction was called."); } var sayHello = function() { console.log (''Hello.''); } document.getElementById (''helloBtn'').addEventListener (''click'', function () { sayHello (); } );

que puedes ver en vivo en esta página jsFiddle .

Si instala y ejecuta este script de Greasemonkey en esa página:

// ==UserScript== // @name _Demonstrate accessing target-page variables with @grant values set // @include http://fiddle.jshell.net/sepwL7n6/*/show/ // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js // @grant GM_addStyle // ==/UserScript== console.log ("*** Greasemonkey script start."); $("body").append (''<div id="gmArea">Added by Greasemonkey:<p></p></div>''); $("#gmArea > p:first").append (''<button id="gmShow">Access select target-page variables and functions</button>''); $("#gmArea > p:first").append (''<button id="gmChange">Change javascript things in the target-page scope.</button>''); $("#gmShow").click ( function () { //-- Access things from the target-page scope: console.log ("----------------"); console.log ("==> simpleGlobalVar is: ", unsafeWindow.simpleGlobalVar); console.log ("==> globalObject is: ", unsafeWindow.globalObject); console.log ("==> Calling target''s simpleFunction():"); unsafeWindow.simpleFunction (); //-- WARNING! This next technique is not robust, but works in some cases. console.log ("==> Calling target''s button''s click()."); unsafeWindow.document.getElementById (''helloBtn'').click (); } ); $("#gmChange").click ( function () { this.disabled = true; //-- Can only click once. unsafeWindow.simpleGlobalVar = "Simple var... Intercepted by GM!"; unsafeWindow.globalObject = cloneInto (gmObject, unsafeWindow); unsafeWindow.sayHello = exportFunction (sayHello, unsafeWindow); console.log ("==> Target page objects were changed."); } ); var gmMessageStr = "Function... Intercepted by GM, but also can use GM_ functions!"; function sayHello () { sayHello.K = (sayHello.K || 0) + 1; console.log (gmMessageStr); GM_addStyle (''body {background: '' + (sayHello.K % 2 ? "lime" : "white") + '';}''); } var gmObject = {message: "Object overridden by GM."};


Abra la consola y presione los botones y verá que el script GM puede leer y cambiar las variables y funciones de la página.

Notas:

  1. Todo esto es específico de Firefox .
  2. Para el código multiplataforma y para algunas situaciones complejas, puede usar la inyección de script en su lugar. Pero el código inyectado no puede acceder directamente a GM_ funciones GM_ .
  3. Tenga en cuenta que estas técnicas solo funcionan para variables y funciones de JavaScript que son globales.

Digamos que estoy trabajando con la siguiente página web:

<html> <body> <span id="click">click me</span> <script> var hello = function() { alert(''hello''); } document.getElementById(''click'').addEventListener(''click'', function(e) { hello(); }); </script> </body> </html>

y mi script de Greasemonkey es:

// ==UserScript== // @name My Script // @include http://example.com/hello.html // @version 1 // @grant none // ==/UserScript== window.hello = function() { alert(''goodbye''); }

Con el script Greasemonkey deshabilitado, al hacer clic en el elemento #click en la página se muestra la alerta ''hola''. Con el script habilitado, al hacer clic en el elemento se muestra la alerta de "adiós".

Suficientemente simple. La función hello de la página web está siendo reemplazada por la función en el script Greasemonkey.

Ahora digamos que quiero usar una API de Greasemonkey. Cuando configuro el valor @grant en un valor válido que no sea ''none'' (por ejemplo, // @grant GM_setClipboard ) [lo que hace que Greasemonkey ejecute el script como un "script de contenido", en lugar de en el alcance de la página como con ''none'' ], el script Greasemonkey no funciona.

window.hello ya no apunta al objeto correcto en la página.

Reemplazar window.hello con unsafeWindow.hello parece que funcionaría, pero en su lugar, se arroja el siguiente error en la consola JS:

Error: permiso denegado para acceder al objeto

¿Cómo puedo reescribir el script Greasemonkey mientras tengo @grant GM_setClipboard configurado para apuntar y reemplazar la función de hello original en la página?

Información del sistema:

  • Windows 7 de 64 bits
  • Firefox 32.0
  • Greasemonkey 2.2