|
Stream Converter Interface
(nsIStreamConverter)
by Richard H. Pizzarro <rhp@netscape.com>
An general purpose interface needs to be defined to allow the integration of stream converters to the Gecko architecture (in particular, netlib). A prime example of a stream converter is the libmime component that currently resides in the Communicator client. libmime is responsible for conversion of "message/RFC822" streams to various formats (such as HTML for display). Currently, libmime is a statically linked library that exposes a C API for use by libnet, but this should take the form of an XP-COM interface that would allow for external modules to be added, updated, etc. as development proceeds.
Before we get into the details of any API, we should discuss the general call flow of what we are trying to accomplish with this stream converter interface. In our example, we will use the IMAP Protocol handler and the operation will be rendering an MHTML message retrieved from an IMAP server.
- The user clicks on a message listed in the Messenger FE. This message resides on an IMAP server so a URL to retrieve the server will be fired by the FE
- The netlib/IMAP protocol handler starts the process of downloading the message from the IMAP server
- The MIME type for the message is identified to be "message/rfc822". Since the user wishes to display this message in an HTML display window, the protocol handler needs to identify and initialize a stream converter than can convert an "message/rfc822" stream to HTML.
- The IMAP protocol handler would query the Stream Converter Manager which had a table of all the available stream converter factories and the format conversions that they support. (Note: this discovery process and the Stream Converter Manager is not explained in this document).
- The IMAP Protocol Handler would create and instance of the RFC822-HTML converter
- The IMAP Protocol Handler would set the following on the converter:
- Output stream for the RFC822-HTML converter. This is the stream where converted output will be written to after processing by the stream converter.
- The output listener on the RFC822-HTML converter. Some explanation is necessary on why we should set the output listener. Consider the following case:
- Have the converted HTML stream be passed back to the IMAP Protocol handler and from there, it will be fed into the HTML rendering engine
- Have the stream converter directly feed the data into the HTML rendering engine without any processing required by the IMAP protocol handler
- After creating the RFC822-HTML converter, the OnStartBinding() method will be called to notify the stream converter that the data flow is starting
- The RFC822-HTML->OnDataAvailable() method will be called to notify the stream converter of new data available for conversion.
- The RFC822-HTML converter will process the data and write the output to the previously set output stream
- IF the IMAP Protocol handler set the output listener on the converter, the RFC822-HTML converter will be responsible for calling the OnDataAvailable() method on these listeners. If not, the converter will return
- The IMAP Protocol Handler would continue receiving data from the network socket and notifying the stream converter until the end of the stream is reached.
- When the stream is completed (or interrupted) the IMAP Protocol Handler will call the StopBinding() method for the stream converter and the this will complete the operation
feeds RFC822 data to the stream converter |
processes RFC822 data and returns an HTML stream |
displays the HTML stream |
Now that we have an understanding of the general call flow for a stream converter, we should start discussing the XP-COM interface for these modules. First, we will define a general nsIStreamConverter interface that will be subclassed with unique ClassID's for all of the various stream converters. For example, nsIStreamConverter is the general class definition for a stream converter, but nsIRFC822toHTMLStreamConverter which supports the nsIStreamConverter interface would be the specific RFC822 to HTML stream converter. (Note: A registry of converters and the formats they support would need to be set on a machine and managed by the Stream Converter Manager for use at runtime)
With all of this in mind, lets look at a definition of the general class
and a specific RFC822 to HTML stream converter.
|
#ifndef nsIStreamConverter_h_
#define nsIStreamConverter_h_
#include "nsIStreamListener.h"
#include "nsIOutputStream.h"
// {C9CDF8E5-95FA-11d2-8807-00805F5A1FB8}
#define NS_ISTREAM_CONVERTER_IID \
{ 0xc9cdf8e5, 0x95fa, 0x11d2, \
{ 0x88, 0x7, 0x0, 0x80, 0x5f, 0x5a, 0x1f, 0xb8 } };
class nsIStreamConverter : public nsIStreamListener {
public:
//
// This is the output stream where the stream
converter will write processed data after
// conversion.
//
NS_IMETHOD SetOutputStream(nsIOutputStream *outStream)
= 0;
//
// The output listener can be set to allow for
the flexibility of having the stream converter
// directly notify the listener of the output
stream for any processed/converter data. If
// this output listener is not set, the data
will be written into the output stream but it is
// the responsibility of the client of the stream
converter to handle the resulting data.
//
NS_IMETHOD SetOutputListener(nsIStreamListener
*outListner) = 0;
};
#endif /* nsIStreamConverter_h_ */
|
#ifndef nsRFC822toHTMLStreamConverter_h_
#define nsRFC822toHTMLStreamConverter_h_
#include "nsIStreamConverter.h"
//
// A specific stream converter will be specified for each format-in/format-out
// pairing.
//
// {22DB1685-AA68-11d2-8809-00805F5A1FB8}
#define NS_RFC822_HTML_STREAM_CONVERTER_CID \
{ 0x22db1685, 0xaa68, 0x11d2, \
{ 0x88, 0x9, 0x0, 0x80, 0x5f, 0x5a, 0x1f, 0xb8 } };
class nsRFC822toHTMLStreamConverter : public nsIStreamConverter
{
public:
void *tagData;
};
#endif /* nsRFC822toHTMLStreamConverter_h_ */