9

我有一个 chrome 扩展,它会在每个打开的选项卡中注入一个 iframe。我的 background.js 中有一个 chrome.runtime.onInstalled 侦听器,它手动注入所需的脚本,如下所示(此处 API 的详细信息:http: //developer.chrome.com/extensions/runtime.html#event-onInstalled):

背景.js

  var injectIframeInAllTabs = function(){
    console.log("reinject content scripts into all tabs");
    var manifest = chrome.app.getDetails();
    chrome.windows.getAll({},function(windows){
      for( var win in windows ){
        chrome.tabs.getAllInWindow(win.id, function reloadTabs(tabs) {
          for (var i in tabs) {
            var scripts = manifest.content_scripts[0].js;
            console.log("content scripts ", scripts);
            var k = 0, s = scripts.length;
            for( ; k < s; k++ ) {
              chrome.tabs.executeScript(tabs[i].id, {
                file: scripts[k]
              });
            }

          }
        });
      }
    });
  };

当我第一次安装扩展时,这很好用。当我的扩展更新时,我也想做同样的事情。如果我在更新时也运行相同的脚本,我看不到注入新的 iframe。不仅如此,如果我在更新后尝试向我的内容脚本发送消息,则不会有任何消息通过内容脚本。我已经看到其他人在 SO 上也遇到了同样的问题(Chrome: message content-script on runtime.onInstalled)。chrome 扩展更新后删除旧内容脚本并注入新内容的正确方法是什么?

4

2 回答 2

6

当扩展更新时,Chrome 会自动切断所有“旧”内容脚本与后台页面的对话,如果旧内容脚本确实尝试与运行时通信,它们也会抛出异常。这对我来说是缺失的部分。我所做的只是在chrome.runtime.onInstalledin 中bg.js调用与问题中发布的相同的方法。这会注入另一个与正确运行时对话的 iframe。在某个时间点,旧的内容脚本尝试与失败的运行时对话。我抓住了那个异常,只是清除了旧的内容脚本。另请注意,每个 iframe 都被注入其自己的“孤立世界”(此处解释了孤立世界:http ://www.youtube.com/watch?v=laLudeUmXHM ),因此新注入的 iframe 无法清除旧的挥之不去的 iframe。

希望这对将来的人有所帮助!

于 2013-08-28T22:58:48.277 回答
3

没有办法“删除”旧的内容脚本(除了使用 window.location.reload 重新加载有问题的页面,这会很糟糕)

如果您想更灵活地处理在内容脚本中执行的代码,请使用 executeScript 函数中的“code”参数,它可以让您使用 javascript 代码传入原始字符串。如果您的内容脚本只是一个位于 background.js 中的大函数(即 content_script_function)

background.js中:

function content_script_function(relevant_background_script_info) {
   // this function will be serialized as a string using .toString()
   // and will be called in the context of the content script page
   // do your content script stuff here...
}

function execute_script_in_content_page(info) {
  chrome.tabs.executeScript(tabid,
    {code: "(" + content_script_function.toString() + ")(" +
     JSON.stringify(info) + ");"});
}

chrome.tabs.onUpdated.addListener(
  execute_script_in_content_page.bind( { reason: 'onUpdated',
                                         otherinfo: chrome.app.getDetails() });

chrome.runtime.onInstalled.addListener(
  execute_script_in_content_page.bind( { reason: 'onInstalled',
                                         otherinfo: chrome.app.getDetails() });
)

其中related_background_script_info 包含有关背景页面的信息,即它是哪个版本,是否有升级事件以及调用该函数的原因。内容脚本页面仍保持其所有相关状态。这样您就可以完全控制如何处理“升级”事件。

于 2013-08-28T18:55:48.313 回答