1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
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) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsIServiceManager.h"
39 #include "nsIComponentManager.h"
40 #include "nsIComponentRegistrar.h"
41 #include "nsIStreamConverterService.h"
42 #include "nsIStreamConverter.h"
43 #include "nsICategoryManager.h"
44 #include "nsIFactory.h"
45 #include "nsIStringStream.h"
47 #include "nsNetUtil.h"
48 #include "nsThreadUtils.h"
52 #define ASYNC_TEST // undefine this if you want to test sycnronous conversion.
54 /////////////////////////////////
56 /////////////////////////////////
64 static int gKeepRunning
= 0;
65 /////////////////////////////////
67 /////////////////////////////////
70 /////////////////////////////////
71 // Test converters include
72 /////////////////////////////////
73 #include "Converters.h"
76 static NS_DEFINE_CID(kStreamConverterServiceCID
, NS_STREAMCONVERTERSERVICE_CID
);
78 ////////////////////////////////////////////////////////////////////////
79 // EndListener - This listener is the final one in the chain. It
80 // receives the fully converted data, although it doesn't do anything with
82 ////////////////////////////////////////////////////////////////////////
83 class EndListener
: public nsIStreamListener
{
85 // nsISupports declaration
90 // nsIStreamListener method
91 NS_IMETHOD
OnDataAvailable(nsIRequest
* request
, nsISupports
*ctxt
, nsIInputStream
*inStr
,
92 PRUint32 sourceOffset
, PRUint32 count
)
96 rv
= inStr
->Available(&len
);
97 if (NS_FAILED(rv
)) return rv
;
99 char *buffer
= (char*)nsMemory::Alloc(len
+ 1);
100 if (!buffer
) return NS_ERROR_OUT_OF_MEMORY
;
102 rv
= inStr
->Read(buffer
, len
, &read
);
104 if (NS_SUCCEEDED(rv
)) {
105 printf("CONTEXT %p: Received %u bytes and the following data: \n %s\n\n", ctxt
, read
, buffer
);
107 nsMemory::Free(buffer
);
112 // nsIRequestObserver methods
113 NS_IMETHOD
OnStartRequest(nsIRequest
* request
, nsISupports
*ctxt
) { return NS_OK
; }
115 NS_IMETHOD
OnStopRequest(nsIRequest
* request
, nsISupports
*ctxt
,
116 nsresult aStatus
) { return NS_OK
; }
119 NS_IMPL_ISUPPORTS2(EndListener
,
123 ////////////////////////////////////////////////////////////////////////
125 ////////////////////////////////////////////////////////////////////////
128 nsresult
SendData(const char * aData
, nsIStreamListener
* aListener
, nsIRequest
* request
) {
131 nsCOMPtr
<nsIStringInputStream
> dataStream
132 (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv
));
133 NS_ENSURE_SUCCESS(rv
, rv
);
135 rv
= dataStream
->SetData(aData
, strlen(aData
));
136 NS_ENSURE_SUCCESS(rv
, rv
);
139 dataStream
->Available(&avail
);
141 return aListener
->OnDataAvailable(request
, nsnull
, dataStream
, 0, avail
);
143 #define SEND_DATA(x) SendData(x, converterListener, request)
146 main(int argc
, char* argv
[])
150 nsCOMPtr
<nsIServiceManager
> servMan
;
151 NS_InitXPCOM2(getter_AddRefs(servMan
), nsnull
, nsnull
);
152 nsCOMPtr
<nsIComponentRegistrar
> registrar
= do_QueryInterface(servMan
);
153 NS_ASSERTION(registrar
, "Null nsIComponentRegistrar");
155 registrar
->AutoRegister(nsnull
);
157 nsCOMPtr
<nsIThread
> thread
= do_GetCurrentThread();
159 nsCOMPtr
<nsICategoryManager
> catman
=
160 do_GetService(NS_CATEGORYMANAGER_CONTRACTID
, &rv
);
161 if (NS_FAILED(rv
)) return rv
;
164 ///////////////////////////////////////////
165 // BEGIN - Stream converter registration
166 // All stream converters must register with the ComponentManager
167 ///////////////////////////////////////////
169 // these stream converters are just for testing. running this harness
170 // from the dist/bin dir will also pickup converters registered
171 // in other modules (necko converters for example).
173 PRUint32 converterListSize
= 7;
174 const char *const converterList
[] = {
175 "?from=a/foo&to=b/foo",
176 "?from=b/foo&to=c/foo",
177 "?from=b/foo&to=d/foo",
178 "?from=c/foo&to=d/foo",
179 "?from=d/foo&to=e/foo",
180 "?from=d/foo&to=f/foo",
181 "?from=t/foo&to=k/foo",
184 TestConverterFactory
*convFactory
= new TestConverterFactory(kTestConverterCID
, "TestConverter", NS_ISTREAMCONVERTER_KEY
);
185 nsCOMPtr
<nsIFactory
> convFactSup(do_QueryInterface(convFactory
, &rv
));
186 if (NS_FAILED(rv
)) return rv
;
188 for (PRUint32 count
= 0; count
< converterListSize
; ++count
) {
189 // register the TestConverter with the component manager. One contractid registration
190 // per conversion pair (from - to pair).
191 nsCString
contractID(NS_ISTREAMCONVERTER_KEY
);
192 contractID
.Append(converterList
[count
]);
193 rv
= registrar
->RegisterFactory(kTestConverterCID
,
197 if (NS_FAILED(rv
)) return rv
;
198 rv
= catman
->AddCategoryEntry(NS_ISTREAMCONVERTER_KEY
, converterList
[count
], "x",
199 PR_TRUE
, PR_TRUE
, getter_Copies(previous
));
200 if (NS_FAILED(rv
)) return rv
;
203 nsCOMPtr
<nsIStreamConverterService
> StreamConvService
=
204 do_GetService(kStreamConverterServiceCID
, &rv
);
205 if (NS_FAILED(rv
)) return rv
;
207 // Define the *from* content type and *to* content-type for conversion.
208 static const char fromStr
[] = "a/foo";
209 static const char toStr
[] = "c/foo";
212 // ASYNCHRONOUS conversion
214 // Build up a channel that represents the content we're
215 // starting the transaction with.
217 // sample multipart mixed content-type string:
218 // "multipart/x-mixed-replacE;boundary=thisrandomstring"
220 nsCOMPtr
<nsIChannel
> channel
;
221 nsCOMPtr
<nsIURI
> dummyURI
;
222 rv
= NS_NewURI(getter_AddRefs(dummyURI
), "http://meaningless");
223 if (NS_FAILED(rv
)) return rv
;
225 rv
= NS_NewInputStreamChannel(getter_AddRefs(channel
),
228 "text/plain", // content-type
229 -1); // XXX fix contentLength
230 if (NS_FAILED(rv
)) return rv
;
232 nsCOMPtr
<nsIRequest
> request(do_QueryInterface(channel
));
235 nsCOMPtr
<nsIRequest
> request
;
237 // setup a listener to receive the converted data. This guy is the end
238 // listener in the chain, he wants the fully converted (toType) data.
239 // An example of this listener in mozilla would be the DocLoader.
240 nsIStreamListener
*dataReceiver
= new EndListener();
241 NS_ADDREF(dataReceiver
);
243 // setup a listener to push the data into. This listener sits inbetween the
244 // unconverted data of fromType, and the final listener in the chain (in this case
246 nsIStreamListener
*converterListener
= nsnull
;
247 rv
= StreamConvService
->AsyncConvertData(fromStr
, toStr
,
248 dataReceiver
, nsnull
, &converterListener
);
249 if (NS_FAILED(rv
)) return rv
;
250 NS_RELEASE(dataReceiver
);
252 // at this point we have a stream listener to push data to, and the one
253 // that will receive the converted data. Let's mimic On*() calls and get the conversion
254 // going. Typically these On*() calls would be made inside their respective wrappers On*()
256 rv
= converterListener
->OnStartRequest(request
, nsnull
);
257 if (NS_FAILED(rv
)) return rv
;
259 rv
= SEND_DATA("aaa");
260 if (NS_FAILED(rv
)) return rv
;
262 rv
= SEND_DATA("aaa");
263 if (NS_FAILED(rv
)) return rv
;
265 // Finish the request.
266 rv
= converterListener
->OnStopRequest(request
, nsnull
, rv
);
267 if (NS_FAILED(rv
)) return rv
;
269 NS_RELEASE(converterListener
);
271 // SYNCHRONOUS conversion
272 nsCOMPtr
<nsIInputStream
> convertedData
;
273 rv
= StreamConvService
->Convert(inputData
, fromStr
, toStr
,
274 nsnull
, getter_AddRefs(convertedData
));
275 if (NS_FAILED(rv
)) return rv
;
278 // Enter the message pump to allow the URL load to proceed.
279 while ( gKeepRunning
) {
280 if (!NS_ProcessNextEvent(thread
))
283 } // this scopes the nsCOMPtrs
284 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
285 NS_ShutdownXPCOM(nsnull
);