设置@grant 值时如何访问`window`(目标页面)对象? [英] How to access `window` (Target page) objects when @grant values are set?
问题描述
假设我正在使用以下网页:
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.
注意事项:
- 这都是 Firefox 特有的.
- 对于跨平台代码,以及一些复杂的情况,可以使用脚本注入反而.但是注入的代码不能直接访问
GM_
函数. - 请注意,这些技术仅适用于全局的 javascript 变量和函数.
这篇关于设置@grant 值时如何访问`window`(目标页面)对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!