File:  [mozdev] / archangel / www / new-protocol.html
Revision 1.7: download - view: text, annotated - select for diffs - revision graph
Tue Jan 6 01:10:59 2004 UTC (13 years, 9 months ago) by marnanel
Branches: MAIN
CVS tags: HEAD
flags info

<h1 class="page-header">HOWTO: add a new protocol to Mozilla</h1>

<p><b>STILL BEING WRITTEN.</b></p>

<p><b>Prerequisite:</b> Some idea about <a href="http://gnusto.mozdev.org/code/components-101.html">component-based architecture</a>, and XPCOM in particular.</p>

<p><b>Overview:</b> This document gives an overview of the process needed to implement a new protocol handler in Mozilla, so that you can make it recognise new kinds of URL. (For example, you might invent a protocol called <code>penguin</code>. Then users would be able to retrieve some kind of document by entering URLs such as "<code>penguin://antarctica/fish.fish.fish</code>").</p>

<p>You do this by creating two components: a <dfn>protocol handler</dfn> and a <dfn>channel</dfn>. The protocol handler is Mozilla's one-stop shop for information about your protocol. When the user asks for a URL from your protocol, Mozilla will ask the protocol handler to return a channel, which is a component which can be repeatedly polled to retrieve more and more of the document.</p>

<p><span style="font-weight: bolder; font-size: 15pt">I'm not an expert. This document may contain mistakes</span>, though I hope it doesn't. If you find any, please let me know.</p>

<p><b>Note about Archangel:</b> <a href="/">Archangel</a>'s back end is a component <a href="http://www.mozdev.org/source/browse/archangel/src/archangel-client.js"><code>@marnanel.org/archangel/client;1</code></a>, with the interface <a href="http://www.mozdev.org/source/browse/archangel/src/archangel-client.idl"><code>nsIReverseGossip</code></a>. This means that all the details of RGTP are kept separate from the implementation of the <code>rgtp:</code> protocol, which lives in the file <a href="http://www.mozdev.org/source/browse/archangel/src/archangel-protocol.js"><code>archangel-protocol.js</code></a>. You might like to follow through that file as you read this document.</p>

<p><b>The protocol handler in detail:</b> Define a component with the contract ID<blockquote><code>@mozilla.org/network/protocol;1?name=<var>protocol</var></blockquote>So in our example:<blockquote><code>@mozilla.org/network/protocol;1?name=rgtp</blockquote></p>

<p>This component should implement <a href="http://www.mozilla.org/projects/embedding/embedapiref/embedapi57.html">nsIProtocolHandler</a>, which involves implementing these attributes and methods:</p>

<dl>
<dt><code>nsIChannel newChannel(<var>uri</var>)</code></dt>
<dd>Returns a channel which can serve the document which <var>uri</var> points at. See below for how to make the channel.</dd>

<dt><code>nsIURI newURI(<var>original</var>, <var>charset</var>, <var>baseURI</var>)</code></dt>
<dd>Returns an nsIURI object created from a string. Mostly you can just instantiate an <a href="http://www.xulplanet.com/references/xpcomref/comps/c_networkstandardurl1.html">@mozilla.org/network/standard-url;1</a> and let it do the work for you. If <var>baseURI</var> is set, the string is relative to another URI, which is <a href="http://diveintomark.org/archives/2004/01/02/relative-uris">a pain in the neck</a>.</dd>

