想出一个如何执行用户脚本的工作计划,当然直到运行时才知道。 与所有三个 runAt 时间兼容——尤其是document_start
。
到目前为止,我的研究见https://github.com/arantius/greasemonkey/tree/8a255bde1aa6312715740fd0157d582a2d6cb183 ,方法是:
tabs.executeScript()
来触发每个用户脚本。这个“有效”,除了我还没有发现可以观察到对所有三个运行时间都有效的事件。 有webNavigation
的onBeforeNavigate
实际上太早了,它(顾名思义)在导航之前触发,当当前文档仍然处于活动状态时。 但是下一点是onCommitted
,此时开始为时已晚,内联脚本已经执行。
研究:
webRequest
而不是webNavigation
。 这是否在开始时为我们提供了一个句柄?回复: https :
我希望能够(在后台)存储一个 blob,稍后获取(仅)它的 URL 并将该 URL(同步)传递给内容脚本,但我知道无法做任何这些事情。
我自己还没有弄清楚所有的细节,但我认为后台页面可以将 blob 存储在 IndexedDB 中,然后在启动时通过 URL.createObjectURL() 将它们转换为 blob URI,并将它们传递给假设的同步配置 API,然后也许通过加载它们
在 Firefox 的隐私浏览模式下,IndexedDB 不是被
我认为这不会影响后台脚本?
这可以通过使用在document_start
运行的内容脚本来实现,看起来像这样:(可能不适用于已经加载的选项卡,为此使用 jQuery)
// execute `document_start` scripts here...
document.addEventListener("DOMContentLoaded", event => {
// execute `document_end` scripts here...
});
window.addEventListener("load", event => {
// execute `document_idle` scripts here...
});
或类似的东西:(可能更容易出错)
let run = [false, false, false];
document_start();
if (document.readyState === "complete") {
document_idle();
} else if (document.readyState === "interactive") {
document_end();
}
document.onreadystatechange = () => {
switch (document.readyState) {
case "loading": break;
case "interactive": document_end();
case "complete": document_idle();
}
};
function document_start() {
if (run[0]) return;
run[0] = true;
// execute `document_start` scripts here...
}
function document_end() {
if (!run[0]) document_start();
if (run[1]) return;
run[1] = true;
// execute `document_end` scripts here...
}
function document_idle() {
if (!run[1]) document_end();
if (run[2]) return;
run[2] = true;
// execute `document_idle` scripts here...
}
另一种方法是使用三个单独的内容脚本,其中每个脚本在不同的时间运行。
为此, manifest.json
包含以下内容:(保证可能有效(可能存在竞争条件))
"content_scripts": [
{
"matches": ["<all_urls>"],
"run_at": "document_start",
"js": ["document_start_handler.js"]
},
{
"matches": ["<all_urls>"],
"run_at": "document_end",
"js": ["document_end_handler.js"]
},
{
"matches": ["<all_urls>"],
"run_at": "document_idle",
"js": ["document_idle_handler.js"]
}
]
也可以使用 jQuery,这可能是最不容易出错的方式,但这都需要大量测试:(同样,以document_start
运行,但需要与 jQuery 捆绑在一起)
function document_start() {
// execute `document_start` scripts here...
}
function document_end() {
// execute `document_end` scripts here...
}
function document_idle() {
// execute `document_idle` scripts here...
}
// Use jQuery to execute all the functions:
document_start();
// `$(document).ready(document_end)` is deprecated since 3.0
$(document_end);
// jQuery used to have a method for this: `$(window).load(document_idle)`
if (document.readyState === "complete") {
document_idle();
} else {
$(window).on("load", document_idle);
}
正如所写,这个问题太广泛了。 我将其拆分为单独的问题,以便更轻松地进行跟踪: