From a065e04d529da1d847b5062a12c46d916408bf32 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 21:46:22 -0500 Subject: update based on https://github.com/mdn/yari/issues/2028 --- .../working_with_multiprocess_firefox/index.html | 235 --------------------- 1 file changed, 235 deletions(-) delete mode 100644 files/zh-tw/archive/add-ons/working_with_multiprocess_firefox/index.html (limited to 'files/zh-tw/archive/add-ons/working_with_multiprocess_firefox/index.html') diff --git a/files/zh-tw/archive/add-ons/working_with_multiprocess_firefox/index.html b/files/zh-tw/archive/add-ons/working_with_multiprocess_firefox/index.html deleted file mode 100644 index 8b685c379e..0000000000 --- a/files/zh-tw/archive/add-ons/working_with_multiprocess_firefox/index.html +++ /dev/null @@ -1,235 +0,0 @@ ---- -title: Working with multiprocess Firefox -slug: Archive/Add-ons/Working_with_multiprocess_Firefox -translation_of: Archive/Add-ons/Working_with_multiprocess_Firefox ---- -
-

這篇文章提供給 Firefox 擴充套件開發者;文中概述了如何讓擴充套件可以執行於多行程的 Firefox.

-
-

在多行程的 Firefox 之前的版本, chrome code (including code inserted by extensions) 和 content 執行於同一作業系統行程中,所以擴充套件可以直接存取 content:

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

然而,在多行程的 Firefox (也稱為 Electrolysis 或 E10S),套件的程式碼與 content 將執行於不同的行程中,因此不再可能直接地存取。

-

取而代之地, the extension will need to factor code that touches content into separate scripts that are called frame scripts. Frame scripts 執行在 content 行程,並可以直接存取 content. Frame scripts 藉由 message-passing API 和套件其餘的部份通訊。

-

當套件程式碼(執行於 chrome 行程中)向套件的 frame script(執行於 content 行程中) 傳訊時,必須使用非同步訊息。

-

content 行程允許向 chrome 行程傳遞同步或非同步訊息,但是,非同步通訊是較好的選擇。

-

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.

-

確認你是否受到相容性影響

-

As a rule:

- -

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

- -

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 1055808.

-

Updating your code

-

The general approach to updating your code is:

- -

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

-

Backwards compatibility of the new APIs

-

With multiprocess support turned off, the e10s messaging APIs are still available and functional. They have been available in one form or another since Firefox 4; however, the original APIs are different than the current ones. Some known differences:

- -

You should test your changes not only in nightlies with multiprocess support turned on, but also in releases you intend to support with multiprocess support turned off.

-

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

-
-

See the code for this example.

-
-

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.
-

-

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
-// will run in the content process
-
-addEventListener("DOMContentLoaded", function(event) {
-  var doc = event.originalTarget;
-  if (doc.nodeName != "#document") return; // only documents
-  doc.body.style.border = "5px solid red";
-});
-
-

We'll register a chrome:// URL for the frame script:

-
// chrome.manifest
-
-content    modify-all-pages    chrome/content/
-
-

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
-// will run in the chrome process
-
-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";
-

Run a script in the active tab

-
-

See the code for this example.

-
-

The example demonstrates how an extension can:

- -

The example is a restartless extension that adds a button using the CustomizableUI module. When the user clicks the button, the extension runs some code that modifies the current tab. The basic infrastructure is taken from the Australis "Hello World" extension written by Jorge Villalobos.
-
- What the code actually does is: find any <img> elements and replace their src with a link to a silly GIF randomly chosen from a list hardcoded into the extension. The silly gifs are taken from the list in the Whimsy extension.

-

The first version accesses the page directly, so it's not multiprocess compatible:

-
// bootstrap.js
-
-let Gifinate = {
-  init : function() {
-    let io =
-      Cc["@mozilla.org/network/io-service;1"].
-        getService(Ci.nsIIOService);
-
-    // the 'style' directive isn't supported in chrome.manifest for bootstrapped
-    // extensions, so this is the manual way of doing the same.
-    this._ss =
-      Cc["@mozilla.org/content/style-sheet-service;1"].
-        getService(Ci.nsIStyleSheetService);
-    this._uri = io.newURI("chrome://gifinate/skin/toolbar.css", null, null);
-    this._ss.loadAndRegisterSheet(this._uri, this._ss.USER_SHEET);
-
-    // create widget and add it to the main toolbar.
-    CustomizableUI.createWidget(
-      { id : "gifinate-button",
-        defaultArea : CustomizableUI.AREA_NAVBAR,
-        label : "Gifinate",
-        tooltiptext : "Gifinate!",
-        onCommand : function(aEvent) {
-          Gifinate.replaceImages(aEvent.target.ownerDocument.defaultView.content.document);
-        }
-      });
-  },
-
-  replaceImages : function(contentDocument) {
-      let images = contentDocument.getElementsByTagName("img");
-      for (var i = 0; i < images.length; ++i) {
-        let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)];
-        images[i].src = gif;
-      }
-    },
-

-

Porting to the message manager

-

To port this example to the message manager we'll make onCommand load a frame script into the current <browser>, then listen for "request-gifs" messages from the frame script. The "request-gifs" message is expected to contain the number of GIFs we need for this page: the message listener retrieves and returns that many GIFs.

-
// bootstrap.js
-// will run in the chrome process
-
-let Gifinate = {
-  init : function() {
-    let io =
-      Cc["@mozilla.org/network/io-service;1"].
-        getService(Ci.nsIIOService);
-
-    // the 'style' directive isn't supported in chrome.manifest for bootstrapped
-    // extensions, so this is the manual way of doing the same.
-    this._ss =
-      Cc["@mozilla.org/content/style-sheet-service;1"].
-        getService(Ci.nsIStyleSheetService);
-    this._uri = io.newURI("chrome://gifinate/skin/toolbar.css", null, null);
-    this._ss.loadAndRegisterSheet(this._uri, this._ss.USER_SHEET);
-
-    // create widget and add it to the main toolbar.
-    CustomizableUI.createWidget(
-      { id : "gifinate-button",
-        defaultArea : CustomizableUI.AREA_NAVBAR,
-        label : "Gifinate Button",
-        tooltiptext : "Gifinate!",
-        onCommand : function(aEvent) {
-          Gifinate.replaceImages(aEvent.target.ownerDocument);
-        }
-      });
-  },
-
-  replaceImages : function(xulDocument) {
-    var browserMM = xulDocument.defaultView.gBrowser.selectedBrowser.messageManager;
-    browserMM.loadFrameScript("chrome://gifinate/content/frame-script.js", false);
-    browserMM.addMessageListener("request-gifs", Gifinate.getGifs);
-  },
-
-  getGifs : function(message) {
-    var gifsToReturn = new Array(message.data);
-    for (var i = 0; i < gifsToReturn.length; i++) {
-      let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)];
-      gifsToReturn[i] = gif;
-    }
-    return gifsToReturn;
-  },
-
-

Again, we need to register a chrome:// URL for the frame script:

-
// chrome.manifest
-
-content gifinate frame-script.js
-

In the frame script, we get all the <img> elements and send the "request-gifs" message to the main add-on code. Because this is a frame script we can make it a synchronous message, and update the src attributes with the value it returns:

-
// frame-script.js
-// will run in the content process
-
-var images = content.document.getElementsByTagName("img");
-var response = sendSyncMessage("request-gifs", images.length);
-var gifs = response[0];
-
-for (var i = 0; i < images.length; ++i) {
-  images[i].src = gifs[i];
-}
-

The overall flow of the add-on now looks like this:
-

-

Known bugs

-

This is a list of open bugs likely to affect add-on developers migrating to multiprocess Firefox:

- -- cgit v1.2.3-54-g00ecf