The message manager

  • Revision slug: The_message_manager
  • Revision title: The message manager
  • Revision id: 57768
  • Created:
  • Creator: Piro
  • Is current revision? No
  • Comment Reverted to earlier version; one or more formatting changes

Revision Content

{{ gecko_minversion_header("2.0") }}

The message manager is a message-passing framework for chrome script to touch content. In Firefox 4, chrome script can access content and content docshells directly through properties on a XUL <browser> element. But in Mobile Firefox 4 and in a future version of Firefox, content will run in separate processes from chrome, and direct access will not be possible. Instead, chrome script must use separate scripts for code which must synchronously touch content, and run these scripts asynchronously using the message manager. The message manager is available in Firefox 4 so that Firefox code and extensions can start using the new API immediately, even before Firefox switches to use content processes.

Note: The message manager is a JavaScript-only API and will not be made available to binary components.

Messages

Messages passed through the message manager have a name and optional data. Sending a message is simple:

manager.sendAsyncMessage("message-name", {"foo": 2});

The data is serialized in the message. This means that it is not possible to send object references via messages.

When a message is sent from chrome to content, it must be dispatched asynchronously, because chrome is not allowed to block on content. However, content scripts may synchronously send a message to chrome and wait for a response:

var response = manager.sendSyncMessage("message-name", {"foo": 1});

Message listeners

Script can add message listeners to a message manager:

function listenerFunction(cx)
{
  var messageName = cx.name;
  var sync = cx.sync; // true if this message was sent synchronously and expects a response
  var data = cx.json;
}

manager.addMessageListener(listenerFunction);
manager.removeMessageListener(listenerFunction);

browser.messageManager

There is one message manager per XUL {{ XULElem("browser") }} element. To get the message manager for the browser, simply use browser.messageManager.

window.messageManager

There is also a special window.messageManager which allows a chrome window to receive messages from any <browser> loaded in the window. Messages are sent to the <browser>.messageManager first, and then to the window.messageManager. Note that you cannot send messages to the window messageManager, you can only register to receive messages. When a message is received from a content process, listeners in the browser.messageManager are called first, followed by the ones in the window's message manager. If multiple message manager are listening for a synchronous message, the last one's return value is sent back to the content script.

Content scripts

In order for messages to be useful, a content script must be installed which either sends or receives messages and interacts with the DOM loaded into the browser. Before loading any pages into a <browser>, code running in the Chrome process uses browser.messageManager.loadFrameScript() to inject a script into the content process. That script then can add listeners into the content process and send result messages back to the chrome process.

Content scripts have the following globals:

  • content - The DOM window of the content loaded in the browser.
  • docShell - The nsIDocShell associated with the browser.
  • addMessageListener
  • removeMessageListener
  • sendAsyncMessage
  • sendSyncMessage
  • dump

A simple example

This simple example forwards all clicks on HTML {{ HTMLElement("a") }} elements to chrome. This is a simplified example, and won't work for child elements, but it should help understand how the messaging system works.

The content script

This code runs in the content process to set up an event listener that forwards the click events to the chrome process.

addEventListener("click",
  function(e) {
    if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &&
        sendSyncMessage("linkclick", { href : e.target.href })[0].cancel) {
      e.preventDefault();
    }
  },
  false);

The chrome script

This code runs in chrome to receive the click events and load the content script.

browser.messageManager.addMessageListener("linkclick",
  function(m) {
    return { cancel: !confirm("Do you want to load " + m.json.href) };
  }
);
browser.messageManager.loadFrameScript("chrome://myextension/content/checklinks.js", true);

See also

{{ languages( { "ja": "ja/The_message_manager"} ) }}

Revision Source