<dt><code>long defaultPort</code></dt>
<dd>The default <a href="http://www.iana.org/assignments/port-numbers">port number assigned to the protocol</a>. (Of course, users can pick their own port numbers using the <code>:<var>port</var></code> syntax in the URL, but this is what they get if they don't.) If port numbers don't make sense with this protocol, either use -1 or use a dummy value. (<a href="http://www.mozilla.org/projects/venkman/">Venkman</a>'s protocol "<code>x-jsd</code>" uses <a href="http://lxr.mozilla.org/mozilla/source/extensions/venkman/js/venkman-service.js#133">2206</a>, a <a href="http://www.google.com/search?q=dana+2206+ghostbusters">reference</a> to <a href="http://us.imdb.com/title/tt0087332/"><cite>Ghostbusters</cite></a>).</dd>

<dt><code>ACstring scheme</code></dt>
<dd>The name of this scheme, the same as <var>protocol</var> in the contract ID. (I'm not sure why this is needed, because you already know the protocol if you've got this far. But there it is.)</dd>

<dt><code>long protocolFlags</code></dt>
<dd>Sum whichever of the following are relevant:

<table>
<tr>
<th>Identifier</th>
<th>Value</th>
<th>When to use</th>
</tr>

<tr>
<th><code>URI_NORELATIVE</code></th>
<td>1</td>
<td>This protocol can't serve up documents which contain relative links.</td>
</tr>

<tr>
<th><code>URI_NOAUTH</code></th>
<td>2</td>
<td>This protocol has no concept of usernames or passwords.</td>
</tr>

<tr>
<th><code>ALLOWS_PROXY</code></th>
<td>4</td>
<td><a href="http://www.socks.permeo.com/">Socks</a> proxies (or, if <code>ALLOWS_PROXY_HTTP</code> is also set, HTTP proxies) know how to deal with this protocol. If you set this, but you don't set <code>ALLOWS_PROXY_HTTP</code>, your component will need to implement <a href="http://www.xulplanet.com/references/xpcomref/nsIProxiedProtocolHandler.html">nsIProxiedProtocolHandler</a> as well, which is beyond the scope of this document.</td>
</tr>

<tr>
<th><code>ALLOWS_PROXY_HTTP</code></th>
<td>8</td>
<td>See <code>ALLOWS_PROXY</code>. If you set this, you must set <code>ALLOWS_PROXY</code> too.</td>
</tr>
</table>

If none are relevant, use zero ("<code>URI_STD</code>").</dd>

<dt><code>boolean allowPort(<var>port</var>, <var>scheme</var>)</code></dt>
<dd>The user can request an unusual port by adding <code>:<var>port</var></code> after the hostname in the URL. However, there are certain ports that Mozilla usually won't let the user request for security reasons. This lets you override that and let the user make a request on a potentially unsafe port.</dd>

</dl>

<p><b>The channel in detail:</b> The channel doesn't have to have a contract ID, because it's never requested by name, only supplied by protocol handlers. It should implement <a href="http://www.mozilla.org/projects/embedding/embedapiref/embedapi53.html">nsIChannel</a>, though if you want to do anything particularly funky you may want to descend a new kind of channel (like <a href="http://www.xulplanet.com/references/xpcomref/nsIFTPChannel.html">nsIFTPChannel</a>) with any extra stuff you need.</p>

<p>The methods and attributes you need to implement are the ordinary nsIChannel ones:</p>

<dl>
<dt><code>void asyncOpen(<var>listener</var>, <var>context</var>)</code></dt>
<dd>This should make <var>listener</var> (an <a href="http://www.mozilla.org/projects/embedding/embedapiref/embedapi60.html">nsIStreamListener</a>) the place to send bits of the document as they come in. You should call its <code>onDataAvailable</code> method, passing in the new pieces of data. (<var>context</var> also gets passed in that call, unchanged.)</dd>

<dt><code>nsIInputStream open()</code></dt>
<dd>Don't bother implementing this. It's optional, can't be used in a lot of places, and callers will always use asyncOpen() instead if this isn't present. Instead, just throw <code>NS_ERROR_NOT_IMPLEMENTED</code>.</dd>

<dt><code>long contentLength</code></dt>
<dd>The length of the data that's coming in, if you know, or -1 if you don't.</dd>

<dt><code>ACString contentType</code></dt>
<dd>The MIME type of the data that's coming in.</dd>

<dt><code>ACString contentCharset</code></dt>
<dd>The charset of the data that's coming in, if applicable. (What format is this supposed to be in?)</dd>

<dt><code>nsIURI URI</code></dt>
<dd>The URI used to construct this channel. You can return the one that was passed to the protocol handler's <code>newChannel()</code>.</dd>

<dt><code>nsIChannel owner</code></dt>
<dd>The owner of this channel. Not sure what good this is. Seems to work if you return null.</dd>

<dt><code>nsIChannel notificationCallbacks</code></dt>
<dd>Something to do with progress indicators and so on. Still trying to find out what. Seems to work if you return null.</dd>

<dt><code>nsISupports securityInfo</code></dt>
<dd>Don't know. Can anyone tell me? Works if you return null.</dd>

</dl>

<p style="text-align: right"><a href="http://www.mozdev.org/source/browse/archangel/www/new-protocol.html">History of this page</a></p>

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>