更新 Firefox 3.5 扩展

本文为试图更新其扩展以在 Firefox 3.5 中正常工作的扩展开发者提供了有用的信息。

更新基础知识

本节涵盖了您在更新扩展以适应新版 Firefox 时需要做的基础工作。

测试您的扩展

首先编辑扩展的 install.rdf 文件,将 maxVersion 更新为 3.5b4(如果您在 Firefox 3.5 Beta 4 上进行测试),并增加扩展的 version

然后创建一个新的 Firefox 配置文件,这样您的测试就不会危及您的常规配置文件。导航到包含 Firefox 的目录,然后输入命令:

bash
firefox -createProfile testBeta4

在 Mac 上,您需要一路导航到 Firefox 应用程序包内。

bash
cd /Applications/Firefox.app/Contents/MacOS/
firefox -createProfile testBeta4

通过在命令行中输入此命令,使用新配置文件启动 Firefox:

bash
firefox -P testBeta4

全面测试您的扩展。建议您将以下首选项设置为 true,以便在出现任何 JavaScript 警告或异常时收到通知:

  • javascript.options.strict
  • javascript.options.showInConsole

更新您的扩展

如果在测试过程中遇到任何问题,请更新您的代码以解决这些问题。本文包含有关可能需要一些工作才能完成的内容的有用信息。

完成之后,请尝试再次使用您的扩展,这次使用您的常规配置文件。这将有助于确保与任何现有的保存数据兼容。

在 addons.mozilla.org 上更新您的扩展

最后,是时候发布您更新后的扩展了。如果您的扩展不需要任何代码更改,您可以登录 AMO 仪表板并在那里更新兼容性版本。否则,您需要将新版本上传到 AMO。

有关更多信息,请参阅 提交插件到 AMO

访问 Places 数据库

在 Firefox 3.5 之前,直接使用 Storage API 访问 Places 数据库需要一些技巧。

js
var places = Components.classes["@mozilla.org/file/directory_service;1"]
  .getService(Components.interfaces.nsIProperties)
  .get("ProfD", Components.interfaces.nsIFile);
places.append("places.sqlite");
var db = Components.classes["@mozilla.org/storage/service;1"]
  .getService(Components.interfaces.mozIStorageService)
  .openDatabase(places);

这会手动构建一个通往 places.sqlite 数据库文件的路径,然后打开文件以供 Storage 访问。

Firefox 3.5 添加了一个专用服务,它提供了一种方便的方式来访问 Places 数据库;上述技术在 Firefox 3.5 或更高版本中不再有效。

js
var db = Components.classes[
  "@mozilla.org/browser/nav-history-service;1"
].getService(Components.interfaces.nsPIPlacesDatabase).DBConnection;

搜索文本框

timed 类型的 textbox 已弃用;您应该改用 search

在 Firefox 3 中,您可能使用过

xml
<textbox type="timed" timeout="1000" oncommand="alert(this.value);"/>

在 Firefox 3.5 中,您应该将其更改为

xml
<textbox type="search" timeout="1000" oncommand="alert(this.value);"/>

JSON

JSON.jsm JavaScript 模块在 Firefox 3.5 中已被移除,转而支持原生的 JSON 对象。有关详细信息,请参阅关于 JSON 的文章,其中概述了 JSON 以及如何在不同版本的 Firefox 中使用它。

为了确保与 Firefox 3 和 Firefox 3.5 的兼容性,您可以这样做:

js
if (typeof JSON === "undefined") {
  Components.utils.import("resource://gre/modules/JSON.jsm");
  JSON.parse = JSON.fromString;
  JSON.stringify = JSON.toString;
}

这通过导入 JSON.jsm JavaScript 模块(如果 JSON 不支持原生)来实现,然后将该模块提供的方法映射到原生 JSON 使用的方法,以便相同的调用都能正常工作。

您也可以通过直接使用 nsIJSON 接口来绕过此问题。

上下文菜单更改

为了支持 Gecko 1.9.1 中添加的新音频和视频功能,nsContextMenu 类已将 imageURL getter 重命名为 mediaURL;但是,imageURL 已于 2009 年 6 月 9 日重新添加。

Chrome 注册更改

