You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



 
Old - replaced by nsIStreamConverter.idl

Stream Converter Interface
(nsIStreamConverter)
by Richard H. Pizzarro <rhp@netscape.com>

Contents Overview
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.
     
Example Call Flow
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:

    •  
         
        IMAP PROTOCOL HANDLER
        feeds RFC822 data to the stream converter
        RFC822 to HTML STREAM CONVERTER
        processes RFC822 data and returns an HTML stream
        HTML RENDERING ENGINE
        displays the HTML stream 
      In this situation, it would be nice to have the flexibility for both of the following options:
      • 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
      For option #2, we will need the stream converter to notify the output listener via the OnDataAvailable() method. In order to do this, the RFC822-HTML converter will need to know the output listener for processed data.
  • 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

  •  
API
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.
 
 
nsIStreamConverter.h

#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_ */
 
 
nsRFC822toHTMLStreamConverter.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_ */