当前位置: 首页 > 面试题库 >

设置@grant值时,如何访问“窗口”(目标页面)对象?

余弘新
2023-03-14
问题内容

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

<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脚本是:

// ==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脚本中的功能替换。

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

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

更换window.hellounsafeWindow.hello看起来像它的工作,而是下面的错误是在JS控制台抛出:

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

@grant GM_setClipboard设置为目标并替换hello页面上的原始功能后,如何重写Greasemonkey脚本?

系统信息:

  • Windows 7 64位
  • Firefox 32.0
  • Greasemonkey 2.2

问题答案:

当您设置任何@grant其他值时,Greasemonkey会激活其沙箱,而Greasemonkey2.0将彻底改变unsafeWindow处理。

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

To Read:

  • 一个简单的变量:

    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 }

  • 一个复杂的对象: 这并不总是可能的。

To Call:

  • 一个简单的功能:
    Target page sets:       function func () {console.log ('Hi');}
    

    GM script can call: unsafeWindow.func() //– “Hi”

To Write/Set:

  • 一个简单的变量:

    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:

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

如果在该页面上安装并运行此Greasemonkey脚本:

// ==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脚本能够读取和更改页面的变量和功能。

笔记:

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


 类似资料:
  • 问题内容: 如何使用jQuery访问父窗口对象? 这是我的父窗口变量,我想在关闭子窗口后设置其值。 问题答案:

  • 问题内容: 我对使用时如何获取价值感到困惑。这是我的测试内容: 控制台将输出。但是,如果我稍微修改一下代码,它就会起作用: 当然,除了那行因为我现在正在使用而失败。我都需要正常工作。我该如何解决? 编辑 : 我应该提到,不是受控组件。但是当我进入时,似乎设置了值。上面的第二个代码块确实打印出了该值,同样,如果我在Chrome中检查了输入元素并在控制台中键入,它将显示期望的值。 问题答案: 得到它了

  • 问题内容: 我有一个3d渲染程序,该程序根据鼠标在屏幕上的位置围绕观察者旋转世界。这条线定义了地球旋转的弧度量 其中xy [0]是屏幕中心的x坐标 这意味着观察者视野的旋转量受到鼠标可以移动的距离的限制。如果我能使鼠标回到屏幕中央,则可以解决此问题。有任何想法吗? 问题答案: 好消息是有一种方法可以做到。 中间的消息是,它没有很好的记录。 坏消息是它仅在某些平台上有效。 另一个中间消息是,您至少可

  • 问题内容: 如何从项目管道访问settings.py中的scrapy设置。文档中提到可以通过扩展程序中的搜寻器访问它,但是我看不到如何在管道中访问搜寻器。 问题答案: 从内部访问Scrapy设置(如中所定义)的方法很简单。所有其他答案都太复杂了。原因是对Scrapy文档的维护非常差,加上许多最新的更新和更改。在“设置”文档“ 如何访问设置 ”中,或者在“设置API”中,都没有给出任何可行的示例。这

  • 当USB设备连接到Android平板电脑时,会出现一个弹出窗口,要求用户许可。我想抑制它,因为客户端不想要它。我应该怎么做? 在代码中: 调用以授予 USB 设备临时访问权限。 这会弹出一个弹出窗口。默认情况下,如何禁止弹出窗口或授予用户访问权限?

  • 问题内容: 我将GhostDriver用作基于Java的项目中的WebDriver实现。我想拍摄页面快照。默认页面大小有点尴尬,因此我想控制快照的页面大小。但是,我找不到Google提供的任何示例。那么,有人可以告诉我如何吗?非常感谢你。 问题答案: 你尝试过的方法吗?这是文档。