Javascript 如何在页面的所有帧加载时执行脚本(即不使用document_idle)

Javascript 如何在页面的所有帧加载时执行脚本(即不使用document_idle),javascript,firefox-addon,firefox-addon-webextensions,Javascript,Firefox Addon,Firefox Addon Webextensions,我的WebExtension(在本例中是Firefox)通过在页面上执行脚本来修改页面。我需要脚本在页面及其所有框架上工作,并且我需要在创建页面/框架时(即页面中的内容仍在加载时)尽快执行脚本 我看到有两种选择,但都无法实现这一点: 调用browser.tabs.executeScript()向脚本注入runAt:“document\u start”和allFrames:false。在执行的内容脚本本身上,尝试修改窗口的所有帧。由于跨域策略,对于内容来自另一个域的帧,这是不可能的 使用allFr

我的WebExtension(在本例中是Firefox)通过在页面上执行脚本来修改页面。我需要脚本在页面及其所有框架上工作,并且我需要在创建页面/框架时(即页面中的内容仍在加载时)尽快执行脚本

我看到有两种选择,但都无法实现这一点:

  • 调用
    browser.tabs.executeScript()
    向脚本注入
    runAt:“document\u start”
    allFrames:false
    。在执行的内容脚本本身上,尝试修改窗口的所有帧。由于跨域策略,对于内容来自另一个域的帧,这是不可能的

  • 使用
    allFrames:true调用
    browser.tabs.executeScript()
    。脚本将被注入到所有帧中,但如果一个帧的加载时间较长,则使用
    runAt:“document\u start”
    将仅在主文档上执行,而不会在帧上执行。使用
    “document\u idle”
    可以很好地工作,但需要很长时间

  • 我还尝试过使用
    runAt:“document\u start”和
    allFrames:false调用
    executeScript
    ,然后使用
    runAt:“document\u idle”
    allFrames:true调用
    。这将是一个折衷方案,允许主文档立即工作(大多数页面),但会稍微延迟帧。但是,执行的脚本将在主页中注入两次并导致错误

    所有这些都不允许我在加载时在所有帧上执行脚本。我该怎么做


    我怀疑需要一个更麻烦的解决方案,如果您有想法,我将不胜感激。谢谢

    您可以对注入脚本进行更细粒度的控制。我有一个带有
    webNavigation.onCompleted
    侦听器的扩展,当页面完全加载时会触发该侦听器

    browser.webNavigation.onCompleted.addListener(function(details){
      // don't inject into the main frame (id = 0)
      if(details.frameId != 0) {
        chrome.tabs.executeScript(details.tabId, {file: "js/contentScript.js", frameId: details.frameId});
      }
    });
    
    这需要manifests.json中的
    webNavigation
    权限


    也许这会与您在
    document\u start

    中插入主框架的第一个脚本一起工作。嗨,Matt,非常感谢您的回答。真管用!光荣!;)如果您不介意的话,我想在您的示例中添加一些内容。:)1.您需要将
    frameId:details.frameId
    添加到传递给executeScript的对象中,否则它仍将尝试在主页面而不是框架上执行。但将其添加到示例中效果很好。2.在我的例子中,我希望事情尽快开始,所以最好使用onDOMContentLoaded而不是onCompleted。干杯不幸的是,我需要额外的许可,但这仍然是唯一有效的选择。:)太好了,很高兴它对你有用!我已经更新了我的答案,加入了
    frameId:details.frameId
    ,这对于我的用例来说是不必要的,但对于你的用例来说肯定是必要的。