Javascript 使用webNavigation.onCommitted将脚本注入网页

Javascript 使用webNavigation.onCommitted将脚本注入网页,javascript,html,browser,firefox-addon-webextensions,Javascript,Html,Browser,Firefox Addon Webextensions,我想找到一种方法,在我的web扩展中,只要DOM可以在web页面中使用,并且在加载任何其他脚本之前,就注入脚本元素 我试图通过使用 当提交导航时,应该触发。至少已从服务器接收到部分新文档,并且浏览器已决定切换到新文档。(引用先前链接的页面) 事实上,在我注入脚本时,文档已经被浏览器解析和呈现,因此我想从网页透视图中引用的对象还没有定义 我只在Firefox上测试过,目前我不关心其他浏览器的支持 我已经建立了一个最小的,可复制的例子。可以获取整个源代码 基本上,我在后台脚本中注册我的事件处理程序,

我想找到一种方法,在我的web扩展中,只要DOM可以在web页面中使用,并且在加载任何其他脚本之前,就注入脚本元素

我试图通过使用 当提交导航时,应该触发
。至少已从服务器接收到部分新文档,并且浏览器已决定切换到新文档。
(引用先前链接的页面)

事实上,在我注入脚本时,文档已经被浏览器解析和呈现,因此我想从网页透视图中引用的对象还没有定义

我只在Firefox上测试过,目前我不关心其他浏览器的支持

我已经建立了一个最小的,可复制的例子。可以获取整个源代码

基本上,我在后台脚本中注册我的事件处理程序,它将内容脚本注入“提交”选项卡:

在inject.js中,我创建了一个脚本元素并将其附加到文档根目录:

const script = document.createElement('script')
script.src = browser.runtime.getURL('script.js')
script.onload = () => {
  console.log('injected')
}

console.log('injecting')
document.documentElement.appendChild(script)

0
script.js非常简单:

TEST=1
为了测试扩展,我构建了另一个非常简单的网页:


试验
console.log(‘太晚了?’,window.TEST?‘否’:‘是:\\’)

我希望在控制台中看到日志行“太晚了?”?不。总是碰巧“太晚了?”?是:\',除了第一次打开网页、关闭包含该页的选项卡并还原(CTRL+SHIFT+T)等少数情况外。刷新页面(F5、CTRL+F5,无论什么)总是导致“太晚了?”?是:\'

我不确定,但我认为问题可能是extensionType,而不是提交的事件触发的时间:

“文档开始”:对应于加载。DOM仍在加载。


这是注入脚本的最快时间。因此,我假设没有办法实现您的目标。

我不确定,但我认为问题可能在于extensionType,而不是提交的事件触发的时间:

“文档开始”:对应于加载。DOM仍在加载。

这是注入脚本的最快时间。所以我认为没有办法实现你的目标

我想找到一种方法,在我的web扩展中,只要DOM可以在web页面中使用,并且在加载任何其他脚本之前,就注入脚本元素

DOM可用后,内联脚本已经加载,远程脚本已经开始加载。用于在“文档开始”处注入

“inject.js”
中添加监听器,例如:
document.addEventListener(“beforescriptexecute”,start,true)(仅Firefox支持)

然后,在脚本执行之前处理脚本

如果您需要处理DOM,那么还需要添加一个侦听器,例如:
document.addEventListener('DOMContentLoaded',doSomething)

我想找到一种方法,在我的web扩展中,只要DOM可以在web页面中使用,并且在加载任何其他脚本之前,就注入脚本元素

DOM可用后,内联脚本已经加载,远程脚本已经开始加载。用于在“文档开始”处注入

“inject.js”
中添加监听器,例如:
document.addEventListener(“beforescriptexecute”,start,true)(仅Firefox支持)

然后,在脚本执行之前处理脚本


如果您需要处理DOM,那么还需要添加一个侦听器,例如:
document.addEventListener('DOMContentLoaded',doSomething)

当我调用executeScript时,我是在OnCommitted的上下文中调用它,而不仅仅是在任何地方。所以,dom仍然在加载,这很好,我只需要它加载得更少,可以先注入脚本。关于OnCommitted与DOM加载的关系没有真正的文档,它只是发生在onDOMContentLoaded(这意味着DOM实际上已经准备好)之前,在web上搜索“OnCommitted+InjectScript”会产生这个方向的结果。“在OnCommitted的上下文中”:当然,但是,即使前面有另一个事件,
runAt
仍会将脚本注入
状态==='loading'
,因此我认为注入取决于
runAt
而不是提交的事件。但是你的观点是绝对正确的,关于这两种情况中任何一种的确切时间,文件都是模糊的。也许有人可以在Mozilla的对话论坛上澄清一下:好luckI,我不认为我理解你的推理。如果执行脚本时
runAt
设置为
document\u start
,但使用
browser.webNavigation.onDOMContentLoaded
,DOM将准备就绪。在这种情况下,
运行在
上并不重要。因此,如果
oncommitted
保证在未准备好的DOM状态下发生,但同样准备好在页面中注入内容,那么它应该可以工作。不管怎样,谢谢你指出mozilla的对话论坛,我不知道它的担忧,然后我误解了你的问题。我想你的脚本注入已经太晚了,你正在寻找一种方法让它成为页面上的第一个脚本。因此,如果您发现一个webNavigation事件在加载DOM时触发,但还没有执行页面脚本,那么它仍然无关紧要——因为
runAt
。我认为您对
runAt
(更准确地说是
文档开始
)的语义过于重视了。我已经给你举了一个例子来说明我想说的,我不会再对此争论了。当我调用executeScript时,我是在OnCommitted的上下文中调用它,而不仅仅是在任何地方。所以,dom仍然在加载,这很好,我只需要它加载得更少,可以先注入脚本。关于OnCommitted与DOM的关系,没有真正的文档
TEST=1
"content_scripts": [
  {
    "matches": ["*://*.mozilla.org/*"],
    "js": ["inject.js"],
     "run_at": "document_start"
  }
]