Process Model

Note

This was a proposal document.  The example scripts are obsolete.

Introduction
Chromium extensions will follow a multi-process architecture to share the same kind of stability and security that regular web pages have in Chromium.  All of an extension's code runs in a single process, separate from the browser (with the exception of user scripts which run in whichever renderers they apply to).  Extension code can communicate with user scripts, and vice versa, through a message passing API.

The Extension Process

The extension process is a special type of renderer that controls rendering of the various pieces of UI that an extension wishes to add to the browser chrome.  It is not able to interact with content directly - instead, the extension can arrange for user scripts to be injected into a page that the extension process can then communicate with.

Each piece of an extension's UI is simply an HTML page rendered by the extension process.  All standard web APIs will be available to these pages, with full CSS and JavaScript support.  Chromium will also provide special APIs usable only by extensions for hooking these replacements into the Chromium UI in the appropriate place.

Extension Pages

An extension modifies the browser UI via one or more HTML pages, registered in the manifest.  These pages are run in the context of the extension process, have special access to the browser UI, and can communicate with each other and with user scripts.  Extension pages are loaded and run when the extension is loaded (generally on browser startup).  They can register to listen for special events, like tab switching, window closing, navigation, etc.

It is also possible to register hidden pages.  This allows the extension to run script, or load an NPAPI plugin, without needing to display UI anywhere.

As an example, consider an Auto-Link extension that shows a button on the toolbar which converts all addresses on the page to links to Google Maps.  Maybe the button is disabled when there are no addresses on the page.  This extension would consist of:
  1. a user script which detects addresses and has the ability to convert addresses to links
  2. a toolstrip containing the HTML, CSS, and script necessary to draw the button
  3. a hidden page that serves as the "master" script, that listens for browser events and controls the state of the toolbar button
manifest.json (snippet):
...
// these two are loaded into the extension process
hidden_pages: ["chrome/master.html"],
toolstrip: "chrome/toolstrip.html",
// this is loaded into renderers
user_scripts: {
  "matc
hes": ["http://*/*", "https://*/*"],
"
files": ["content/address.js"]
},
...

content/address.js:
extension.addEventListener("on-message", function (e) {
  if (e.message == "autolink") {
    doAutoLink();
  } else if (e.message == "check-for-addresses") {
    var found = checkForAddresses();  // implemented elsewhere
    e.channel.postMessage({hasAddresses: found});
  }
}, false);

chrome/master.html:
<html>
<body>
  <script>
    extension.addEventListener("tab-changed", function (e) {
      
// user switched tabs, so check if our button should be enabled
      e.tab.postMessage("check-for-addresses");
    }, false);

    extension.addEventListener("on-message", function (e) {
      
// we got a response from our user script
      var found = e.message["hasAddresses"];
      var toolstrip = e.tab.browserWindow.getToolstrip("autolink");
      toolstrip.contentWindow.document.getElementById("autolink").disabled = !found;
    }, false);
  </script>
</body>
</html

chrome/toolstrip.html:
<html>
<body>
  <button onclick="autolink()" id="autolink">Auto-Link</button>
  <script>
    function autolink() {
      extension.currentTab.postMessage("autolink");
    }
  </script>
</body>
</html>

Note: The APIs presented here are not meant to be final, but are shown merely to give an idea how the different pieces fit together and communicate with each other.
Note: It's possible that toolstrip.html could have itself contained the script that is in master.html, but this example avoids that in order to demonstrate a hidden page.

Implementation

The extension process is simply a regular renderer process with extension-specific APIs.  Each piece of UI (toolstrip, sidebar, etc) is a single HTML page with its own RenderView in the extension process.   An extension's pages all have the same origin "chrome-extension://<extension-id>".  Process separation by origin is done similarly to web renderers, in that each extension generally gets its own process, but may share a process with another extension as resource constraints demand.

Since each extension page runs within the same extension process, they can obtain script handles to each other and manipulate contents directly (see use of "getToolstrip()" in example above).  In order to communicate with user scripts, which are loaded in renderer processes, a message-passing API is available, with ways to open a message channel to a specific tab or extension component.

Other Considerations

  • JavaScript console.  Ideally, one console would be able to inspect all of an extension's components.  This suggests they're treated like iframes of a main extension component.
Comments