この翻訳は不完全です。英語から この記事を翻訳 してください。

This article gives an overview of how Firefox extension developers can ensure that their code works with multiprocess Firefox.

In current versions of desktop Firefox, chrome code (including code inserted by extensions) and content run in the same operating system process. So extensions can access content directly:

gBrowser.selectedBrowser.contentDocument.body.innerHTML = "replaced by chrome code";

However, in multiprocess Firefox (also called Electrolysis or E10S), the extension's code will run in a different process from content, and this kind of direct access will no longer be possible.

Instead, the extension will need to factor code that touches content into separate scripts that are called frame scripts. Frame scripts run in the content process and get direct access to content. Frame scripts communicate with the rest of the extension using a message-passing API.

Although content is allowed to send synchronous messages to the extension's main code, the main code must use asynchronous messaging when it's communicating with the frame script. This is to ensure that the Firefox UI process can't be blocked by the content process.

For more details on using the message manager and content scripts, refer to the message manager guide. The rest of this article explains how to work out if you're affected or not, provides an overview of the sorts of changes that are needed, then walks through the process of porting some simple extension patterns so they work properly with multiprocess Firefox.

Checking whether you're affected

As a rule:

To know for sure, you need to test it, and setting that up is a two-step process:

  • switch on multiprocess support in Firefox: multiprocess support is in Firefox Nightly, but is hiding behind a preference. To enable it visit about:config, find the preference named browser.tab.remote.autostart, set it to true, and restart the browser. As a visual indicator that you're running multiprocess Firefox, the titles of tabs are underlined.
  • declare that your extension is multiprocess compatible: to make migration to multiprocess Firefox easier, we've implemented shims that help extensions to work even when they're not compatible. To check whether your extension is really compatible you need to disable these shims. To do that, add a new property to your extension's install.rdf named multiprocessCompatible, with a value of true. (note that this flag isn't implemented yet, see bug 1029926).

Now you'll be able to test your extension in multiprocess Firefox, with no compatibility shims. At the moment you can't actually install extensions in multiprocess Firefox, so you have to install the extension, then switch on multiprocess support. This is being tracked as bug 952201.

Updating your code

The general approach to updating your code is:

  • factor the part of your extension that accesses web content into one or more separate scripts. In multiprocess Firefox these are called frame scripts.
  • register chrome:// URLs for your frame scripts
  • use a message manager to load the scripts into browser objects
  • if you need to communicate between the main extension code and a frame script, use message manager APIs to do so

There are more details on this in the message manager documentation.

Compatibility shims

To help developers migrate their extensions to multiprocess Firefox we're implementing a number of compatibility shims that in many cases will mean extensions continue to function in multiprocess Firefox without needing any updates. For example: whenever extensions try to access web content, the browser will return a Cross Process Object Wrapper that gives the chrome code synchronous access to the content.

We're still working out which shims will be needed by analysing extensions that break in multiprocess Firefox, so for now the best way to find out which shims are implemented is to see the tracking bug for the work.

However, these shims are not a substitute for migrating extensions:

  • they are only a temporary measure, and will be removed eventually
  • they can have a bad effect on responsiveness
  • there are likely to be edge cases in which they don't work properly

Examples

This section walks through the process of porting a few different sorts of extension. The extensions are all extremely simple, and are intended to represent fundamental extension patterns that require different handling in multiprocess Firefox.

You can find all the source code for these examples in the e10s-example-addons GitHub repository.

Run a script in all pages

The first extension runs some code on every page load. The code doesn't need to interact with any other part of the extension: it just makes some predetermined modification to the page. In this case it adds a border to the document's body.

It does this by attaching to a XUL overlay a version of the "On page load" code snippet:

var myExtension = {  
    init: function() {  
        // The event can be DOMContentLoaded, pageshow, pagehide, load or unload.  
        if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);  
    },  
    onPageLoad: function(aEvent) {  
        var doc = aEvent.originalTarget; // doc is document that triggered the event  
        if (doc.nodeName != "#document") return; // only documents  
        // make whatever modifications you want to doc
        doc.body.style.border = "5px solid blue";
    }  
}  

window.addEventListener("load", function load(event){  
    window.removeEventListener("load", load, false); //remove listener, no longer needed  
    myExtension.init();    
},false);

Because this code accesses web content directly, it won't work in multiprocess Firefox.

See the code for this example.

Porting to the message manager

To port this example using the message manager, we can put all the meat of the add-on in a frame script:

// frame-script.js

addEventListener("DOMContentLoaded", function(event) {
  var doc = event.originalTarget;
  if (doc.nodeName != "#document") return; // only documents
  doc.body.style.border = "5px solid red";
});

The main script, that we attach to the XUL overlay, is just a stub that uses the global message manager to load the frame script into each tab:

// chrome script
var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
  .getService(Ci.nsIMessageListenerManager);

globalMM.loadFrameScript("chrome://modify-all-pages/content/frame-script.js", true);

Porting to the Add-on SDK

A good alternative for an extension like this is to port to the Add-on SDK. The Add-on SDK includes a module called page-mod which is designed to load scripts into web pages. The Add-on SDK calls these scripts content scripts.

In this case the main extension code creates a page-mod to load a content script into every page loaded by the user:

// main.js

var pageMod = require("sdk/page-mod");
var self = require("sdk/self");

pageMod.PageMod({
  include: "*",
  contentScriptFile: self.data.url("modify-all-pages.js")
});

The content script can modify the page directly:

// modify-all-pages.js - content script

document.body.style.border = "5px solid green";

ドキュメントのタグと貢献者

このページの貢献者: mdnwebdocs-bot, Ginji.
最終更新者: mdnwebdocs-bot,