Firefox 3.5 修复了一个可能允许使用远程 chrome 的安全漏洞。这将影响任何在其 chrome.manifest 文件中包含引用网站、数据或资源 URL 的资源的插件。有关详细信息,请参阅 Firefox 3.5 的安全更改

从请求中获取加载上下文

以前,可以通过查询各种 docShell API 从请求中获取加载上下文。特别是,使用 notificationCallbacks.getInterface(nsIDOMWindow) 来获取与加载关联的窗口对象是一种常见做法。虽然旧方法在某些情况下可能有效,但不再推荐使用(详情)。

正确且可靠的方法是使用 nsILoadContext(请参阅 接口定义)。

从 JavaScript,您可以这样做:

js
var loadContext;
try {
  loadContext = aRequest
    .QueryInterface(Components.interfaces.nsIChannel) // aRequest is equivalent to aSubject from observe
    .notificationCallbacks.getInterface(Components.interfaces.nsILoadContext);
} catch (ex) {
  try {
    loadContext = aRequest.loadGroup.notificationCallbacks.getInterface(
      Components.interfaces.nsILoadContext,
    );
  } catch (ex) {
    loadContext = null;
  }
}
// you can now use |loadContext.associatedWindow| to get the Window object

另一个 JavaScript 示例,如果上述方法不起作用:

js
// SOURCE: http://stackoverflow.com/questions/10719606/is-it-possible-to-know-the-target-domwindow-for-an-httprequest

function getWindowForRequest(request) {
  if (request instanceof Components.interfaces.nsIRequest) {
    try {
      if (request.notificationCallbacks) {
        return request.notificationCallbacks.getInterface(
          Components.interfaces.nsILoadContext,
        ).associatedWindow;
      }
    } catch (e) {}
    try {
      if (request.loadGroup && request.loadGroup.notificationCallbacks) {
        return request.loadGroup.notificationCallbacks.getInterface(
          Components.interfaces.nsILoadContext,
        ).associatedWindow;
      }
    } catch (e) {}
  }
  return null;
}

从 C++,您可以这样做:

cpp
nsCOMPtr<nsILoadContext> loadContext;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
NS_QueryNotificationCallbacks(channel, loadContext);

可自定义工具栏

在 Firefox 3.5 中,可自定义工具栏的行为已发生更改,现在 <xul:toolbar/> 绑定会从其关联的 <xul:toolbarpalette/> 中移除工具栏项并将其添加到工具栏,而不是克隆它们并复制到工具栏。这意味着调色板现在只会包含不在工具栏上的项,而不再像以前那样包含无论是否显示在工具栏上的所有可自定义元素。这可能会给那些依赖于能够从 <xul:toolbarpalette/> 中检索所有可自定义工具栏项,或尝试动态将项插入调色板以在工具栏自定义期间使其可用的插件带来麻烦。有关更多信息,请参阅 Firefox bug 407725WebKit bug 467045

XPCNativeWrapper

从 Firefox 3.5 开始,您不能再在使用了 XPCNativeWrapper 自动化的 chrome 包中使用 data: 绑定。这解决了潜在的安全问题。

XUL 文档现在会进行 XPCNativeWrapper 处理,因此您现在需要使用 getAttribute() 方法来获取属性值,而不是直接读取它们。

如果您的扩展使用了 xpcnativewrappers=no(这种情况不应该发生,因为它不安全),那么从 Firefox 3.5 开始,该扩展的 XBL 将不会应用于使用 XPCNativeWrapper 自动化的文档。

新的相关功能

监听所有标签页上的事件

Firefox 3.5 引入了对添加和移除侦听所有标签页的进度监听器的支持。有关详细信息,请参阅 监听所有标签页上的事件

面向主题开发者

  • 请参阅 Firefox 3.5 中的主题更改
  • 访问 MozillaZine 论坛 FF3.1 的主题更改,以获取 3.0 和 3.1 之间影响主题开发者的所有更改的概览/列表。这包括新的 CSS 功能(如 nth-child、-moz-box-shadow 等)、现有小部件的更改、整体 UI 改进以及新的 FF3.1 功能(音频/视频支持、隐私浏览、扩展的会话恢复、盒状/窗口/文本阴影)。