With parameters in ContractIDs I mean something like this:

"@xyz.com/some-module/foobar;1?param1=small;param2=blue"

where param1 and param2 can take values of some predefined

sets {'small', 'medium', 'big'} and {'red', 'blue'}.

Further, it should be acceptable that a client may _not_ resort

parameters like this:

"@xyz.com/some-module/foobar;1?param2=blue;param1=small"



1. Are there established patterns of design to realize such stuff?

a) .. where there is one implementing class and the ContractID

parameters are used to initialize some member vars of the

implementing class

b) .. where there are multiple implementing classes and the

parameters are used to choose the appropriate implementation


i) .. and the different implementations are manually programmed

implementation classes

ii) .. and the different implementations are compile time

generated via C++ template classes

2. If there are different ways of doing it, what questions should

I ask myself in choosing my way?





I did find no dox for XPCOM regarding this special topic .. consequently
read

through the Mozilla sources. The results of this journey are documented
below,

which got a bit lengthy -- sorry. There are fundamental questions left which

puzzle me.

The only case which is quite clear to me is 1.b.i - where nothing special
happens

at all, in essence.

Any hints would be greatly appreciated.

Tobias



P.S. Regarding 1.b.ii, I did manage to get it going by defining a slightly

extended macro:

#define NS_IMPL_ISUPPORTS1_TEMPL(_template, _class, _interface) \

_template NS_IMPL_ADDREF(_class) \

_template NS_IMPL_RELEASE(_class) \

_template NS_IMPL_QUERY_INTERFACE1(_class, _interface)

Full details can be found below. I did not manage to get this stuff going
with

the nsIClassInfo support, facilitating interface flattening and such.





Note: I'm refering to the sources of Mozilla-0.9.7-RELEASE.





Different CONTRACTIDs - same CLSID - GenericFactory

****************************************************************************
********

Please consider ..

@mozilla.org/uriloader/content-handler;1?type=text/plain

CLSID c2343730-dc2c-11d3-98b3-001083010e9b

@mozilla.org/uriloader/content-handler;1?type=text/xml

CLSID c2343730-dc2c-11d3-98b3-001083010e9b

@mozilla.org/uriloader/content-handler;1?type=image/jpeg

CLSID c2343730-dc2c-11d3-98b3-001083010e9b



I want to understand how the ?type=.. CONTRACTID "parameter"

gets mapped to the right implementation. My naive thinking was, that

the value for this parameter must somehow be provided as an argument

to an constructor of the implementation class behind the single CLSID.



nsBrowserInstance.cpp declares a

class nsBrowserContentHandler : public nsIContentHandler, public
nsICmdLineHandler

(Line 832) with a plain standard constructor:

nsBrowserContentHandler::nsBrowserContentHandler()

{

NS_INIT_ISUPPORTS();

}

On line 1012, a standard macro from nsIGenericFactory.h expands

to a static constructor function, which again calls
nsBrowserContentHandler::nsBrowserContentHandler()

NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserContentHandler)

and the handler components for different types are declared just below

static nsModuleComponentInfo components[] = {

...

{ "Browser Content Handler",

NS_BROWSERCONTENTHANDLER_CID,

NS_CONTENT_HANDLER_CONTRACTID_PREFIX"text/html",

nsBrowserContentHandlerConstructor

},

...

{ "Browser Content Handler",

NS_BROWSERCONTENTHANDLER_CID,

NS_CONTENT_HANDLER_CONTRACTID_PREFIX"text/xml",

nsBrowserContentHandlerConstructor

},

...

{ "Browser Content Handler",

NS_BROWSERCONTENTHANDLER_CID,

NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/jpeg",

nsBrowserContentHandlerConstructor

},

...

};

NS_CONTENT_HANDLER_CONTRACTID_PREFIX is #defined in nsCURLILoader.idl as

#define NS_CONTENT_HANDLER_CONTRACTID_PREFIX NS_CONTENT_HANDLER_CONTRACTID
"?type="

#define NS_CONTENT_HANDLER_CONTRACTID
"@mozilla.org/uriloader/content-handler;1"

Obviously, all handlers are registered with the same CLSID and use

the same constructor, which takes _no_ arguments and essentially does
nothing

(but init ISupports). The only difference seems to be the contract IDs. But
how

get these passed in via nsGenericFactory or the ComponentManager ??

In other words, what puzzles me is how these different contract IDs get

disptached to different content handler implementations??

A minor point is, that obviously this breaks a one-to-one correspondence

between CLSIDs and CONTRACTIDs (if this was ever a goal).

****************************************************************************
********





Different CONTRACTIDs - different CLSIDs - GenericFactory

****************************************************************************
********

This seems to be the case 1.b.i. - essentially nothing magically is
happening here.



