如何从内容脚本正确处理chrome扩展更新

时间:2014-03-19 19:27:20

标签: javascript google-chrome google-chrome-extension

在后台页面中,我们可以使用chrome.runtime.onInstalled.addListener检测扩展程序更新。

但是在更新扩展后,所有内容脚本都无法连接到后台页面。我们收到错误:Error connecting to extension ....

可以使用chrome.tabs.executeScript重新注入内容脚本...但是如果我们有一个敏感数据应该在更新之前保存并在更新后使用怎么办?我们能做什么?

此外,如果我们重新注入所有内容脚本,我们应该正确拆除以前的内容脚本。

在不丢失用户数据的情况下,从内容脚本处理扩展程序更新的正确方式是什么?

2 个答案:

答案 0 :(得分:2)

Chrome扩展程序更新发生后,"孤立的"内容脚本完全从扩展名中删除。它仍然可以通信的唯一方式是通过共享DOM。如果您正在谈论真正的敏感数据,那么从页面来看这是不安全的。稍后会详细介绍。

首先,您可以延迟更新。在后台脚本中,为chrome.runtime.onUpdateAvailable事件添加处理程序。只要听众在那里,你就有机会进行清理。

// Background script
chrome.runtime.onUpdateAvailable.addListener(function(details) {
  // Do your work, call the callback when done
  syncRemainingData(function() {
    chrome.runtime.reload();
  });
});

其次,假设最坏的情况发生并且你被切断了。您仍然可以使用DOM事件进行通信:

// Content script
// Get ready for data
window.addEventListener("SendRemainingData", function(evt) {
  processData(evt.detail);
}, false);

// Request data
var event = new CustomEvent("RequestRemainingData");
window.dispatchEvent(event);

// Be ready to send data if asked later
window.addEventListener("RequestRemainingData", function(evt) {
  var event = new CustomEvent("SendRemainingData", {detail: data});
  window.dispatchEvent(event);
}, false);

但是,主机页面可能会窃听此通信通道。并且,如前所述,窃听不是你可以绕过的东西。

然而,您可以拥有一些带外预共享数据。假设您在首次安装时生成随机密钥并将其保留在chrome.storage中 - 网页无法通过任何方式访问该密钥。当然,一旦成为孤儿,你就无法阅读它,但你可以在注射的那一刻。

var PSK;
chrome.storage.local.get("preSharedKey", function(data) {
  PSK = data.preSharedKey;

  // ...

  window.addEventListener("SendRemainingData", function(evt) {
    processData(decrypt(evt.detail, PSK));
  }, false);

  // ...

  window.addEventListener("RequestRemainingData", function(evt) {
    var event = new CustomEvent("SendRemainingData", {detail: encrypt(data, PSK)});
    window.dispatchEvent(event);
  }, false);
});

这当然是概念验证代码。我怀疑你需要的不只是onUpdateAvailable听众。

答案 1 :(得分:1)

如果您已通过var port = chrome.runtime.connect(...)建立了通讯(如上所述) https://developer.chrome.com/extensions/messaging#connect),应该可以收听runtime.Port.onDisconnect event

tport.onDisconnect.addListener(function(msg) {...})

你可以做出反应,例如应用某种记忆,让我们说通过localStorage。但总的来说,我建议尽量减少内容脚本,并在后台执行所有数据操作,如果需要,只允许内容收集/传递数据并呈现某些状态。