greasemonkey 为一个简单的脚本抛出 SecurityError

greasemonkey throws SecurityError for a simple script

我是 greasemonkey 的新手,正在尝试了解 greasemonkey 与嵌入式 Web 控制台的不同之处。一个在 Web 控制台上完美运行的简单脚本在 greasemonkey 上 运行,我不知道为什么。

环境

Web 控制台

这是我使用的测试脚本:

(function() {
    "use strict";

    const w = window.open('https://www.google.com/', 'w');

    console.log("Hello");

    w.onload = () => {
        console.log("World");
    };

})();

当我访问https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0(Google美国首页)时,将脚本复制并粘贴到Web控制台,然后执行,

  1. 新的windoww加载https://www.google.com/打开

  2. 打印字符串Hello

  3. 打印字符串World

一切如预期。

油猴

在 greasemonkey 上,我使用下面的脚本。 header 部分是唯一的区别。

// ==UserScript==
// @name     test
// @namespace n
// @match https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0
// ==/UserScript==

(function() {
    "use strict";

    const w = window.open('https://www.google.com/', 'w');

    console.log("Hello");

    w.onload = () => {
        console.log("World");
    };

})();

当我访问 https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0(Google 美国首页)时,

  1. 新的windoww加载https://www.google.com/打开

  2. 打印字符串Hello

  3. SecurityError 被抛出

    Script error in [Greasemonkey script n/test]:
    SecurityError: Permission denied to access property "onload" on cross-origin object test:42:19
        user-script:n/test:42

当我使用 unsafeWindow 而不是 window 时,

  1. 新的windoww加载https://www.google.com/打开

  2. 打印字符串Hello

  3. 而且没有其他事情发生。 (没有错误,没有World

问题

我应该如何修改脚本才能在 greasemonkey 上执行?


更新

根据 ,该脚本适用于 Chrome.

下的 Tampermonkey 或 Violentmonkey

我尚未确认这一点,但已确认该脚本在 Firefox.

下的 Tampermonkey 4.10.6105Violentmonkey 2.12.7 上有效

Web 控制台是浏览器范围的一部分,而 GreaseMonkey 脚本被注入到页面内容中并且其范围仅限于该页面。

您可以使用 GM 从页面内容打开一个新的 tab/window,但是 window/tab 将有自己的页面内容范围,与第一个不同。因此,您无法从不同选项卡的页面内容访问属于另一个 tab/window 的属性。

这种分离适用于所有内容脚本,而不仅仅是 GM。否则,如果一个 tab/page 中的 JS 可以访问其他选项卡上的数据,将会产生很大的安全风险。

更新:

正如 wOxxOm 所指出的,CSP 和跨源策略阻止了 Cross-Origin Resource Sharing (CORS)

在您的示例中,在 Firefox 中,第一个问题是 Firefox 将 "Block pop-up windows" 来自内容脚本。

测试Firefox专用userScripts API on FireMonkey,允许弹出后,仍然报错:

SecurityError: Permission denied to access property "onload" on cross-origin object

在这种情况下,我认为这是由于为安全起见对 userScripts 进行了沙盒处理。

GM/TM/VM 不要使用 userScripts API 并使用其他方式注入 userSripts,这会导致不同的结果。