Please consider ..

@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-1

CLSID a3254cb0-8e20-11d2-8a98-00600811a836

@mozilla.org/intl/unicode/decoder;1?charset=windows-1252

CLSID 7c657d15-ec5e-11d2-8aac-00600811a836

@mozilla.org/intl/unicode/decoder;1?charset=UTF-8

CLSID 5534ddc0-dd96-11d2-8aac-00600811a836

and ..

@mozilla.org/intl/unicode/decoder;1?charset=windows-1250

CLSID 7c657d14-ec5e-11d2-8aac-00600811a836

@mozilla.org/intl/unicode/decoder;1?charset=us-ascii

CLSID ba6151b9-1dfa-11d3-b3bf-00805f8a6670



The ContractIDs of the former 3 are defined in ..

http://lxr.mozilla.org/seamonkey/source/intl/uconv/src/nsCP1252ToUnicode.h

#define NS_CP1252TOUNICODE_CONTRACTID
"@mozilla.org/intl/unicode/decoder;1?charset=windows-1252"

http://lxr.mozilla.org/seamonkey/source/intl/uconv/src/nsISO88591ToUnicode.h

#define NS_ISO88591TOUNICODE_CONTRACTID
"@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-1"


http://lxr.mozilla.org/seamonkey/source/intl/uconv/src/nsUTF8ToUnicode.h

#define NS_UTF8TOUNICODE_CONTRACTID
"@mozilla.org/intl/unicode/decoder;1?charset=UTF-8"

.. and assembled into a module in ..

http://lxr.mozilla.org/seamonkey/source/intl/uconv/src/nsUConvModule.cpp



94 NS_GENERIC_FACTORY_CONSTRUCTOR(nsISO88591ToUnicode)

95 NS_GENERIC_FACTORY_CONSTRUCTOR(nsCP1252ToUnicode)

96 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacRomanToUnicode)

97 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUTF8ToUnicode)


113 static nsModuleComponentInfo components[] =

