设置@grant值时如何访问“window”(目标页)对象
How to access `window` (Target page) objects when @grant values are set?
假设我正在使用以下网页:
<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
函数正被Greasemonkey脚本中的函数所取代。
现在让我们说我想使用一个Greasemonkey API。当我将@grant
值设置为除"none"之外的有效值(例如// @grant GM_setClipboard
)[这会导致Greasemonkey将脚本作为"内容脚本"运行,而不是像"none’"那样在页面范围内运行]时,Greasemonkeyscript无法工作。
window.hello
不再针对页面上的正确对象。
用unsafeWindow.hello
替换window.hello
看起来是可行的,但在JS控制台中抛出了以下错误:
错误:访问对象的权限被拒绝
如何在将@grant GM_setClipboard
设置为目标并替换页面上的原始hello
函数的情况下重写Greasemonkey脚本?
系统信息:
- Windows 7 64位
- Firefox 32.0
- Greasemonkey 2.2
当您设置一个@grant
值而不是none时,Greasemonkey会激活其沙箱,Greasemonkey 2.0从根本上改变了unsafeWindow处理。
现在,为了在目标页面范围内创建或覆盖变量,您必须从技术菜单中正确选择。例如:
阅读:
-
一个简单的变量:
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:
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页面上实时看到。
如果你在这个页面上安装并运行这个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脚本能够读取和更改页面的变量和函数。
注:
- 这都是特定于Firefox的
- 对于跨平台代码和一些复杂的情况,可以使用脚本注入。但是注入的代码不能直接访问
GM_
函数 - 请注意,这些技术仅适用于全局的javascript变量和函数
将代码封装在lambda函数中,如:
(function(window){ // and more arguments if you need it
console.log(window); // here, should be the real 'window'
})(window.unsafeWindow)
- 正在寻找比$(document).ready慢的$(window).load的替代方案
- 直接下载文件,而不是从window.open(url)
- $window.ga在AngularJS事件中未定义
- 如何将PDF作为二进制文件传递到window.open()
- 为什么HTML5拖放的目标是孩子?(可排序列表)
- 如何覆盖锚点元素's href目标,并在我点击转到目标javascript时删除其他错误
- window.onload没有'无法在Android WebView中工作
- window.location替换并传递URL历史记录条目中的变量
- window.on.scroll事件未启动
- 可以<脚本类型=“;text/javascript”>window.location=“/"</
- 对一个对象使用reduce可以返回一个没有't在数组中包含目标字母
- Href:当前DIV中的目标ID
- 为什么window.open不打开一个以变量形式给出的链接
- window.location使用jquery mobile实现chrome跳转
- 当使用extern和目标JavaScript时,我如何强制Haxe编译器使用require语句
- 正在将目标添加到window.location
- window.onerror获取元素目标
- window.open在Chrome中使用目标“_blank”
- 设置@grant值时如何访问“window”(目标页)对象
- Window.open + href 替换并弹出到新窗口中,但不使用目标_blank