如何设置@grant值时如何访问`window`(目标页面)对象? [英] How to access `window` (Target page) objects when @grant values are set?

查看:226
本文介绍了如何设置@grant值时如何访问`window`(目标页面)对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b

 < html> 
< body>
< span id =click>点击我< / span>
< script>
var hello = function(){
alert('hello');

$ b document.getElementById('click')。addEventListener('click',function(e){
hello();
});
< / script>
< / body>
< / html>

和我的Greasemonkey脚本是:

  // == UserScript == 
// @name My Script
// @include http://example.com/hello.html
/ / @version 1
// @grant none
// == / UserScript ==

window.hello = function(){
alert('goodbye' );

禁用Greasemonkey脚本,单击 #click页面上的元素显示hello警报。启用脚本后,单击该元素将显示再见提醒。



足够简单。网页中的 hello 函数正在被Greasemonkey脚本中的函数取代。



现在让我们来说说I想要使用Greasemonkey API。当我将 @grant 值设置为none以外的有效值(例如 // @grant GM_setClipboard )时这导致Greasemonkey作为内容脚本运行脚本,而不是像'none'那样在页面的范围内运行,Greasemonkey脚本无法运行。



window.hello 不再针对页面上的正确对象。



替换窗口.hello unsafeWindow.hello 看起来好像会起作用,但是在JS控制台中引发了下面的错误:


错误:拒绝访问对象的权限

在将 @grant GM_setClipboard 设置为target并替换页面上的原始 hello 函数时重写Greasemonkey脚本

系统信息:

$ ul

  • Windows 7 64位
  • Firefox 32.0
  • Greasemonkey 2.2 li>

    解决方案当您设置 @grant Greasemonkey激活它的沙盒,并且 Greasemonkey 2.0从根本上改变了unsafeWindow的处理方式



    现在,为了在目标页面范围内创建或覆盖变量,您必须从技术菜单中正确选择。 EG:

    阅读:




    • 变量:

       目标页面设置:var foo =bar; 
      GM脚本可以读取:unsafeWindow.foo // - bar


    • 一个简单的对象:

       目标页面集:var obj = {A:1}; 
      GM脚本可以读取:unsafeWindow.obj // - Object {A:1}





    打电话给一个复杂的对象: :




    • 一个简单的函数:

       目标页面设置:函数func(){console.log('Hi');} 
      GM脚本可以调用:unsafeWindow.func()// - Hi


    • 复杂的功能:


    • 写/设置:




      • 一个简单的变量

          unsafeWindow.foo =Apple; 


      • 一个简单的对象

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


      • 简单的功能: b

          function gmFunc(){
        console.log(Lorem ipsum);
        // - 可以在这里使用GM_函数! :)
        }
        unsafeWindow.func = exportFunction(gmFunc,unsafeWindow);







      • <看看这个HTML:

         < button id =helloBtn>说Hello。< / button> 

        而这个javascript:

          var simpleGlobalVar =页面范围内的一个简单的全局变量。 
        var globalObject = {Letter:A,Number:2};

        函数simpleFunction(){
        console.log(目标页面的simpleFunction被调用。


        var sayHello = function(){
        console.log('Hello。');

        $ b document.getElementById('helloBtn')。addEventListener('click',function(){
        sayHello();
        });

        您可以在 这个jsFiddle页面

        如果你安装并运行这个Greasemonkey脚本:

          // == UserScript == 
        // @name _Demonstrate访问目标页面具有@grant值的变量设置
        // @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脚本启动);
        $ b $(body)。append('< div id =gmArea>添加Greasemonkey:< p>< / p>< / div>');
        $(#gmArea> p:first)。append('< button id =gmShow>访问选择目标页面变量和函数< / button>');
        $(#gmArea> p:first)。append('< button id =gmChange>在目标页面范围内改变javascript的东西< / button>');

        $(#gmShow)。click(function(){
        // - 从目标页面范围访问事物:
        console.log( - ;
        console.log(==> simpleGlobalVar是:,unsafeWindow.simpleGlobalVar);
        console.log(= => globalObject is:,unsafeWindow.globalObject);
        console.log(==>调用目标的simpleFunction():);
        unsafeWindow.simpleFunction();

        // - 警告!下一个技巧不是很强大,但是在某些情况下可以使用
        console.log(==>调用目标按钮的click()。);
        unsafeWindow .document.getElementById('helloBtn')。click();
        });点击(函数(){
        this.disabled = true; // - 只能点击一次
        unsafeWindow.simpleGlobalVar = ();
        unsafeWindow.globalObject = cloneInto(gmObject,unsafeWindow);
        unsafeWindow.sayHello = exportFunction(sayHello,unsafeWindow);
        console.log( ==>目标页面对象已被更改。);
        });

        var gmMessageStr =功能...被GM拦截,也可以使用GM_功能!
        函数sayHello(){
        sayHello.K =(sayHello.K || 0)+ 1;
        console.log(gmMessageStr);
        GM_addStyle('body {background:'+(sayHello.K%2?lime:white)+';}');
        }
        var gmObject = {message:对象被GM覆盖。





        打开控制台并按下按钮,您将看到GM脚本能够读取和更改页面的变量和函数。






        注释:


        1. 这些都是特定于Firefox的
        2. 对于跨平台的代码和一些复杂的情况,改为使用 Script Injection 。但注入的代码不能直接访问 GM _ 函数。注意,这些技术只适用于全局的javascript变量和函数。
        3. li>


        Let's say I am working with the following web page:

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

        and my Greasemonkey script is:

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

        With the Greasemonkey script disabled, clicking the #click element on the page displays the 'hello' alert. With the script enabled, clicking the element displays the 'goodbye' alert.

        Simple enough. The hello function from the web page is being replaced by the function in the Greasemonkey script.

        Now let's say I want to use a Greasemonkey API. When I set the @grant value to a valid value other than 'none' (e.g. // @grant GM_setClipboard) [which causes Greasemonkey to run the script as a "content script", rather than in the page's scope like with 'none'], the Greasemonkey script fails to work.

        window.hello is no longer targeting the correct object on the page.

        Replacing window.hello with unsafeWindow.hello looks like it would work, but instead, the following error is thrown in the JS console:

        Error: Permission denied to access object

        How can I rewrite the Greasemonkey script while having @grant GM_setClipboard set to target and replace the original hello function on the page?

        System information:

        • Windows 7 64-bit
        • Firefox 32.0
        • Greasemonkey 2.2

        解决方案

        When you set a @grant value other than none, Greasemonkey activates its sandbox and Greasemonkey 2.0 radically changed unsafeWindow handling.

        Now, in order to create or overwrite variables in the target-page scope, you must correctly chose from a menu of techniques. EG:

        To Read:

        • A simple variable:

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

        • A simple object:

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

        • A complex object: This is not always possible.

        To Call:

        • A simple function:

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

        • A complex function: This is not always possible.

        To Write/Set:

        • A simple variable:

          unsafeWindow.foo = "Apple";
          

        • A simple object:

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

        • A simple function:

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


        Consider this HTML:

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

        And this 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 ();
        } );
        

        which you can see live at this jsFiddle page.

        If you install and run this Greasemonkey script against that page:

        // ==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."};
        


        Open the console and press the buttons and you will see that the GM script is able to read and change the page's variables and functions.


        Notes:

        1. This is all Firefox specific.
        2. For cross platform code, and for some complex situations, you can use Script Injection instead. But injected code cannot directly access GM_ functions.
        3. Note that these techniques only work for javascript variables and functions that are global.

        这篇关于如何设置@grant值时如何访问`window`(目标页面)对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
  • 登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