114 {

115 {

...

155 {

156 "ISO-8859-1 To Unicode Converter", NS_ISO88591TOUNICODE_CID,

157 NS_ISO88591TOUNICODE_CONTRACTID,

158 nsISO88591ToUnicodeConstructor,

159 nsISO88591ToUnicodeRegSelf, nsISO88591ToUnicodeUnRegSelf

160 },

161 {

162 "windows-1252 To Unicode Converter", NS_CP1252TOUNICODE_CID,

163 NS_CP1252TOUNICODE_CONTRACTID,

164 nsCP1252ToUnicodeConstructor,

165 nsCP1252ToUnicodeRegSelf, nsCP1252ToUnicodeUnRegSelf

166 },

...

173 {

174 "UTF-8 To Unicode Converter", NS_UTF8TOUNICODE_CID,

175 NS_UTF8TOUNICODE_CONTRACTID,

176 nsUTF8ToUnicodeConstructor,

177 nsUTF8ToUnicodeRegSelf, nsUTF8ToUnicodeUnRegSelf

178 },

...





The ContractIDs of the latter 2 are defined on the basis of ..

http://lxr.mozilla.org/seamonkey/source/intl/uconv/public/nsIUnicodeDecoder.
h

#define NS_UNICODEDECODER_CONTRACTID_BASE
"@mozilla.org/intl/unicode/decoder;1?charset="


.. and assembled into a module in ..

http://lxr.mozilla.org/seamonkey/source/intl/uconv/ucvlatin/nsUCvLatinModule
.cpp

309 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAsciiToUnicode);

329 NS_GENERIC_FACTORY_CONSTRUCTOR(nsCP1250ToUnicode);



431 static nsModuleComponentInfo components[] =

432 {

433 {

434 DECODER_NAME_BASE "us-ascii" , NS_ASCIITOUNICODE_CID,

435 NS_UNICODEDECODER_CONTRACTID_BASE "us-ascii",

436 nsAsciiToUnicodeConstructor ,

437 nsAsciiToUnicodeRegSelf , nsAsciiToUnicodeUnRegSelf

438 },

...

553 {

554 DECODER_NAME_BASE "windows-1250" , NS_CP1250TOUNICODE_CID,

555 NS_UNICODEDECODER_CONTRACTID_BASE "windows-1250",

556 nsCP1250ToUnicodeConstructor ,

557 nsCP1250ToUnicodeRegSelf , nsCP1250ToUnicodeUnRegSelf

558 },

****************************************************************************
********





Different CONTRACTIDs - different CLSIDs - GenericFactory - Template Classes

****************************************************************************
********

I defined a sligtly extended variant of NS_IMPL_ISUPPORTS1

http://lxr.mozilla.org/seamonkey/source/xpcom/base/nsISupportsImpl.h#754



#define NS_IMPL_ISUPPORTS1_TEMPL(_template, _class, _interface) \

_template NS_IMPL_ADDREF(_class) \

_template NS_IMPL_RELEASE(_class) \

_template NS_IMPL_QUERY_INTERFACE1(_class, _interface)



This will expand to templated member functions for addref, release and QI.

/**

* NS_IMPL_ISUPPORTS1_TEMPL expands to a simple implementation of nsISupports

* for template classes

*/

NS_IMPL_ISUPPORTS1_TEMPL(template<class VT>, btCSequenceSeries<VT>,
btISequenceSeries)



Now I typedef'ed my template class for all the parameters (that are type
traits)

I support:

template<class VT> class btCSequenceSeries;

typedef btCSequenceSeries<VtBool> btCSequenceSeriesVtBool;

typedef btCSequenceSeries<VtUint8> btCSequenceSeriesVtUint8;

typedef btCSequenceSeries<VtUint16> btCSequenceSeriesVtUint16;

typedef btCSequenceSeries<VtUint32> btCSequenceSeriesVtUint32;

typedef btCSequenceSeries<VtDouble> btCSequenceSeriesVtDouble;



.. and plainly defined different CLSIDs ..

#define BT_SEQUENCE_SERIES_BOOL_CID \

{ 0x83cba871, 0x24c7, 0x46ba, { 0xa3, 0xb9, 0x8f, 0xc3, 0xf9, 0x49, 0x00,
0xd7 } }

#define BT_SEQUENCE_SERIES_UINT8_CID \

{ 0x325dce7b, 0x1a9f, 0x480f, { 0x84, 0xe2, 0x3d, 0x85, 0xec, 0xb5, 0xe5,
0x74 } }

#define BT_SEQUENCE_SERIES_UINT16_CID \

{ 0x31fdd1e0, 0x04b8, 0x4bd3, { 0x88, 0x2f, 0x0b, 0x0e, 0xf0, 0xdd, 0x18,
0x99 } }

#define BT_SEQUENCE_SERIES_UINT32_CID \

{ 0x1884b872, 0x2a01, 0x47fa, { 0x9b, 0x22, 0x7a, 0x1b, 0xfe, 0x29, 0x95,
0x0a } }

#define BT_SEQUENCE_SERIES_DOUBLE_CID \

{ 0x6faa0d74, 0x5d27, 0x47b4, { 0xaf, 0xdb, 0x5b, 0x0b, 0xf6, 0x74, 0xe1,
0xba } }



and CONTRACTIDs for all supported implementations :



#define BT_SEQUENCE_SERIES_BOOL_CONTRACTID \

"@xyz.com/omk/sequence-series;1?vtype=bool"

#define BT_SEQUENCE_SERIES_UINT8_CONTRACTID \

"@xyz.com/omk/sequence-series;1?vtype=uint8"

#define BT_SEQUENCE_SERIES_UINT16_CONTRACTID \

"@xyz.com/omk/sequence-series;1?vtype=uint16"

#define BT_SEQUENCE_SERIES_UINT32_CONTRACTID \

"@xyz.com/omk/sequence-series;1?vtype=uint32"

#define BT_SEQUENCE_SERIES_DOUBLE_CONTRACTID \

"@xyz.com/omk/sequence-series;1?vtype=double"



The module containing these components builds standard factory-ctors:



NS_GENERIC_FACTORY_CONSTRUCTOR(btCSequenceSeriesVtBool)

NS_GENERIC_FACTORY_CONSTRUCTOR(btCSequenceSeriesVtUint8)

NS_GENERIC_FACTORY_CONSTRUCTOR(btCSequenceSeriesVtUint16)

NS_GENERIC_FACTORY_CONSTRUCTOR(btCSequenceSeriesVtUint32)

NS_GENERIC_FACTORY_CONSTRUCTOR(btCSequenceSeriesVtDouble)



.. and registers all components:

static nsModuleComponentInfo components[] =

{

{

"BT Sequence-Series Component",

BT_SEQUENCE_SERIES_BOOL_CID,

BT_SEQUENCE_SERIES_BOOL_CONTRACTID,

btCSequenceSeriesVtBoolConstructor,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

0

},

{

"BT Sequence-Series Component",

BT_SEQUENCE_SERIES_UINT8_CID,

BT_SEQUENCE_SERIES_UINT8_CONTRACTID,

btCSequenceSeriesVtUint8Constructor,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

0

},

...

}



Quiet straightforward. Providing for a templated variant of

NS_IMPL_ISUPPORTS1_CI

is not that straight - I'm still wading throu the preprocessor stuff.



****************************************************************************
*******




Reply via email to