Import from 1.9a8 tarball
[mozilla-extra.git] / extensions / webservices / proxy / src / wspinfoservice.cpp
blob9c3696810244d58ec717206347327bd38b1dbc95
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * John Bandhauer (jband@netscape.com) (Original author)
24 * Vidur Apparao (vidur@netscape.com)
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsIVariant.h"
41 #include "wspprivate.h"
43 /***************************************************************************/
44 // IIDX is used as a way to hold and share our common set of interface
45 // indexes.
47 class IIDX {
48 public:
49 enum IndexID {
50 IDX_nsISupports,
51 IDX_nsIException,
52 IDX_nsIWebServiceCallContext,
53 IDX_nsIVariant,
54 IDX_nsIDOMElement,
56 IDX_Count // Just a count of the above.
59 PRUint16 Get(IndexID id) const
61 NS_ASSERTION(id < IDX_Count, "bad");
62 return mData[id];
65 PRUint16* GetAddr(IndexID id)
67 NS_ASSERTION(id < IDX_Count, "bad");
68 return &mData[id];
71 private:
72 PRUint16 mData[IDX_Count];
75 /***************************************************************************/
76 // ParamAccumulator helps us build param arrays without knowing the length
77 // ahead of time. We later memcpy out of the array into space allocated using
78 // nsIGenericInterfaceInfoSet::AllocateParamArray.
80 class ParamAccumulator
82 private:
83 enum {
84 MAX_BUILTIN = 8,
85 ALLOCATION_INCREMENT = 16,
86 MAX_TOTAL = 255
87 }; // The typelib format limits us to 255 params.
89 public:
90 PRUint16 GetCount() const
92 return mCount;
94 XPTParamDescriptor* GetArray()
96 return mArray;
98 void Clear()
100 mCount = 0;
103 XPTParamDescriptor* GetNextParam();
105 ParamAccumulator()
106 : mCount(0), mAvailable(MAX_BUILTIN), mArray(mBuiltinSpace)
110 ~ParamAccumulator()
112 if(mArray != mBuiltinSpace)
113 delete [] mArray;
115 private:
116 PRUint16 mCount;
117 PRUint16 mAvailable;
118 XPTParamDescriptor* mArray;
119 XPTParamDescriptor mBuiltinSpace[MAX_BUILTIN];
122 XPTParamDescriptor*
123 ParamAccumulator::GetNextParam()
125 if (mCount == MAX_TOTAL) {
126 NS_WARNING("Too many params!");
127 return nsnull;
129 if (mCount == mAvailable) {
130 PRUint16 newAvailable = mAvailable + ALLOCATION_INCREMENT;
131 XPTParamDescriptor* newArray = new XPTParamDescriptor[newAvailable];
132 if (!newArray) {
133 return nsnull;
136 memcpy(newArray, mArray, newAvailable * sizeof(XPTParamDescriptor));
138 if (mArray != mBuiltinSpace) {
139 // The old array was heap allocated, delete so that we don't
140 // leak it.
141 delete [] mArray;
144 mArray = newArray;
145 mAvailable = newAvailable;
148 XPTParamDescriptor* p = &mArray[mCount++];
149 memset(p, 0, sizeof(XPTParamDescriptor));
150 return p;
153 /***************************************************************************/
154 // NewUniqueID generates a uuid that is intended to be locally unique for the
155 // life of the process. These uuids should not be shared with other processes
156 // or persisted.
158 static nsresult
159 NewUniqueID(nsID *aID)
161 // XXX Hack Alert. This was generated on jband's 'bugsfree' machine and
162 // *ought* not to conflict with any existing guids. We should find a
163 // more foolproof crossplatfor dynmic guidgen scheme.
165 // {00000000-1063-11d6-98A8-00C04FA0D259}
166 static const nsID sBaseGuid =
167 {0x00000000, 0x1063, 0x11d6,
168 {0x98, 0xa8, 0x0, 0xc0, 0x4f, 0xa0, 0xd2, 0x59}};
170 static PRInt32 sSerialNumber = 0;
172 *aID = sBaseGuid;
173 aID->m0 = (PRUint32) PR_AtomicIncrement(&sSerialNumber);
174 return NS_OK;
177 /***************************************************************************/
178 // FindInterfaceByName finds an interface info keyed by interface name. It
179 // searches the super manager and any additional managers
181 static nsresult
182 FindInterfaceByName(const char* aName, nsIInterfaceInfoSuperManager* iism,
183 nsIInterfaceInfoManager **aSet, nsIInterfaceInfo **_retval)
185 NS_ENSURE_ARG_POINTER(aSet);
186 if (NS_SUCCEEDED(iism->GetInfoForName(aName, _retval)) && *_retval) {
187 NS_ADDREF(*aSet = iism);
188 return NS_OK;
191 PRBool yes;
192 nsCOMPtr<nsISimpleEnumerator> list;
194 if (NS_SUCCEEDED(iism->HasAdditionalManagers(&yes)) && yes &&
195 NS_SUCCEEDED(iism->EnumerateAdditionalManagers(getter_AddRefs(list))) &&
196 list) {
197 PRBool more;
198 nsCOMPtr<nsIInterfaceInfoManager> current;
200 while (NS_SUCCEEDED(list->HasMoreElements(&more)) && more &&
201 NS_SUCCEEDED(list->GetNext(getter_AddRefs(current))) && current) {
202 if (NS_SUCCEEDED(current->GetInfoForName(aName, _retval)) &&
203 *_retval) {
204 NS_ADDREF(*aSet = current.get());
205 return NS_OK;
210 return NS_ERROR_NO_INTERFACE;
213 /***************************************************************************/
214 // FindInterfaceByName finds the *index* of an interface info in the given
215 // generic info set keyed by interface name.
217 static nsresult
218 FindInterfaceIndexByName(const char* aName, nsIInterfaceInfoSuperManager* iism,
219 nsIGenericInterfaceInfoSet* aSet, PRUint16* aIndex)
221 nsresult rv = aSet->IndexOfByName(aName, aIndex);
222 if (NS_SUCCEEDED(rv)) {
223 return NS_OK;
226 nsCOMPtr<nsIInterfaceInfo> info;
227 nsCOMPtr<nsIInterfaceInfoManager> unused;
228 rv = FindInterfaceByName(aName, iism, getter_AddRefs(unused), getter_AddRefs(info));
229 if (NS_FAILED(rv)) {
230 return rv;
233 return aSet->AppendExternalInterface(info, aIndex);
236 /***************************************************************************/
237 // AppendStandardInterface is used to 'seed' the generic info set with a
238 // specific interface info that we expect to find in the super manager keyed
239 // by interface id.
241 static nsresult
242 AppendStandardInterface(const nsIID& iid, nsIInterfaceInfoSuperManager* iism,
243 nsIGenericInterfaceInfoSet* set, PRUint16* aIndex)
245 nsresult rv;
246 nsCOMPtr<nsIInterfaceInfo> tempInfo;
248 rv = iism->GetInfoForIID(&iid, getter_AddRefs(tempInfo));
249 if (NS_FAILED(rv)) {
250 return rv;
253 return set->AppendExternalInterface(tempInfo, aIndex);
256 /***************************************************************************/
257 // BuildInterfaceName is used to construct the name of an interface
258 // based on three AStrings.
260 static void
261 BuildInterfaceName(const nsAString& qualifier, const nsAString& name,
262 const nsAString& uri, nsACString& aCIdentifier)
264 WSPFactory::XML2C(qualifier, aCIdentifier);
266 nsCAutoString temp;
267 WSPFactory::XML2C(name, temp);
268 aCIdentifier.Append(temp);
270 WSPFactory::XML2C(uri, temp);
271 aCIdentifier.Append(temp);
274 /***************************************************************************/
275 // Forward declaration...
277 static nsresult
278 AppendMethodsForModelGroup(nsIInterfaceInfoSuperManager* iism,
279 nsIGenericInterfaceInfoSet* aSet,
280 nsISchemaModelGroup* aModelGroup,
281 const IIDX& iidx, XPTParamDescriptor* defaultResult,
282 nsIGenericInterfaceInfo* aInfo,
283 const nsAString& qualifier);
285 // Forward declaration...
286 static nsresult
287 GetParamDescOfType(nsIInterfaceInfoSuperManager* iism,
288 nsIGenericInterfaceInfoSet* aSet,
289 nsISchemaType* aType, const IIDX& iidx,
290 XPTParamDescriptor* defaultResult,
291 const nsAString& qualifier, PRUint32 depth,
292 ParamAccumulator* aParams);
294 /***************************************************************************/
295 // AppendMethodForParticle appends a method to a 'struct' interface
296 // to represent the given nsISchemaParticle. It knows how to flatten
297 // particles that are themselves modelgroups (by recurring into
298 // AppendMethodsForModelGroup). At also knows how to deal with arrays.
300 static nsresult
301 AppendMethodForParticle(nsIInterfaceInfoSuperManager* iism,
302 nsIGenericInterfaceInfoSet* aSet,
303 nsISchemaParticle* aParticle, const IIDX& iidx,
304 XPTParamDescriptor* defaultResult,
305 nsIGenericInterfaceInfo* aInfo,
306 const nsAString& qualifier)
308 nsresult rv;
309 XPTMethodDescriptor methodDesc;
310 XPTParamDescriptor* pparamDesc;
311 PRUint16 ignoredIndex;
312 XPTParamDescriptor* paramArray;
313 ParamAccumulator params;
314 PRUint16 i;
316 // If the particle is itself a modelGroup, then flatten in its methods.
317 nsCOMPtr<nsISchemaModelGroup> modelGroup(do_QueryInterface(aParticle));
318 if (modelGroup) {
319 return AppendMethodsForModelGroup(iism, aSet, modelGroup, iidx,
320 defaultResult, aInfo, qualifier);
322 // else...
324 nsCOMPtr<nsISchemaElement> schemaElement(do_QueryInterface(aParticle));
325 if (!schemaElement) {
326 // XXX we are considering this an error. (e.g is a nsISchemaAnyParticle).
327 // XXX need better error tracking!
328 return NS_ERROR_UNEXPECTED;
331 nsCOMPtr<nsISchemaType> schemaType;
332 schemaElement->GetType(getter_AddRefs(schemaType));
333 if (!schemaType) {
334 // XXX need better error tracking!
335 return NS_ERROR_UNEXPECTED;
338 nsAutoString name;
339 rv = aParticle->GetName(name);
340 if (NS_FAILED(rv)) {
341 return rv;
344 nsCAutoString identifierName;
345 WSPFactory::XML2C(name, identifierName);
347 rv = GetParamDescOfType(iism, aSet, schemaType, iidx, defaultResult,
348 qualifier, 0, &params);
349 if (NS_FAILED(rv)) {
350 return rv;
353 rv = aSet->AllocateParamArray(params.GetCount(), &paramArray);
354 if (NS_FAILED(rv)) {
355 return rv;
358 pparamDesc = params.GetArray();
359 for (i = 0; i < params.GetCount(); pparamDesc++, i++) {
360 // handle AString 'out' passing convensions
361 pparamDesc->flags |=
362 (XPT_TDP_TAG(pparamDesc->type.prefix) == TD_DOMSTRING) ?
363 (XPT_PD_IN | XPT_PD_DIPPER) : XPT_PD_OUT;
365 // handle array size_of/length_of.
366 if (XPT_TDP_TAG(pparamDesc->type.prefix) == TD_ARRAY) {
367 pparamDesc->type.argnum =
368 pparamDesc->type.argnum2 = i - 1;
371 // handle trailing retval.
372 if (i+1 == params.GetCount()) {
373 pparamDesc->flags |= XPT_PD_RETVAL;
377 memcpy(paramArray, params.GetArray(),
378 params.GetCount() * sizeof(XPTParamDescriptor));
380 // XXX conditionally tack on 'Get' for array getter?
381 // XXX Deal with intercaps in that case?
383 methodDesc.flags = params.GetCount() == 1 ? XPT_MD_GETTER : 0;
384 methodDesc.name = const_cast<char*>(identifierName.get());
385 methodDesc.params = paramArray;
386 methodDesc.result = defaultResult;
387 methodDesc.num_args = (PRUint8) params.GetCount();
389 return aInfo->AppendMethod(&methodDesc, &ignoredIndex);
392 /***************************************************************************/
393 // AppendMethodsForModelGroup iterates the group's particles and calls
394 // AppendMethodForParticle for each.
396 static nsresult
397 AppendMethodsForModelGroup(nsIInterfaceInfoSuperManager* iism,
398 nsIGenericInterfaceInfoSet* aSet,
399 nsISchemaModelGroup* aModelGroup,
400 const IIDX& iidx, XPTParamDescriptor* defaultResult,
401 nsIGenericInterfaceInfo* aInfo,
402 const nsAString& qualifier)
404 nsresult rv;
405 PRUint32 particleCount;
406 rv = aModelGroup->GetParticleCount(&particleCount);
407 if (NS_FAILED(rv)) {
408 return rv;
411 for (PRUint32 i = 0; i < particleCount; i++) {
412 nsCOMPtr<nsISchemaParticle> particle;
413 rv = aModelGroup->GetParticle(i, getter_AddRefs(particle));
414 if (NS_FAILED(rv)) {
415 return rv;
418 rv = AppendMethodForParticle(iism, aSet, particle, iidx, defaultResult,
419 aInfo, qualifier);
420 if (NS_FAILED(rv)) {
421 return rv;
424 return NS_OK;
427 /***************************************************************************/
428 // FindOrConstructInterface is used for 'struct' interfaces that represent
429 // compound data. Like the names says, it will find an existing info or
430 // create one. In our world these 'struct' interfaces are discovered by
431 // name: qualifier+typename+typetargetnamespace.
433 static nsresult
434 FindOrConstructInterface(nsIInterfaceInfoSuperManager* iism,
435 nsIGenericInterfaceInfoSet* aSet,
436 nsISchemaComplexType* aComplexType,
437 nsISchemaModelGroup* aModelGroup,
438 const IIDX& iidx, XPTParamDescriptor* defaultResult,
439 const nsAString& qualifier,
440 PRUint16* aTypeIndex)
442 nsresult rv;
443 nsCAutoString qualifiedName;
444 nsAutoString name;
445 nsAutoString ns;
446 nsCOMPtr<nsIGenericInterfaceInfo> newInfo;
447 nsID tempID;
448 PRBool haveUniqueID = PR_FALSE;
450 rv = aComplexType->GetName(name);
451 if (NS_FAILED(rv)) {
452 return rv;
455 if (name.IsEmpty()) {
456 // Fabricate a unique name for anonymous type.
457 // Bug 199555
458 ::NewUniqueID(&tempID);
459 nsXPIDLCString idStr;
460 idStr += tempID.ToString();
461 name.AssignWithConversion(idStr);
462 haveUniqueID = PR_TRUE;
464 else {
465 rv = aComplexType->GetTargetNamespace(ns);
466 if (NS_FAILED(rv)) {
467 return rv;
471 BuildInterfaceName(qualifier, name, ns, qualifiedName);
473 // Does the interface already exist?
475 rv = FindInterfaceIndexByName(qualifiedName.get(), iism, aSet, aTypeIndex);
476 if (NS_SUCCEEDED(rv)) {
477 return NS_OK;
480 // Need to create the interface.
482 if (!haveUniqueID)
483 ::NewUniqueID(&tempID);
484 rv = aSet->CreateAndAppendInterface(qualifiedName.get(), tempID,
485 iidx.Get(IIDX::IDX_nsISupports),
486 XPT_ID_SCRIPTABLE,
487 getter_AddRefs(newInfo),
488 aTypeIndex);
489 if (NS_FAILED(rv)) {
490 return rv;
493 return AppendMethodsForModelGroup(iism, aSet, aModelGroup, iidx,
494 defaultResult, newInfo, qualifier);
497 /***************************************************************************/
498 // GetParamDescOfType fills in a param descriptor for a given schematype.
499 // The descriptor is appended to the ParamAccumulator passed in. In array cases
500 // it may append more than one param. For compound data it may do significant
501 // work (via FindOrConstructInterface). It is used both for populating the
502 // params of the primary interface and of 'struct' interfaces.
503 // Note that the flags that control param passing (such as XPT_PD_IN,
504 // XPT_PD_OUT, XPT_PD_DIPPER, and XPT_PD_RETVAL) are *not* set by this method.
506 static nsresult
507 GetParamDescOfType(nsIInterfaceInfoSuperManager* iism,
508 nsIGenericInterfaceInfoSet* aSet, nsISchemaType* aType,
509 const IIDX& iidx, XPTParamDescriptor* defaultResult,
510 const nsAString& qualifier, PRUint32 depth,
511 ParamAccumulator* aParams)
513 XPTTypeDescriptor* additionalType;
514 PRUint16 typeIndex;
516 nsCOMPtr<nsISchemaSimpleType> simpleType;
517 nsresult rv;
519 XPTParamDescriptor* paramDesc = aParams->GetNextParam();
520 if (!paramDesc) {
521 return NS_ERROR_OUT_OF_MEMORY;
524 nsCOMPtr<nsISchemaComplexType> complexType(do_QueryInterface(aType));
525 if (complexType) {
526 PRUint16 contentModel;
527 rv = complexType->GetContentModel(&contentModel);
528 if (NS_FAILED(rv)) {
529 return rv;
532 PRBool isArray;
533 rv = complexType->GetIsArray(&isArray);
534 if (NS_FAILED(rv)) {
535 return rv;
538 if (isArray) {
539 // Punt by calling this array an nsIVariant.
540 // Fix bug 202485
541 paramDesc->type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
542 paramDesc->type.type.iface = iidx.Get(IIDX::IDX_nsIVariant);
543 return NS_OK;
546 switch(contentModel) {
547 case nsISchemaComplexType::CONTENT_MODEL_SIMPLE:
548 rv = complexType->GetSimpleBaseType(getter_AddRefs(simpleType));
549 if (NS_FAILED(rv)) {
550 return rv;
552 goto do_simple;
553 case nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY:
554 case nsISchemaComplexType::CONTENT_MODEL_MIXED:
555 break;
556 default:
557 NS_ERROR("unexpected contentModel!");
558 case nsISchemaComplexType::CONTENT_MODEL_EMPTY:
559 return NS_ERROR_UNEXPECTED;
562 nsCOMPtr<nsISchemaModelGroup> modelGroup;
563 rv = complexType->GetModelGroup(getter_AddRefs(modelGroup));
564 if (NS_FAILED(rv)) {
565 return rv;
568 PRUint16 compositor;
569 rv = modelGroup->GetCompositor(&compositor);
570 if (NS_FAILED(rv)) {
571 return rv;
574 if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {
575 // CHOICE not supported
576 return NS_ERROR_UNEXPECTED;
579 // XXX I *think* we can safely assume that we've already handled the case
580 // where the type is an array.
582 rv = FindOrConstructInterface(iism, aSet, complexType, modelGroup, iidx,
583 defaultResult, qualifier, &typeIndex);
584 if (NS_FAILED(rv)) {
585 return rv;
588 paramDesc->type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
589 paramDesc->type.type.iface = typeIndex;
590 return NS_OK;
593 // If it is not complex it *must* be simple.
595 simpleType = do_QueryInterface(aType, &rv);
596 do_simple:
597 if (!simpleType) {
598 return rv;
601 // We just ignore the restrictions on restrictionTypes and get at the
602 // underlying simple type.
604 nsCOMPtr<nsISchemaRestrictionType> restrictionType;
605 while (nsnull != (restrictionType = do_QueryInterface(simpleType))) {
606 rv = restrictionType->GetBaseType(getter_AddRefs(simpleType));
607 if (NS_FAILED(rv)) {
608 return rv;
612 nsCOMPtr<nsISchemaBuiltinType> builtinType(do_QueryInterface(simpleType));
613 if (builtinType) {
614 PRUint16 typeID;
615 rv = builtinType->GetBuiltinType(&typeID);
616 if (NS_FAILED(rv)) {
617 return rv;
620 switch(typeID) {
621 case nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE:
622 paramDesc->type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
623 paramDesc->type.type.iface = iidx.Get(IIDX::IDX_nsIVariant);
624 return NS_OK;
625 case nsISchemaBuiltinType::BUILTIN_TYPE_STRING:
626 case nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING:
627 case nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN:
628 paramDesc->type.prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
629 return NS_OK;
630 case nsISchemaBuiltinType::BUILTIN_TYPE_BYTE:
631 paramDesc->type.prefix.flags = TD_INT8;
632 return NS_OK;
633 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE:
634 paramDesc->type.prefix.flags = TD_UINT8;
635 return NS_OK;
636 case nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY:
637 case nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY:
638 // XXX We are treating this as an array of TD_UINT8.
640 rv = aSet->AllocateAdditionalType(&typeIndex, &additionalType);
641 if (NS_FAILED(rv)) {
642 return rv;
645 // Copy the element type into the referenced additional type.
646 additionalType->prefix.flags = TD_UINT8;
648 // Add the leading 'length' param.
649 paramDesc->type.prefix.flags = TD_UINT32;
651 // Alloc another param descriptor to hold the array info.
652 paramDesc = aParams->GetNextParam();
653 if (!paramDesc) {
654 return NS_ERROR_OUT_OF_MEMORY;
657 // Set this *second* param as an array and return.
658 paramDesc->type.prefix.flags = TD_ARRAY | XPT_TDP_POINTER;
659 paramDesc->type.type.additional_type = typeIndex;
660 return NS_OK;
661 case nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER:
662 case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER:
663 // XXX need a longInteger class?
664 paramDesc->type.prefix.flags = TD_UINT64;
665 return NS_OK;
666 case nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER:
667 case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER:
668 case nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER:
669 // XXX need a longInteger class?
670 paramDesc->type.prefix.flags = TD_INT64;
671 return NS_OK;
672 case nsISchemaBuiltinType::BUILTIN_TYPE_INT:
673 paramDesc->type.prefix.flags = TD_INT32;
674 return NS_OK;
675 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT:
676 paramDesc->type.prefix.flags = TD_UINT32;
677 return NS_OK;
678 case nsISchemaBuiltinType::BUILTIN_TYPE_LONG:
679 paramDesc->type.prefix.flags = TD_INT64;
680 return NS_OK;
681 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG:
682 paramDesc->type.prefix.flags = TD_UINT64;
683 return NS_OK;
684 case nsISchemaBuiltinType::BUILTIN_TYPE_SHORT:
685 paramDesc->type.prefix.flags = TD_INT16;
686 return NS_OK;
687 case nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT:
688 paramDesc->type.prefix.flags = TD_UINT16;
689 return NS_OK;
690 case nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL:
691 // XXX need a decimal class?
692 paramDesc->type.prefix.flags = TD_DOUBLE;
693 return NS_OK;
694 case nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT:
695 paramDesc->type.prefix.flags = TD_FLOAT;
696 return NS_OK;
697 case nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE:
698 paramDesc->type.prefix.flags = TD_DOUBLE;
699 return NS_OK;
700 case nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN:
701 paramDesc->type.prefix.flags = TD_BOOL;
702 return NS_OK;
703 case nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME:
704 // XXX date type?
705 case nsISchemaBuiltinType::BUILTIN_TYPE_TIME:
706 case nsISchemaBuiltinType::BUILTIN_TYPE_DURATION:
707 case nsISchemaBuiltinType::BUILTIN_TYPE_DATE:
708 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH:
709 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR:
710 case nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH:
711 case nsISchemaBuiltinType::BUILTIN_TYPE_GDAY:
712 case nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY:
713 paramDesc->type.prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
714 return NS_OK;
716 case nsISchemaBuiltinType::BUILTIN_TYPE_NAME:
717 case nsISchemaBuiltinType::BUILTIN_TYPE_QNAME:
718 case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME:
719 case nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI:
720 case nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE:
721 case nsISchemaBuiltinType::BUILTIN_TYPE_ID:
722 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF:
723 case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS:
724 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY:
725 case nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES:
726 case nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION:
727 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN:
728 case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS:
729 paramDesc->type.prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
730 return NS_OK;
732 default:
733 NS_ERROR("unexpected typeID!");
734 return NS_ERROR_UNEXPECTED;
736 NS_ERROR("missing return");
737 return NS_ERROR_UNEXPECTED;
740 // else...
742 nsCOMPtr<nsISchemaListType> listType(do_QueryInterface(simpleType));
743 if (listType) {
744 paramDesc->type.prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
745 return NS_OK;
748 // else...
750 nsCOMPtr<nsISchemaUnionType> unionType(do_QueryInterface(simpleType));
751 if (unionType) {
752 paramDesc->type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
753 paramDesc->type.type.iface = iidx.Get(IIDX::IDX_nsIVariant);
754 return NS_OK;
757 // else...
759 NS_ERROR("unexpected simple type!");
760 return NS_ERROR_UNEXPECTED;
763 /***************************************************************************/
764 // GetParamDescOfPart is used in building the primary interface. It figures
765 // out if encoding of a given param is even necessary and then finds the
766 // appropriate schema type so that it can call GetParamDescOfType to do the
767 // rest of the work of filliung in a param descriptor.
769 static nsresult
770 GetParamDescOfPart(nsIInterfaceInfoSuperManager* iism,
771 nsIGenericInterfaceInfoSet* aSet, nsIWSDLPart* aPart,
772 const IIDX& iidx, XPTParamDescriptor* defaultResult,
773 const nsAString& qualifier, ParamAccumulator* aParams)
775 nsresult rv;
777 // If the binding is 'literal' then we consider this as DOM element.
778 nsCOMPtr<nsIWSDLBinding> binding;
779 rv = aPart->GetBinding(getter_AddRefs(binding));
780 if (NS_FAILED(rv)) {
781 return rv;
784 nsCOMPtr<nsISOAPPartBinding> soapPartBinding(do_QueryInterface(binding));
785 if (soapPartBinding) {
786 PRUint16 use;
787 rv = soapPartBinding->GetUse(&use);
788 if (NS_FAILED(rv)) {
789 return rv;
792 if (use == nsISOAPPartBinding::USE_LITERAL) {
793 XPTParamDescriptor* paramDesc = aParams->GetNextParam();
794 if (!paramDesc) {
795 return NS_ERROR_OUT_OF_MEMORY;
797 paramDesc->type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
798 paramDesc->type.type.iface = iidx.Get(IIDX::IDX_nsIDOMElement);
799 return NS_OK;
803 nsCOMPtr<nsISchemaComponent> schemaComponent;
804 rv = aPart->GetSchemaComponent(getter_AddRefs(schemaComponent));
805 if (NS_FAILED(rv)) {
806 return rv;
809 nsCOMPtr<nsISchemaType> type;
810 nsCOMPtr<nsISchemaElement> element(do_QueryInterface(schemaComponent));
811 if (element) {
812 rv = element->GetType(getter_AddRefs(type));
814 else {
815 type = do_QueryInterface(schemaComponent, &rv);
818 if (NS_FAILED(rv)) {
819 return rv;
822 return GetParamDescOfType(iism, aSet, type, iidx, defaultResult, qualifier,
823 0, aParams);
826 /***************************************************************************/
827 // AccumulateParamsForMessage iterates the parts of a given message and
828 // accumulates the param descriptors.
830 static nsresult
831 AccumulateParamsForMessage(nsIInterfaceInfoSuperManager* iism,
832 nsIGenericInterfaceInfoSet* aSet,
833 nsIWSDLMessage* aMsg, const IIDX& iidx,
834 XPTParamDescriptor* defaultResult,
835 const nsAString& qualifier,
836 ParamAccumulator* aParams)
838 nsresult rv;
839 PRUint32 partCount;
841 rv = aMsg->GetPartCount(&partCount);
842 if (NS_FAILED(rv)) {
843 return rv;
846 for (PRUint32 i = 0; i < partCount; i++) {
847 nsCOMPtr<nsIWSDLPart> part;
848 rv = aMsg->GetPart(i, getter_AddRefs(part));
849 if (NS_FAILED(rv)) {
850 return rv;
853 // Accumulate paramDescriptors (except some flags). This might include
854 // constructing a nested set of compound types and adding them
855 // to the set.
857 rv = GetParamDescOfPart(iism, aSet, part, iidx, defaultResult, qualifier,
858 aParams);
859 if (NS_FAILED(rv)) {
860 return rv;
863 return NS_OK;
866 /***************************************************************************/
868 NS_IMPL_ISUPPORTS1(nsWSPInterfaceInfoService, nsIWSPInterfaceInfoService)
870 nsWSPInterfaceInfoService::nsWSPInterfaceInfoService()
874 nsWSPInterfaceInfoService::~nsWSPInterfaceInfoService()
876 // empty
879 /***************************************************************************/
880 // InfoForPort takes a nsIWSDLPort, qualifier name, and isAsync flag and
881 // finds or constructs the primary interface info for that port. It also
882 // finds or constructs all the interface infos used in params to its methods.
883 // It returns the interface info and optionally the interface info set -
884 // which allows the caller to gather information on the referenced interfaces.
886 /* nsIInterfaceInfo infoForPort (in nsIWSDLPort aPort, in AString
887 aPortURL, in AString aQualifier, in PRBool aIsAsync, out
888 nsIInterfaceInfoManager aSet); */
889 NS_IMETHODIMP
890 nsWSPInterfaceInfoService::InfoForPort(nsIWSDLPort *aPort,
891 const nsAString & aPortURL,
892 const nsAString & aQualifier,
893 PRBool aIsAsync,
894 nsIInterfaceInfoManager **aSet,
895 nsIInterfaceInfo **_retval)
897 if (!aPort) {
898 // aPort can't be null.
899 return NS_ERROR_NULL_POINTER;
902 nsresult rv;
904 nsCAutoString primaryName;
905 nsCAutoString primaryAsyncName;
906 nsAutoString portName;
908 nsCOMPtr<nsIInterfaceInfoSuperManager> iism =
909 do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
910 if (!iism) {
911 return NS_ERROR_UNEXPECTED;
914 // Build the primary and primaryAsync interface names.
916 rv = aPort->GetName(portName);
917 if (NS_FAILED(rv)) {
918 return rv;
921 BuildInterfaceName(aQualifier, portName, aPortURL, primaryName);
922 primaryAsyncName.Assign(primaryName);
923 primaryAsyncName.Append("Async");
925 // With luck the work has already been done and we can just return the
926 // existing info.
928 if (NS_SUCCEEDED(FindInterfaceByName(aIsAsync ? primaryAsyncName.get() :
929 primaryName.get(),
930 iism, aSet, _retval))) {
931 return NS_OK;
934 // No, we need to build all the stuff...
936 nsCOMPtr<nsIGenericInterfaceInfo> primaryInfo;
937 nsCOMPtr<nsIGenericInterfaceInfo> primaryAsyncInfo;
938 nsCOMPtr<nsIGenericInterfaceInfo> listenerInfo;
940 ParamAccumulator inParams;
941 ParamAccumulator outParams;
943 XPTParamDescriptor* tempParamArray;
944 XPTParamDescriptor* defaultResult;
946 XPTParamDescriptor* primaryParamArray;
947 XPTParamDescriptor* primaryAsyncParamArray;
948 XPTParamDescriptor* listenerParamArray;
950 nsCOMPtr<nsIInterfaceInfo> tempInfo;
951 nsCAutoString tempCString;
952 nsAutoString tempString;
954 IIDX iidx;
955 PRUint16 listenerIndex;
957 XPTMethodDescriptor methodDesc;
958 XPTParamDescriptor paramDesc;
959 XPTParamDescriptor* pparamDesc;
961 // Create a new info set.
963 nsCOMPtr<nsIGenericInterfaceInfoSet> set =
964 do_CreateInstance(NS_GENERIC_INTERFACE_INFO_SET_CONTRACTID, &rv);
965 if (NS_FAILED(rv)) {
966 return rv;
969 // Seed the info set with commonly needed interfaces.
971 rv = AppendStandardInterface(NS_GET_IID(nsISupports), iism, set,
972 iidx.GetAddr(IIDX::IDX_nsISupports));
973 if (NS_FAILED(rv)) {
974 return rv;
977 rv = AppendStandardInterface(NS_GET_IID(nsIException), iism, set,
978 iidx.GetAddr(IIDX::IDX_nsIException));
979 if (NS_FAILED(rv)) {
980 return rv;
983 rv = AppendStandardInterface(NS_GET_IID(nsIWebServiceCallContext), iism, set,
984 iidx.GetAddr(IIDX::IDX_nsIWebServiceCallContext));
985 if (NS_FAILED(rv)) {
986 return rv;
989 rv = AppendStandardInterface(NS_GET_IID(nsIVariant), iism, set,
990 iidx.GetAddr(IIDX::IDX_nsIVariant));
991 if (NS_FAILED(rv)) {
992 return rv;
995 rv = AppendStandardInterface(NS_GET_IID(nsIDOMElement), iism, set,
996 iidx.GetAddr(IIDX::IDX_nsIDOMElement));
997 if (NS_FAILED(rv)) {
998 return rv;
1001 // Create and add the primary interface.
1003 PRUint16 ignoredIndex;
1004 nsID tempID;
1006 ::NewUniqueID(&tempID);
1007 rv = set->CreateAndAppendInterface(primaryName.get(), tempID,
1008 iidx.Get(IIDX::IDX_nsISupports),
1009 XPT_ID_SCRIPTABLE,
1010 getter_AddRefs(primaryInfo),
1011 &ignoredIndex);
1012 if (NS_FAILED(rv)) {
1013 return rv;
1016 // Create and add the primary async interface.
1018 ::NewUniqueID(&tempID);
1019 rv = set->CreateAndAppendInterface(primaryAsyncName.get(), tempID,
1020 iidx.Get(IIDX::IDX_nsISupports),
1021 XPT_ID_SCRIPTABLE,
1022 getter_AddRefs(primaryAsyncInfo),
1023 &ignoredIndex);
1024 if (NS_FAILED(rv)) {
1025 return rv;
1029 // Allocate the param info for the 'nsresult' return type that we reuse.
1031 rv = set->AllocateParamArray(1, &defaultResult);
1032 if (NS_FAILED(rv)) {
1033 return rv;
1036 defaultResult->type.prefix.flags = TD_UINT32;
1037 defaultResult->flags = XPT_PD_OUT;
1039 // Create and add the listener interface.
1041 tempCString = primaryName;
1042 tempCString.Append("Listener");
1043 ::NewUniqueID(&tempID);
1044 rv = set->CreateAndAppendInterface(tempCString.get(), tempID,
1045 iidx.Get(IIDX::IDX_nsISupports),
1046 XPT_ID_SCRIPTABLE,
1047 getter_AddRefs(listenerInfo),
1048 &listenerIndex);
1049 if (NS_FAILED(rv)) {
1050 return rv;
1053 // Add the setListener method to the primaryAsync interface.
1054 // void setListener(in 'OurType'Listener listener);
1056 rv = set->AllocateParamArray(1, &tempParamArray);
1057 if (NS_FAILED(rv)) {
1058 return rv;
1061 tempParamArray[0].type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
1062 tempParamArray[0].type.type.iface = listenerIndex;
1063 tempParamArray[0].flags = XPT_PD_IN;
1064 methodDesc.name = "setListener";
1065 methodDesc.params = tempParamArray;
1066 methodDesc.result = defaultResult;
1067 methodDesc.flags = 0;
1068 methodDesc.num_args = 1;
1070 rv = primaryAsyncInfo->AppendMethod(&methodDesc, &ignoredIndex);
1071 if (NS_FAILED(rv)) {
1072 return rv;
1075 // Add the onError method to the listener interface.
1076 // void onError(in nsIException error, in nsIWebServiceCallContext cx);
1078 rv = set->AllocateParamArray(2, &tempParamArray);
1079 if (NS_FAILED(rv)) {
1080 return rv;
1083 tempParamArray[0].type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
1084 tempParamArray[0].type.type.iface = iidx.Get(IIDX::IDX_nsIException);
1085 tempParamArray[0].flags = XPT_PD_IN;
1087 tempParamArray[1].type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
1088 tempParamArray[1].type.type.iface =
1089 iidx.Get(IIDX::IDX_nsIWebServiceCallContext);
1090 tempParamArray[1].flags = XPT_PD_IN;
1092 methodDesc.name = "onError";
1093 methodDesc.params = tempParamArray;
1094 methodDesc.result = defaultResult;
1095 methodDesc.flags = 0;
1096 methodDesc.num_args = 2;
1098 rv = listenerInfo->AppendMethod(&methodDesc, &ignoredIndex);
1099 if (NS_FAILED(rv)) {
1100 return rv;
1103 // Add the methods.
1105 PRUint32 methodCount;
1106 rv = aPort->GetOperationCount(&methodCount);
1107 if (NS_FAILED(rv)) {
1108 return rv;
1111 PRUint32 i;
1112 for (i = 0; i < methodCount; i++)
1114 nsCOMPtr<nsIWSDLOperation> op;
1115 rv = aPort->GetOperation(i, getter_AddRefs(op));
1116 if (NS_FAILED(rv)) {
1117 return rv;
1120 // Accumulate the input params.
1122 nsCOMPtr<nsIWSDLMessage> msg;
1123 rv = op->GetInput(getter_AddRefs(msg));
1124 if (NS_FAILED(rv)) {
1125 return rv;
1128 inParams.Clear();
1129 rv = AccumulateParamsForMessage(iism, set, msg, iidx, defaultResult,
1130 aQualifier, &inParams);
1131 if (NS_FAILED(rv)) {
1132 return rv;
1135 // Accumulate the output params.
1137 rv = op->GetOutput(getter_AddRefs(msg));
1138 if (NS_FAILED(rv)) {
1139 return rv;
1142 outParams.Clear();
1143 rv = AccumulateParamsForMessage(iism, set, msg, iidx, defaultResult,
1144 aQualifier, &outParams);
1145 if (NS_FAILED(rv)) {
1146 return rv;
1149 // XXX do we need types for the faults?
1150 // XXX ignoring param ordering problem for now.
1152 // Allocate the param arrays. On the other hand
1153 // no need to allocate the param arrays if the
1154 // input type and the output type are null; fixing
1155 // bug 200767
1156 PRUint32 k = 0;
1157 PRUint16 primaryParamCount = inParams.GetCount() + outParams.GetCount();
1158 if (primaryParamCount != 0) {
1159 rv = set->AllocateParamArray(primaryParamCount, &primaryParamArray);
1160 if (NS_FAILED(rv)) {
1161 return rv;
1164 // Set the appropriate 'in' param flags.
1166 // 'input' param cases are easy because they are exactly the same for
1167 // primary and primaryAsync.
1169 pparamDesc = inParams.GetArray();
1171 for (k = 0; k < inParams.GetCount(); pparamDesc++, k++) {
1172 // set direction flag
1173 pparamDesc->flags |= XPT_PD_IN;
1175 // handle array size_of/length_of.
1176 if (XPT_TDP_TAG(pparamDesc->type.prefix) == TD_ARRAY) {
1177 pparamDesc->type.argnum =
1178 pparamDesc->type.argnum2 = k - 1;
1182 // Copy the 'in' param arrays.
1184 memcpy(primaryParamArray, inParams.GetArray(),
1185 inParams.GetCount() * sizeof(XPTParamDescriptor));
1187 // Do 'output' param cases for primary interface.
1189 pparamDesc = outParams.GetArray();
1190 for (k = 0; k < outParams.GetCount(); pparamDesc++, k++) {
1191 // handle AString 'out' passing convensions
1192 pparamDesc->flags |=
1193 (XPT_TDP_TAG(pparamDesc->type.prefix) == TD_DOMSTRING) ?
1194 (XPT_PD_IN | XPT_PD_DIPPER) : XPT_PD_OUT;
1196 // handle array size_of/length_of.
1197 if (XPT_TDP_TAG(pparamDesc->type.prefix) == TD_ARRAY) {
1198 pparamDesc->type.argnum =
1199 pparamDesc->type.argnum2 = inParams.GetCount() + k - 1;
1202 // handle trailing retval.
1203 if (k+1 == outParams.GetCount()) {
1204 pparamDesc->flags |= XPT_PD_RETVAL;
1208 memcpy(primaryParamArray + inParams.GetCount(),
1209 outParams.GetArray(),
1210 outParams.GetCount() * sizeof(XPTParamDescriptor));
1211 // primaryParamArray is done now.
1215 PRUint16 primaryAsyncParamCount = inParams.GetCount() + 1;
1216 rv = set->AllocateParamArray(primaryAsyncParamCount,
1217 &primaryAsyncParamArray);
1218 if (NS_FAILED(rv)) {
1219 return rv;
1222 memcpy(primaryAsyncParamArray, inParams.GetArray(),
1223 inParams.GetCount() * sizeof(XPTParamDescriptor));
1226 // Add the trailing [retval] param for the Async call
1228 paramDesc.type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
1229 paramDesc.type.type.iface = iidx.Get(IIDX::IDX_nsIWebServiceCallContext);
1230 paramDesc.flags = XPT_PD_OUT | XPT_PD_RETVAL;
1231 primaryAsyncParamArray[inParams.GetCount()] = paramDesc;
1232 // primaryAsyncParamArray is done now.
1234 PRUint16 listenerParamCount = 1 + outParams.GetCount();
1235 rv = set->AllocateParamArray(listenerParamCount, &listenerParamArray);
1236 if (NS_FAILED(rv)) {
1237 return rv;
1240 // Do 'output' param cases for listener interface.
1242 pparamDesc = outParams.GetArray();
1243 for (k = 0; k < outParams.GetCount(); pparamDesc++, k++) {
1244 // set direction flag
1245 pparamDesc->flags &= ~(XPT_PD_OUT | XPT_PD_DIPPER | XPT_PD_RETVAL);
1246 pparamDesc->flags |= XPT_PD_IN;
1248 // handle array size_of/length_of.
1249 if (XPT_TDP_TAG(pparamDesc->type.prefix) == TD_ARRAY) {
1250 pparamDesc->type.argnum =
1251 pparamDesc->type.argnum2 = k - 1;
1255 memcpy(listenerParamArray,
1256 outParams.GetArray(),
1257 outParams.GetCount() * sizeof(XPTParamDescriptor));
1259 // Add the trailing 'in nsIWebServiceCallContext cx' param for listener
1261 paramDesc.type.prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
1262 paramDesc.type.type.iface = iidx.Get(IIDX::IDX_nsIWebServiceCallContext);
1263 paramDesc.flags = XPT_PD_IN;
1264 listenerParamArray[listenerParamCount-1] = paramDesc;
1265 // listenerParamArray is done now.
1267 rv = op->GetName(tempString);
1268 if (NS_FAILED(rv)) {
1269 return rv;
1272 // Append the methods...
1274 WSPFactory::XML2C(tempString, tempCString);
1276 methodDesc.name = const_cast<char*>(tempCString.get());
1277 methodDesc.params = primaryParamArray;
1278 methodDesc.result = defaultResult;
1279 methodDesc.flags = 0;
1280 methodDesc.num_args = (PRUint8) primaryParamCount;
1282 rv = primaryInfo->AppendMethod(&methodDesc, &ignoredIndex);
1283 if (NS_FAILED(rv)) {
1284 return rv;
1288 methodDesc.name = const_cast<char*>(tempCString.get());
1289 methodDesc.params = primaryAsyncParamArray;
1290 methodDesc.result = defaultResult;
1291 methodDesc.flags = 0;
1292 methodDesc.num_args = (PRUint8) primaryAsyncParamCount;
1294 rv = primaryAsyncInfo->AppendMethod(&methodDesc, &ignoredIndex);
1295 if (NS_FAILED(rv)) {
1296 return rv;
1300 tempCString.Append("Callback");
1301 methodDesc.name = const_cast<char*>(tempCString.get());
1302 methodDesc.params = listenerParamArray;
1303 methodDesc.result = defaultResult;
1304 methodDesc.flags = 0;
1305 methodDesc.num_args = (PRUint8) listenerParamCount;
1307 rv = listenerInfo->AppendMethod(&methodDesc, &ignoredIndex);
1308 if (NS_FAILED(rv)) {
1309 return rv;
1313 // 'Publish' our new set by adding it to the global additional managers list.
1315 rv = iism->AddAdditionalManager(set);
1316 if (NS_FAILED(rv)) {
1317 return rv;
1320 // Optionally return our new set.
1322 if (aSet) {
1323 NS_ADDREF(*aSet = set);
1326 // Return the appropriate interface info.
1328 if (aIsAsync) {
1329 NS_ADDREF(*_retval = primaryAsyncInfo);
1331 else {
1332 NS_ADDREF(*_retval = primaryInfo);
1335 return NS_OK;