2

有什么方法可以让这段代码在 Greasemonkey/Scriptish 中工作,还是我必须将它注入网页本身?

body = document.getElementsByTagName("body")[0];
fakeConsole = 'window.top._console';
injected = document.getElementById("sandbox") ? true : false;
sandboxframe = injected ? document.getElementsById("sandbox") : document.createElement('iframe');
sandbox = null;

if (!injected) {
   body.appendChild(sandboxframe);
   sandboxframe.setAttribute('id', 'sandbox');
   sandboxframe.setAttribute('style', "display:none")
}

var p = sandboxframe.contentWindow.eval('1 + 1');
console.log(p);

使用源代码时,此代码确实有效:

 <script type="text/javascript" src="test.js"></script>

但不是在 Greasemonkey 脚本中使用时,我观察到存在某种我不太熟悉的安全屏障,并试图使用 unsafeWindow 绕过 XPCNativeWrapper。

请对此有所了解。

4

1 回答 1

1

几件事:

  1. 代码有错误;getElementsById不是函数。
  2. 如果该指令适用,那么该代码在 Greasemonkey 1.0 或更高版本中确实有效。@grant none更多关于这下面。
  3. 对于 Scriptish、所有其他浏览器和 Greasemonkey 场景@grant none是不可能的;您将不得不“注入”代码。更多关于这下面。
  4. 正如 Jeremy J Starcher 所说,eval()应尽可能避免。 eval()使性能、维护、调试和安全性变得更加困难。

对于 Greasemonkey 1.0 及更高版本:

某些情况下,Greasemonkey 不再使用XPCNativeWrapper. 请参阅@grant指令的文档。

所以这意味着 (1) 如果您的脚本不使用任何GM_函数并且 (2) 脚本指定@grant none,那么您的代码将按原样运行(getElementsById拼写错误除外)。

请注意,没有其他脚本引擎会这样做。(出于很好的理由。Greasemonkey 的新行为与@grant沙盒有关,充其量是有争议的。)

如果你想使用GM_函数,那么你必须注入 iframe 代码。请参阅下一节。


对于 Scriptish、Privileged Greasemonkey、Chrome 等:

Scriptish、Sandboxed Greasemonkey、Chrome 等都不能在各自的沙箱中很好地处理 iframe。(例如,请参阅这些 Q。

从 GM/用户脚本运行此类代码的唯一可靠方法是注入它。像这样:

function gmMain () {
    body = document.getElementsByTagName("body")[0];
    fakeConsole = 'window.top._console';
    injected = document.getElementById("sandbox") ? true : false;
    sandboxframe = injected ? document.getElementById("sandbox") : document.createElement('iframe');
    sandbox = null;

    if (!injected) {
       body.appendChild(sandboxframe);
       sandboxframe.setAttribute('id', 'sandbox');
       sandboxframe.setAttribute('style', "display:none")
    }

    var p = sandboxframe.contentWindow.eval('1 + 1');
    console.log(p);
}

addJS_Node (null, null, gmMain);

function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}
于 2012-09-27T02:16:11.217 回答