<p>{{ gecko_minversion_header("2.0") }}</p>
<p>The message manager is a message-passing framework for chrome script to touch content. In Firefox 4, chrome script can access content and content docshells directly through properties on a XUL &lt;browser&gt; element. But in Mobile Firefox 4 and in a future version of Firefox, content will run in separate processes from chrome, and direct access will not be possible. Instead, chrome script must use separate scripts for code which must synchronously touch content, and run these scripts asynchronously using the message manager. The message manager is available in Firefox 4 so that Firefox code and extensions can start using the new API immediately, even before Firefox switches to use content processes.</p>
<div class="note"><strong>Note:</strong> The message manager is a JavaScript-only API and will not be made available to binary components.</div>
<h2>Messages</h2>
<p>Messages passed through the message manager have a name and optional data. Sending a message is simple:</p>
<pre>manager.sendAsyncMessage("message-name", {"foo": 2});
</pre>
<p>The data is serialized in the message. This means that it is not possible to send object references via messages.</p>
<p>When a message is sent from chrome to content, it must be dispatched asynchronously, because chrome is not allowed to block on content. However, content scripts may synchronously send a message to chrome and wait for a response:</p>
<pre>var response = manager.sendSyncMessage("message-name", {"foo": 1});
</pre>
<h2>Message listeners</h2>
<p>Script can add message listeners to a message manager:</p>
<pre>function listenerFunction(cx)
{
  var messageName = cx.name;
  var sync = cx.sync; // true if this message was sent synchronously and expects a response
  var data = cx.json;
}

manager.addMessageListener(listenerFunction);
manager.removeMessageListener(listenerFunction);
</pre>
<h2>browser.messageManager</h2>
<p>There is one message manager per XUL {{ XULElem("browser") }} element. To get the message manager for the browser, simply use <code>browser.messageManager</code>.</p>
<h2>window.messageManager</h2>
<p>There is also a special window.messageManager which allows a chrome window to receive messages from any &lt;browser&gt; loaded in the window. Messages are sent to the &lt;browser&gt;.messageManager first, and then to the window.messageManager. Note that you cannot <em>send </em>messages to the window messageManager, you can only register to receive messages. When a message is received from a content process, listeners in the browser.messageManager are called first, followed by the ones in the window's message manager. If multiple message manager are listening for a synchronous message, the last one's return value is sent back to the content script.</p>
<h2>Content scripts</h2>
<p>In order for messages to be useful, a content script must be installed which either sends or receives messages and interacts with the DOM loaded into the browser. Before loading any pages into a &lt;browser&gt;, code running in the Chrome process uses browser.messageManager.loadFrameScript() to inject a script into the content process. That script then can add listeners into the content process and send result messages back to the chrome process.</p>
<p>Content scripts have the following globals:</p>
<ul> <li>content - The DOM window of the content loaded in the browser.</li> <li>docShell - The nsIDocShell associated with the browser.</li> <li>addMessageListener</li> <li>removeMessageListener</li> <li>sendAsyncMessage</li> <li>sendSyncMessage</li> <li>dump</li>
</ul>
<h2>A simple example</h2>
<p>This simple example forwards all clicks on HTML {{ HTMLElement("a") }} elements to chrome. This is a simplified example, and won't work for child elements, but it should help understand how the messaging system works.</p>
<h3>The content script</h3>
<p>This code runs in the content process to set up an event listener that forwards the click events to the chrome process.</p>
<pre>addEventListener("click",
  function(e) {
    if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &amp;&amp;
        sendSyncMessage("linkclick", { href : e.target.href })[0].cancel) {
      e.preventDefault();
    }
  },
  false);</pre>
<h3>The chrome script</h3>
<p>This code runs in chrome to receive the click events and load the content script.</p>
<pre class="brush: js">browser.messageManager.addMessageListener("linkclick",
  function(m) {
    return { cancel: !confirm("Do you want to load " + m.json.href) };
  }
);
browser.messageManager.loadFrameScript("chrome://myextension/content/checklinks.js", true);
</pre>
<h2>See also</h2>
<ul> <li><a class=" link-https" href="https://wiki.mozilla.org/Content_Process_Event_Handlers" title="https://wiki.mozilla.org/Content_Process_Event_Handlers">Content Process Event Handlers</a> (design document)</li>
</ul> <p>{{ languages( { "ja": "ja/The_message_manager"} ) }}</p>
Revert to this revision