为什么window(和unsafeWindow)与用户脚本和<script>标签不一样?

ldi*_*ual 18 javascript greasemonkey scope userscripts

在开发这个小用户时我遇到了一个问题.当我想XMLHttpRequest用我的脚本阻止正在运行的网站中的每一个时,没有发生任何事情(至少在Chrome上):

function main() {
  // Override XHR.open with a custom function
  window.XMLHttpRequest.prototype.open = function() {
    // Nothing... so it's supposed to block every xhr.open() call
  }
}
main();
Run Code Online (Sandbox Code Playgroud)

更换时同样的事情windowunsafeWindow.

然而,当我使用这个小技巧时,一切都像魅力一样:

// No more call to main(), and:
var script = document.createElement("script");
script.textContent = "(" + main.toString() + ")();";
document.body.appendChild(script);
Run Code Online (Sandbox Code Playgroud)

每次调用xhr.open都被我的自定义函数替换,不再需要AJAX.

所以我猜这个window元素在main从脚本内部调用时与从<script></script>容器中调用时的元素不同.有人能解释一下为什么吗?

Bro*_*ams 47

请参阅"Chrome用户脚本是否与全局命名空间分离,如Greasemonkey脚本?" .Chrome用户脚本/内容脚本和Greasemonkey脚本都与页面的javascript隔离.这样做是为了帮助您避免被黑客攻击,但它也可以减少冲突和意外的副作用.

但是,每种浏览器的方法都不同......

火狐:

  1. XPCNativeWrapper沙箱中运行脚本,除非@grant none生效(从GM 1.0开始).
  2. 默认情况下,将脚本包含在匿名函数中.
  3. 提供unsafeWindow访问目标页面的javascript.但请注意,敌对网站管理员可能会将unsafeWindow使用情况追溯到脚本的上下文,从而获得提升权限.

铬:

  1. "孤立的世界"中运行脚本.
  2. 在匿名函数中包装脚本.
  3. 严格阻止脚本对页面JS的任何访问,反之亦然.
    最近版本的Chrome现在提供了一个名为的对象unsafeWindow,但兼容性非常有限,但此对象不提供对目标页面JS的任何访问.它window与脚本范围(不在window页面范围内)相同.

也就是说,unsafeWindow如果正确实现,您使用的脚本版本应该在Firefox上工作.它可能在Chrome上使用Tampermonkey扩展程序,但我现在不打算再仔细检查.

当您执行"技巧"(var script = document.createElement("script"); ...)时,您代码注入目标页面.这绕过了沙盒,是普通Chrome用户脚本与脚本JS交互的唯一方式.

注塑优势:

  1. 非Tampermonkey用户脚本访问目标页面提供的对象或功能的唯一方法.
  2. Chrome,Firefox,Opera等几乎总是完全兼容(IE一如既往地是其他东西.)
  3. 通常更容易调试整个脚本; 开发人员工具正常工作

注射缺点:

  1. 脚本(至少是注入的部分)不能使用GM_函数提供的增强特权(尤其是跨域)- 尤其是GM_xmlhttpRequest().
    需要注意的是目前的Chrome只支持GM_addStyle,GM_xmlhttpRequest,GM_logGM_openInTab,充分,本身.
    但是,Tampermonkey GM_几乎完全支持功能.

  2. 可能会导致与页面JS的副作用或冲突.

  3. 使用外部库会引入更多冲突和时序问题.它远没有那么容易@require.
    @require,还从本地副本运行外部JS - 加快执行速度,但几乎不再依赖外部服务器.

  4. 该页面可以查看,使用,更改或阻止脚本.

  5. 需要启用JS.特别是Firefox Greasemonkey可以在JS被阻止的页面上运行.对于臃肿,蹩脚和/或侵入性的页面,这可能是天赐之物.