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

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

问题描述

假设我正在使用以下网页:

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>

我的 Greasemonkey 脚本是:

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');
}

在禁用 Greasemonkey 脚本的情况下,单击页面上的 #click 元素会显示hello"警报.启用脚本后,单击该元素会显示再见"警报.

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.

很简单.网页中的 hello 函数正在被 Greasemonkey 脚本中的函数替换.

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

现在假设我想使用 Greasemonkey API.当我将 @grant 值设置为none"以外的有效值时(例如 //@grant GM_setClipboard)[这会导致 Greasemonkey 将脚本作为内容"运行脚本",而不是像无"那样在页面范围内],Greasemonkey 脚本无法工作.

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 不再针对页面上的正确对象.

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

unsafeWindow.hello 替换 window.hello 看起来可行,但在 JS 控制台中抛出以下错误:

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

如何在将 @grant GM_setClipboard 设置为目标并替换页面上的原始 hello 函数的同时重写 Greasemonkey 脚本?

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

系统信息:

  • Windows 7 64 位
  • 火狐 32.0
  • Greasemonkey 2.2

推荐答案

当你设置一个 @grant 值而不是 none 时,Greasemonkey 会激活它的沙箱和 Greasemonkey 2.0 从根本上改变了 unsafeWindow 处理.

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

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

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

  • 一个简单的变量:

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

  • 一个简单的对象:

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

  • 复杂对象:这并不总是可行的.

    • 一个简单的函数:

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

  • 一个复杂的函数: 这并不总是可行的.

    • 一个简单的变量:

    unsafeWindow.foo = "Apple";
    

  • 一个简单的对象:

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

  • 一个简单的函数:

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

  • 考虑这个 HTML:

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

    还有这个 javascript:

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

    您可以在 这个 jsFiddle 页面.

    which you can see live at this jsFiddle page.

    如果您针对该页面安装并运行此 Greasemonkey 脚本:

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


    打开控制台并按下按钮,您将看到 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.

    注意事项:

    1. 这都是 Firefox 特有的.
    2. 对于跨平台代码,以及一些复杂的情况,可以使用脚本注入反而.但是注入的代码不能直接访问GM_函数.
    3. 请注意,这些技术仅适用于全局的 javascript 变量和函数.

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

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