【问题标题】:tabs.executeScript - how can I tell if content script was being injected?tabs.executeScript - 如何判断内容脚本是否被注入?
【发布时间】:2019-07-08 01:50:51
【问题描述】:

我使用browser.tabs.executeScript 以编程方式将内容脚本注入网站。这将返回一个 Promise,但如果它被拒绝,似乎无法区分以下两种情况:

  1. 无法注入内容脚本(即缺少主机 许可)
  2. 脚本update解析end:update时出错(但正在注入脚本)

我只对脚本是否被注入感兴趣。

传递给catch 的参数是一个错误对象。 catch(e => console.log(e.toString()) 将输出错误消息,这可能是注入失败的原因(即Missing host permission)或发生错误更新读取脚本end:update.

    browser.tabs.executeScript(tabId, {
        file: '../path/to/content-script.js',
        frameId: 0,
        runAt: 'document_idle'
    })
        .catch(e => console.log(e.toString()));

所以,例如内容脚本如下:

    window.document.body.addEventListener('click', e => console.log('clicked body'), false);
    bla.bla();

那么 Promise 将被拒绝,因为 bla.bla 未定义 - 但脚本已成功注入。

如果无法注入内容脚本,我想用相应的错误消息通知用户。 但是当发生与是否可以注入脚本无关的错误updateend:update,在注入脚本时,我不想通知用户,但默默地处理它。 有没有办法区分这两种情况?

编辑:我想出了一个间接解决方案:如果返回的 Promise 被拒绝,我会尝试向内容脚本发送消息。如果这失败了,那么后台脚本“知道”没有内容脚本被注入 -> 通知用户。

【问题讨论】:

    标签: firefox-addon firefox-addon-webextensions


    【解决方案1】:

    这就是 Promise 的工作原理......

    browser.tabs.executeScript(tabId, {
      file: '../path/to/content-script.js',
      frameId: 0,
      runAt: 'document_idle'
    })
    .catch(e => console.log(e.toString()));
    

    如果tabs.executeScript 注入失败,上面的catch 将捕获错误。如果 JS 文件有解析错误(无效的 JS),它也可能在解析文件以注入时显示一些错误。这与 '../path/to/content-script.js' 之后的行为无关。

    所以一旦注入,那么上面的 Promise 就实现了。

    如果注入的脚本有一个sync返回,那么它可以被tabs.executeScript通过then()接收,例如

    browser.tabs.executeScript(tabId, {
      file: '../path/to/content-script.js',
      frameId: 0,
      runAt: 'document_idle'
    })
    .then(result => {})
    .catch(e => console.log(e.toString()));
    

    如果 async 函数(例如 .addEventListener)稍后会发生,则不会返回任何内容到 tabs.executeScript

    要捕获内容脚本中的错误,您可以在内容脚本中生成错误消息或向后台脚本发送消息,即sendMessage & onMessage.addListener

    tabs.executeScript()
    将通过对象数组实现的 Promise, 表示每个注入帧中的脚本结果。
    脚本的结果是最后评估的语句,即 类似于将输出的内容(结果,不是任何 console.log() 输出)如果您在 Web 控制台中执行脚本。例如, 考虑这样的脚本:

    var foo='my result';foo;
    
    browser.tabs.executeScript(tabId, {
      file: '../path/to/content-script.js',
      frameId: 0,
      runAt: 'document_idle'
    })
    .then(result => {
      // result is returned by the Promise
      if (result === []) { 
        // it was fine but there was nothing to return
      }
      else if (result[0]) {
        // result[0] is return from the promise
      }
    })
    .catch(e => console.log(e.toString()));
    

    现在如果你想要返回(它必须是同步的,否则你必须将它绑定到另一个 Promise),从 '../path/to/content-script.js' 中返回一些东西

    【讨论】:

    • 但是catch 也会从内容脚本中捕获错误即使脚本被注入:对于我上面的内容脚本示例catch 将输出“错误:bla未定义”,在点击相应页面时,浏览器控制台将输出“clicked body” -> 很明显,脚本正在被注入。
    • @user1521685 在读取代码以注入代码时,catch 可以显示代码中的 JavaScript 错误。那只是一些错误而不是全部。换句话说,与解析您尝试注入的 JS 文件相关的错误(与内容无关)。
    • 是的,我知道这与注入后内容脚本中发生的事情无关(抱歉,如果我没有正确表达自己)。而且我也知道catch 在解析代码时会显示代码错误。但这正是问题所在:返回的 Promise 无法判断脚本是否被注入。
    • @user1521685 document.body is null 在加载文档之前注入脚本时发生。稍后再注入。
    • @user1521685 您正在使用的各种异步 API 之间可能存在冲突,或者在不检查代码的情况下难以猜测的其他内容之间存在冲突。
    猜你喜欢
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    相关资源
    最近更新 更多