如何将ViolentMonkey用户脚本制作成浏览器扩展?

3

我一直在尝试将一个用户脚本迁移到我的扩展程序中,但出于某些原因,我无法运行以下代码:

// ==/UserScript==
console.info('BEFORE Hooked! MONKEY');
(function() {
    'use strict';
    // Reference [Augular loaded detect]: https://dev59.com/yI7da4cB1Zd3GeqP7gMY#31970556
    var initWatcher = setInterval(function () {
        if (window.MegaUtils) {
            console.info(window.MegaUtils);
            clearInterval(initWatcher);
            hookImport();
            hookFull();
            console.info('FUNtions Hooked! MONKEY');
        }
    }, 500);
})();

但由于某些原因,IF语句从未为TRUE,但完全相同的代码在ViolentMonkey中运行时立即起作用。
因此,完全没有检测到window.MegaUtils,而我不知道原因。有人告诉我,我的扩展程序可能无法访问DOM对象,但为什么ViolentMonkey可以访问它。
这是我在Chrome中导入扩展程序时使用的清单:

{
    "manifest_version": 2,
    "content_scripts": [ {
        "exclude_globs":    [  ],
        "include_globs":    [ "*" ],
        "js":               [ "mega.user.js" ],
        "matches":          [   "https://mega.nz/*",
                                "http://mega.nz/*" ],
        "run_at": "document_end"
    } ],
    "converted_from_user_script": true,
    "description":  "testing extension",
    "permissions": [],
    "name":         "MegaByPass",
    "icons": {
        "16": "images/mega-cloud-icon.png",
        "32": "images/mega-cloud-icon.png",
        "48": "images/download.png",
        "128": "images/873133.png"
      },
    "version":      "1.0"
}

感谢您的提前支持。

源代码

先感谢一下。


以上代码在哪里运行?是在后台脚本还是内容脚本中?它是如何注入的? - erosman
我相信这就是你所询问的内容://@run-at document-end 完整源代码请见:https://greasyfork.org/en/scripts/397876-mega-nz-ultimately-import/code - Chop Labalagun
不好意思,我想问一下这个插件是如何注入上述脚本的?是通过 manifest.json 还是 tabs.executeScript 或者 contentScripts.register() 或者 userScripts.register() 等方式呢? - erosman
这是一个很好的问题,我正在使用manifest.json,但不确定ViolentMonkey是如何使用它的。如何找到答案? 我已经将我的清单添加到问题中。 - Chop Labalagun
回复已更新,附带更多信息。 - erosman
2个回答

1
首先,移除通配符,因为它可能会引起问题。
"content_scripts": [
  {
    "matches": ["http://mega.nz/*", "https://mega.nz/*"],
    "js": ["mega.user.js"]
  }
]

ViolentMonkey默认在document-end注入。然而,GM/VM/TM手动注入用户脚本,而不使用专用API(Firefox中的FireMonkey使用专用API),因此注入时间可能晚于浏览器API注入的时间。
尝试使用默认值"document_idle"(可以省略)。
使用"document_end"可能导致脚本在外部Angular加载之前运行,这可能是问题的原因。
为了进行适当的测试,需要实际扩展程序。
更新1:
内容脚本被注入到与它们所在页面不同的范围/上下文中。因此,它们不能直接与页面上的JS交互,反之亦然。
全局window的行为在不同的浏览器之间不统一(例如,在Chrome中eval()始终在内容脚本的上下文中运行,但在Firefox中eval()在内容范围内运行,而window.eval()在页面范围内运行)。

经过快速测试,内容脚本无法访问全局windowwindow.MegaUtils。有方法可以解决这个问题,但是用户脚本能够工作可能与ViolentMonkey注入的方式或者授予window对象访问权限有关,而不使用unsafewindow

您是否已经在其他脚本管理器上测试过该脚本?!! 该脚本在所有脚本管理器上都有效还是只在ViolentMonkey上有效?

更多信息:
在Chrome扩展中访问当前选项卡的所有窗口变量
使用内容脚本将代码插入页面上下文

PS. 我只在Firefox上进行了测试,因为我不使用Chrome。

更新2

看到使用GM_函数时找不到页面变量,似乎当存在@grant none(需要适当确认)时,GM|TM|VM可能会将用户脚本注入到页面内容中。这就解释了为什么具有@grant none的上述用户脚本能够工作并可以在GM|TM|VM(不是FM)中获取window.MegaUtils。在这种情况下,您需要将脚本注入到页面JS中。
以下是示例:
const script = document.createElement('script');
script.textContent = `(function() {
    'use strict';
    // Reference [Augular loaded detect]: https://dev59.com/yI7da4cB1Zd3GeqP7gMY#31970556
    var initWatcher = setInterval(function () {
        if (window.MegaUtils) {
            clearInterval(initWatcher);
            hookImport();
            hookFull();
            console.info('FUNtions Hooked!');
        }
    }, 500);
})();

....`;
document.body.appendChild(script);

更新3 CSP

目前,浏览器遵循页面CSP(内容安全策略),这是您在评论中提到的问题。
参考:
[meta]页面CSP不应适用于由内容脚本插入的内容(V2问题)
CSP“沙箱”指令防止内容脚本与唯一来源匹配,也破坏了浏览器功能[屏幕截图]

有办法绕过这个问题,但它们不是标准的,扩展程序不应规避浏览器或页面CSP。


Chrome会抱怨删除匹配和js字段,因此它们必须存在才能导入它。我尝试使用document_idle,但是相同的行为它从未检测到window.MegaUtils。 - Chop Labalagun
@ChopLabalagun 为了进行适当的测试,需要实际的扩展名。 - erosman
你可以从这里获取:https://drive.google.com/drive/folders/1WFUfK7gl60rue-AweRc3qPPGeUGK6Hma?usp=sharing - Chop Labalagun
@ChopLabalagun 回答已更新...尽管问题未得到解决。 - erosman
@ChopLabalagun 我之前问了一下其他脚本管理工具,只是为了查看是否有关于 ViolentMonkey 的特殊情况,而不是建议使用用户脚本。 - erosman
显示剩余8条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接