【问题标题】:How to replace/upgrade a Chrome extension with another?如何用另一个替换/升级 Chrome 扩展?
【发布时间】:2015-12-16 08:42:36
【问题描述】:

我的团队拥有一个 Chrome 扩展程序,而另一个团队也有一个类似的扩展程序,但很快就会被弃用,因此我们将接管他们所有现有用户。问题来了 - 有没有办法将用户从他们的扩展无缝迁移到我们的扩展? IE。有没有办法从用户端自动升级到我们的扩展?

【问题讨论】:

  • 除非你想维护两个独立的版本。

标签: google-chrome google-chrome-extension


【解决方案1】:

没有无缝的方法,因为明显的安全原因,扩展程序无法安装其他扩展程序(即使有"management" 权限),但这里有一个可能的升级路径。

我将调用“旧”扩展 A 并假设其 ID 为 "extension_a_id",而“新”扩展 B 并假设其 ID 为“extension_b_id”。

  1. 确保扩展可以相互通信。除非您在清单中明确定义"externally_connectable",否则默认情况下应该是这种情况;如果这样做,请确保扩展 B 包含 "extension_a_id" ID,反之亦然。

  2. 更新扩展 B 以包含响应来自 A 的请求的代码在所有后续步骤中。在您有理由确定大多数安装基础都具有此版本(可能等待一周左右)之前,请不要继续。

    //// Extension B (background code) ////
    chrome.runtime.onMessageExternal.addListener(
      function(message, sender, sendResponse) {
        if(sender.id && sender.id == "extension_A_id") {
          /* ..processing code.. */
        }
      }
    );
    
  3. 在扩展 A 中,添加检查扩展 B 是否已安装。通过 ping 来执行此操作:

    //// Extension A ////
    chrome.runtime.onStartup.addListener(function() {
      isNewInstalled(function(response) {
        if(response) {
          transferPreferences(response.versionB); // See step 5
        } else {
          // Nag user to install, see step 4
        }
      });
    });        
    
    function isNewInstalled(callback) {
      chrome.runtime.sendMessage(
        "extension_B_id",
        {areYouThere: true},
        passResponseOrFalse(callback)
      );
    }
    
    function passResponseOrFalse(callback) {
      return function(response) {
        // It's important to evaluate chrome.runtime.lastError
        //   to prevent uncatchable exception, see http://stackoverflow.com/q/28431505
        if(chrome.runtime.lastError || !response) {
          callback(false);
        } else {
          callback(response);
        }
      }
    }
    
    //// Extension B (processing code) ////
    // Send version number just in case
    if(message.areYouThere) sendResponse({
      versionB: chrome.runtime.getManifest().version
    });
    
  4. 如果在第 3 步中没有安装扩展 B,请提醒用户安装它:显示一个页面,解释为什么需要升级并链接到 CWS 列表。此步骤需要用户输入。

  5. 如果扩展 B 已在步骤 3 中安装,则将用户选项转移过来并自行卸载:

    //// Extension A ////
    function transferPreferences(versionB) {
      /* ..validate version of B.. */
      var prefs = {};
      /* ..fill prefs with data that needs to be transfered (JSON-encodable).. */
      chrome.runtime.sendMessage(
        "extension_B_id",
        {
          versionA: chrome.runtime.getManifest().version,
          preferences: prefs
        },
        passResponseOrFalse(goodbyeCruelWorld)
      );
    }
    
    function goodbyeCruelWorld(response) {
      if(response.processed) {
        // Does not require management permission
        chrome.management.uninstallSelf();
      } else {
        console.warn("It is not my time to die yet.");
      }
    }
    
    //// Extension B, processing code ////
    if(message.preferences) {
      /* ..validate message.versionA and process message.preferences.. */
      sendResponse({processed: true});
    }
    
  6. 安装扩展程序 B 后,向(可能已安装的)扩展程序 A 发送消息,告知可以立即开始传输:

    //// Extension B, background code ////
    chrome.runtime.onInstalled.addListener(function(details) {
      /* ..maybe check details.reason and new version.. */
      chrome.runtime.sendMessage(
        "extension_A_id",
        {iAmHere: true, versionB: chrome.runtime.getManifest().version},
        ignoreResponse
      );
    });
    
    function ignoreResponse(response) {
      // Again, evaluate to avoid exceptions;
      //   if needed, this is the place to check if A is still installed
      return chrome.runtime.lastError;
    }
    
    //// Extension A, background code ////
    chrome.runtime.onMessageExternal.addListener(
      function(message, sender, sendResponse) {
        if(sender.id && sender.id == "extension_B_id") {
          if(message.iAmHere) {
            sendResponse({
              versionA: chrome.runtime.getManifest().version
            });
            transferPreferences(message.versionB);
          }
        }
      }
    );
    
  7. 使用上述所有内容发布对扩展 B 的更新。

结果:

  • 安装了 B 的用户不会注意到任何事情,因为 ignoreResponse 会吞噬消息错误;
  • B 更新后,同时安装的用户会立即启动传输,并且会安静地完成;
  • 只有 A 的用户在每次重新启动扩展程序时都会被提醒安装 B,然后传输将自动开始。

最后一个问题是不要用 A 的偏好来破坏 B 的偏好;留给读者作为练习(也取决于实现)。

【讨论】:

  • 请注意:我没有实际测试过上面的代码,它可能包含愚蠢的错误和/或拼写错误;欢迎对此进行修改。
  • 谢谢,很有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 2018-05-21
  • 2012-07-12
  • 1970-01-01
相关资源
最近更新 更多