【问题标题】:Upgrading an addon to be compatible with Firefox 4.0, but trying to keep it compatible with 3.x also. Advice?升级插件以与 Firefox 4.0 兼容,但也尝试使其与 3.x 兼容。建议?
【发布时间】:2010-12-17 21:53:28
【问题描述】:

我有一个为 Firefox 3.6 编写的插件,现在我正在为 Firefox 4.0 升级它,同时尝试使其与 3.6 兼容。有没有人有任何尝试这样做的经验,或者关于如何在不让代码变得过于意大利面条式的情况下做到这一点的提示?

在一些地方保持它与两个版本兼容意味着做这样的事情:

.myAddonClass {
  -moz-background-size: 100% 100%; /* Fx 3.x */
  background-size: 100% 100%; /* Fx 4.x */
}

在两个版本中都会产生 CSS 警告。我可以忍受这一点。还有其他地方我正在做这样的事情:

/** get the current version of this addon */
function getVersion() {
  var version;
  if (Application.extensions) { // Fx 3.x
    version = Application.extensions.get('myaddon@example.com').version;  
  }
  else { // Fx 4.x
    Components.utils.import('resource://gre/modules/AddonManager.jsm');
    AddonManager.getAddonByID('myaddon@example.com', function(addon) {  
      version = addon.version;  
    });
    sleepUntil(function() {
      return version;
    }
  }
  return version;
}

(其中 sleepUntil 是一个使用 Thread.processNextEvent technique 的实用程序函数)

检查Application.extensions 是否已定义似乎比直接检查Application.version 字符串更干净,但这种方法可能存在一些我不知道的缺陷?

我在尝试将内容插入网页时也遇到了问题。在一种情况下,doc.body.appendChild 在 3.x 中工作,但在 4.x 中没有,所以我尝试这样做:

try { // Fx 3.x
  doc.body.appendChild(myElement);
}
catch (e) { // Fx 4.x
  let span = doc.createElement('span');
  doc.body.appendChild(span);
  span.innerHTML = outerHTML(myElement);
}

上面的代码不起作用,但如果我在 doc.body.appendChild(myElement) 之前插入一个 throw new Error('') 则它确实起作用,这表明在 Firefox 4 中,appendChild 调用显然在它之前以某种方式修改了 myElement引发错误。我确信我可以弄清楚如何让这个特定的代码 sn-p 工作,但我担心我也会遇到更多这样的问题,所以我想看看其他人是否已经经历了类似的过程,并且有任何我应该注意的提示。

很抱歉这个冗长的问题。 这是我真正要问的:

  1. 对于尝试同时与 Firefox 3 和 Firefox 4 兼容的插件,您有什么建议?
  2. 您如何看待对代码进行分支以便我们为 3.x 提供一个版本而为 4.x 提供另一个版本的想法?然后,我们必须将任何新功能应用于两个版本,并在两个版本中进行测试,等等。
  3. 一般来说,最好是测试是否存在您想要的特定功能(就像我对if (Application.extensions) ... 或try/catch 所做的那样)还是只检查Application.version 是否以“3”或“4”开头?

【问题讨论】:

  • 当然,一种选择是在 Firefox 4 发布后不久就放弃对 Firefox 3.x 的支持,但最好还是等着看 Firefox 3.x 用户是否犹豫不决升级...
  • 如果有人想知道,该 try/catch 的解决方案就是执行 doc.body.appendChild(doc.importNode(myElement)),这在两个版本中都能完美运行。
  • 与其写doc.body.appendChild(doc.importNode(myElement)),不如使用doc.createElement创建myElement而不是使用其他文档创建它吗?
  • @Neil 我现在没有代码在我面前,但我认为原因是元素足够大且足够复杂,我想在自己的 html 文件中定义它,然后将其加载到隐藏的 iframe 中进行解析,然后直接将其复制到 doc
  • 在这种情况下,我同意 importNode 是要走的路。你很幸运,它恰好在 Firefox 3.6 中工作;如果您阅读官方 DOM 文档,则需要使用adoptNode 或 importNode。

标签: firefox firefox-addon compatibility firefox4


【解决方案1】:

对于尝试同时与 Firefox 3 和 Firefox 4 兼容的插件,您有什么建议?

我建议为两个最新的主要版本使用一个 XPI。使用旧版本的人是一个失败的案例,对于不同的“活动”版本有两个 XPI 令人困惑(我最近没有尝试过 AMO 呈现这种方式的方式,但这是我的旧印象)。

您如何看待将代码分支以便我们有一个 3.x 版本和另一个 4.x 版本的想法?然后,我们必须将任何新功能应用于两个版本,并在两个版本中进行测试,等等。

只有当代码变得过于意大利面时,我才会这样做。作为一个爱好者,我会停止更新旧版本,留给使用旧​​ Firefox 版本的人使用。您可以在 AMO 上查看您的扩展程序的统计信息,以检查新 Firefox 版本的采用率(即使统计信息页面不是很容易使用。)

一般来说,最好是测试是否存在您想要的特定功能(就像我对 if (Application.extensions) ... 或 try/catch 所做的那样)还是只检查 Application.version 是否以 ' 开头3'还是'4'?

在这里,基于能力的分支无关紧要,因为您处理的是一组固定的主机应用程序,这与网页不同。

但请记住可能的副作用:

  • 检查应用程序的版本会使移植到其他应用程序变得更加困难,因此如果您的部分代码仅使用平台功能,而不是特定应用程序的功能,那么测试平台版本会更有意义。
  • try..catch 还可以捕获与您所期望的错误无关的其他错误。我会避免它。

附言

1) 为避免未知属性的 CSS 警告(如果有很多),您可以通过 appversion in chrome.manifest 为不同的版本使用不同的样式

2) 我认为 Thread.processNextEvent 技术很危险,因为它会阻止调用堆栈在您完成之前展开。

【讨论】:

  • “其他应用程序”是指其他 Mozilla 产品,例如 Seamonkey?
  • 您能否详细说明为什么 Thread.processNextEvent 很危险,或者发布一个描述它的链接?
  • @MatrixFrog:1)是的; 2)您链接到的页面本身会发出警告。想象一下,您的事件是从必须在 AddonManager.getAddonByID 调用其回调之前返回的函数 F 调用的。不将控制权返回给 F 将使内部 processNextEvent 循环无休止地运行。我并不是说这会发生在你的情况下,只是你正在使用的一种非犹太技术。
【解决方案2】:

来自 Mozilla #addons IRC 频道的一个建议,用于我的 getVersion() 函数:编写一个由 nsIExtensionManager 支持的 AddonManager 模型。 Or use this one。这样,函数本身就不必具有 if/then 模式。

【讨论】:

    猜你喜欢
    • 2012-04-08
    • 1970-01-01
    • 2020-02-23
    • 2019-06-28
    • 2018-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多