对复杂页面功能的调用在 Tampermonkey 中有效,但在 Greasemonkey 中无效?
Call to a complex page function works in Tampermonkey but not Greasemonkey?
我正在尝试为 XenForo 论坛打开覆盖对话框,重新使用现有库:
// ==UserScript==
// @name FooBar
// @match https://xenforo.com/community/
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
unsafeWindow.XenForo.createOverlay(null, $(`
<div class="xenOverlay">
<form id="efd_form">
<div class="section">
<h2 class="heading h1">Greasemonkey test</h2>
<h3 class="primaryContent">${GM_getValue('lorem', 'Lorem ipsum dolor sit amet …')}</h3>
</div>
</form>
</div>
`), { noCache: true }).load();
})();
当您使用 Tampermonkey (Firefox/Chromium) 访问 https://xenforo.com/community/ 时,此脚本将打开简单的对话框。
但是,当您使用 Greasemonkey (Firefox) 尝试时,什么也没有发生。有没有办法在访问 GM_getValue
的同时实现这一目标?
如果您 ,您将看到如下错误消息:
$ is not defined ... FooBar.user.js
这是因为使用 @grant
而不是 none
在 Greasemonkey(以及 Tampermonkey-ish)中开启了沙箱。这意味着脚本无法直接看到页面的 javascript,因此 jQuery 未为脚本定义 ***.
在您的代码中,您不能使用 unsafeWindow
技术来调用 XenForo.createOverlay()
,因为该函数需要页面范围内的 jQuery 对象 defined/valid(对于更复杂的原因)。
参考How to access `window` (Target page) objects when @grant values are set?。这种情况属于 "A complex function: This is not always possible" 情况。
所以,你需要注入调用XenForo.createOverlay()
的代码。
但是,有一个障碍。因为 GM_getValue()
在页面范围内不可用,所以您需要 单独注入 GM_getValue
调用的结果。
此脚本说明了该过程并适用于两种浏览器:
// ==UserScript==
// @name FooBar
// @match https://xenforo.com/community/
// @grant GM_getValue
// ==/UserScript==
unsafeWindow.GM_simplevar = GM_getValue ('lorem', 'Hello world!');
function GM_usePagesOverlay ($) {
XenForo.createOverlay (null, $(`
<div class="xenOverlay">
<form id="efd_form">
<div class="section">
<h2 class="heading h1">Greasemonkey test</h2>
<h3 class="primaryContent">${GM_simplevar}</h3>
</div>
</form>
</div>
`), { noCache: true }).load ();
}
withPages_jQuery (GM_usePagesOverlay);
function withPages_jQuery (NAMED_FunctionToRun) {
//--- Use named functions for clarity and debugging...
var funcText = NAMED_FunctionToRun.toString ();
var funcName = funcText.replace (/^function\s+(\w+)\s*\((.|\n|\r)+$/, "");
var script = document.createElement ("script");
script.textContent = funcText + "\n\n";
script.textContent += 'jQuery(document).ready(function() {'+funcName+'(jQuery);});';
document.body.appendChild (script);
}
对于更复杂的数据交换,在页面范围和用户脚本范围之间,您可能需要 use messaging.
*** Tampermonkey 的行为违反了沙盒范式,可能 是一个安全漏洞,允许不良网页访问特权 GM_ 函数 - - 有一天需要对此进行调查...... :)
我正在尝试为 XenForo 论坛打开覆盖对话框,重新使用现有库:
// ==UserScript==
// @name FooBar
// @match https://xenforo.com/community/
// @grant GM_getValue
// ==/UserScript==
(function() {
'use strict';
unsafeWindow.XenForo.createOverlay(null, $(`
<div class="xenOverlay">
<form id="efd_form">
<div class="section">
<h2 class="heading h1">Greasemonkey test</h2>
<h3 class="primaryContent">${GM_getValue('lorem', 'Lorem ipsum dolor sit amet …')}</h3>
</div>
</form>
</div>
`), { noCache: true }).load();
})();
当您使用 Tampermonkey (Firefox/Chromium) 访问 https://xenforo.com/community/ 时,此脚本将打开简单的对话框。
但是,当您使用 Greasemonkey (Firefox) 尝试时,什么也没有发生。有没有办法在访问 GM_getValue
的同时实现这一目标?
如果您
$ is not defined ... FooBar.user.js
这是因为使用 @grant
而不是 none
在 Greasemonkey(以及 Tampermonkey-ish)中开启了沙箱。这意味着脚本无法直接看到页面的 javascript,因此 jQuery 未为脚本定义 ***.
在您的代码中,您不能使用 unsafeWindow
技术来调用 XenForo.createOverlay()
,因为该函数需要页面范围内的 jQuery 对象 defined/valid(对于更复杂的原因)。
参考How to access `window` (Target page) objects when @grant values are set?。这种情况属于 "A complex function: This is not always possible" 情况。
所以,你需要注入调用XenForo.createOverlay()
的代码。
但是,有一个障碍。因为 GM_getValue()
在页面范围内不可用,所以您需要 单独注入 GM_getValue
调用的结果。
此脚本说明了该过程并适用于两种浏览器:
// ==UserScript==
// @name FooBar
// @match https://xenforo.com/community/
// @grant GM_getValue
// ==/UserScript==
unsafeWindow.GM_simplevar = GM_getValue ('lorem', 'Hello world!');
function GM_usePagesOverlay ($) {
XenForo.createOverlay (null, $(`
<div class="xenOverlay">
<form id="efd_form">
<div class="section">
<h2 class="heading h1">Greasemonkey test</h2>
<h3 class="primaryContent">${GM_simplevar}</h3>
</div>
</form>
</div>
`), { noCache: true }).load ();
}
withPages_jQuery (GM_usePagesOverlay);
function withPages_jQuery (NAMED_FunctionToRun) {
//--- Use named functions for clarity and debugging...
var funcText = NAMED_FunctionToRun.toString ();
var funcName = funcText.replace (/^function\s+(\w+)\s*\((.|\n|\r)+$/, "");
var script = document.createElement ("script");
script.textContent = funcText + "\n\n";
script.textContent += 'jQuery(document).ready(function() {'+funcName+'(jQuery);});';
document.body.appendChild (script);
}
对于更复杂的数据交换,在页面范围和用户脚本范围之间,您可能需要 use messaging.
*** Tampermonkey 的行为违反了沙盒范式,可能 是一个安全漏洞,允许不良网页访问特权 GM_ 函数 - - 有一天需要对此进行调查...... :)