1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/streamconv/test/TestStreamConv.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,259 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsIServiceManager.h" 1.10 +#include "nsIStreamConverterService.h" 1.11 +#include "nsIStreamConverter.h" 1.12 +#include "nsICategoryManager.h" 1.13 +#include "mozilla/Module.h" 1.14 +#include "nsXULAppAPI.h" 1.15 +#include "nsIStringStream.h" 1.16 +#include "nsCOMPtr.h" 1.17 +#include "nsThreadUtils.h" 1.18 +#include "mozilla/Attributes.h" 1.19 +#include "nsMemory.h" 1.20 +#include "nsServiceManagerUtils.h" 1.21 +#include "nsComponentManagerUtils.h" 1.22 +#include "nsIRequest.h" 1.23 +#include "nsNetCID.h" 1.24 + 1.25 +#define ASYNC_TEST // undefine this if you want to test sycnronous conversion. 1.26 + 1.27 +///////////////////////////////// 1.28 +// Event pump setup 1.29 +///////////////////////////////// 1.30 +#ifdef XP_WIN 1.31 +#include <windows.h> 1.32 +#endif 1.33 + 1.34 +static int gKeepRunning = 0; 1.35 +///////////////////////////////// 1.36 +// Event pump END 1.37 +///////////////////////////////// 1.38 + 1.39 + 1.40 +///////////////////////////////// 1.41 +// Test converters include 1.42 +///////////////////////////////// 1.43 +#include "Converters.h" 1.44 + 1.45 +// CID setup 1.46 +static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); 1.47 + 1.48 +//////////////////////////////////////////////////////////////////////// 1.49 +// EndListener - This listener is the final one in the chain. It 1.50 +// receives the fully converted data, although it doesn't do anything with 1.51 +// the data. 1.52 +//////////////////////////////////////////////////////////////////////// 1.53 +class EndListener MOZ_FINAL : public nsIStreamListener { 1.54 +public: 1.55 + // nsISupports declaration 1.56 + NS_DECL_ISUPPORTS 1.57 + 1.58 + EndListener() {} 1.59 + 1.60 + // nsIStreamListener method 1.61 + NS_IMETHOD OnDataAvailable(nsIRequest* request, nsISupports *ctxt, nsIInputStream *inStr, 1.62 + uint64_t sourceOffset, uint32_t count) 1.63 + { 1.64 + nsresult rv; 1.65 + uint32_t read; 1.66 + uint64_t len64; 1.67 + rv = inStr->Available(&len64); 1.68 + if (NS_FAILED(rv)) return rv; 1.69 + uint32_t len = (uint32_t)std::min(len64, (uint64_t)(UINT32_MAX - 1)); 1.70 + 1.71 + char *buffer = (char*)nsMemory::Alloc(len + 1); 1.72 + if (!buffer) return NS_ERROR_OUT_OF_MEMORY; 1.73 + 1.74 + rv = inStr->Read(buffer, len, &read); 1.75 + buffer[len] = '\0'; 1.76 + if (NS_SUCCEEDED(rv)) { 1.77 + printf("CONTEXT %p: Received %u bytes and the following data: \n %s\n\n", 1.78 + static_cast<void*>(ctxt), read, buffer); 1.79 + } 1.80 + nsMemory::Free(buffer); 1.81 + 1.82 + return NS_OK; 1.83 + } 1.84 + 1.85 + // nsIRequestObserver methods 1.86 + NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt) { return NS_OK; } 1.87 + 1.88 + NS_IMETHOD OnStopRequest(nsIRequest* request, nsISupports *ctxt, 1.89 + nsresult aStatus) { return NS_OK; } 1.90 +}; 1.91 + 1.92 +NS_IMPL_ISUPPORTS(EndListener, 1.93 + nsIStreamListener, 1.94 + nsIRequestObserver) 1.95 + 1.96 +//////////////////////////////////////////////////////////////////////// 1.97 +// EndListener END 1.98 +//////////////////////////////////////////////////////////////////////// 1.99 + 1.100 +nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* request) { 1.101 + nsresult rv; 1.102 + 1.103 + nsCOMPtr<nsIStringInputStream> dataStream 1.104 + (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv)); 1.105 + NS_ENSURE_SUCCESS(rv, rv); 1.106 + 1.107 + rv = dataStream->SetData(aData, strlen(aData)); 1.108 + NS_ENSURE_SUCCESS(rv, rv); 1.109 + 1.110 + uint64_t avail = 0; 1.111 + dataStream->Available(&avail); 1.112 + 1.113 + uint64_t offset = 0; 1.114 + while (avail > 0) { 1.115 + uint32_t count = saturated(avail); 1.116 + rv = aListener->OnDataAvailable(request, nullptr, dataStream, 1.117 + offset, count); 1.118 + if (NS_FAILED(rv)) return rv; 1.119 + 1.120 + offset += count; 1.121 + avail -= count; 1.122 + } 1.123 + return NS_OK; 1.124 +} 1.125 +#define SEND_DATA(x) SendData(x, converterListener, request) 1.126 + 1.127 +static const mozilla::Module::CIDEntry kTestCIDs[] = { 1.128 + { &kTestConverterCID, false, nullptr, CreateTestConverter }, 1.129 + { nullptr } 1.130 +}; 1.131 + 1.132 +static const mozilla::Module::ContractIDEntry kTestContracts[] = { 1.133 + { NS_ISTREAMCONVERTER_KEY "?from=a/foo&to=b/foo", &kTestConverterCID }, 1.134 + { NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=c/foo", &kTestConverterCID }, 1.135 + { NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=d/foo", &kTestConverterCID }, 1.136 + { NS_ISTREAMCONVERTER_KEY "?from=c/foo&to=d/foo", &kTestConverterCID }, 1.137 + { NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=e/foo", &kTestConverterCID }, 1.138 + { NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=f/foo", &kTestConverterCID }, 1.139 + { NS_ISTREAMCONVERTER_KEY "?from=t/foo&to=k/foo", &kTestConverterCID }, 1.140 + { nullptr } 1.141 +}; 1.142 + 1.143 +static const mozilla::Module::CategoryEntry kTestCategories[] = { 1.144 + { NS_ISTREAMCONVERTER_KEY, "?from=a/foo&to=b/foo", "x" }, 1.145 + { NS_ISTREAMCONVERTER_KEY, "?from=b/foo&to=c/foo", "x" }, 1.146 + { NS_ISTREAMCONVERTER_KEY, "?from=b/foo&to=d/foo", "x" }, 1.147 + { NS_ISTREAMCONVERTER_KEY, "?from=c/foo&to=d/foo", "x" }, 1.148 + { NS_ISTREAMCONVERTER_KEY, "?from=d/foo&to=e/foo", "x" }, 1.149 + { NS_ISTREAMCONVERTER_KEY, "?from=d/foo&to=f/foo", "x" }, 1.150 + { NS_ISTREAMCONVERTER_KEY, "?from=t/foo&to=k/foo", "x" }, 1.151 + { nullptr } 1.152 +}; 1.153 + 1.154 +static const mozilla::Module kTestModule = { 1.155 + mozilla::Module::kVersion, 1.156 + kTestCIDs, 1.157 + kTestContracts, 1.158 + kTestCategories 1.159 +}; 1.160 + 1.161 +int 1.162 +main(int argc, char* argv[]) 1.163 +{ 1.164 + nsresult rv; 1.165 + { 1.166 + XRE_AddStaticComponent(&kTestModule); 1.167 + 1.168 + nsCOMPtr<nsIServiceManager> servMan; 1.169 + NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); 1.170 + 1.171 + nsCOMPtr<nsIThread> thread = do_GetCurrentThread(); 1.172 + 1.173 + nsCOMPtr<nsICategoryManager> catman = 1.174 + do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); 1.175 + if (NS_FAILED(rv)) return -1; 1.176 + nsCString previous; 1.177 + 1.178 + nsCOMPtr<nsIStreamConverterService> StreamConvService = 1.179 + do_GetService(kStreamConverterServiceCID, &rv); 1.180 + if (NS_FAILED(rv)) return -1; 1.181 + 1.182 + // Define the *from* content type and *to* content-type for conversion. 1.183 + static const char fromStr[] = "a/foo"; 1.184 + static const char toStr[] = "c/foo"; 1.185 + 1.186 +#ifdef ASYNC_TEST 1.187 + // ASYNCHRONOUS conversion 1.188 + 1.189 + // Build up a channel that represents the content we're 1.190 + // starting the transaction with. 1.191 + // 1.192 + // sample multipart mixed content-type string: 1.193 + // "multipart/x-mixed-replacE;boundary=thisrandomstring" 1.194 +#if 0 1.195 + nsCOMPtr<nsIChannel> channel; 1.196 + nsCOMPtr<nsIURI> dummyURI; 1.197 + rv = NS_NewURI(getter_AddRefs(dummyURI), "http://meaningless"); 1.198 + if (NS_FAILED(rv)) return -1; 1.199 + 1.200 + rv = NS_NewInputStreamChannel(getter_AddRefs(channel), 1.201 + dummyURI, 1.202 + nullptr, // inStr 1.203 + "text/plain", // content-type 1.204 + -1); // XXX fix contentLength 1.205 + if (NS_FAILED(rv)) return -1; 1.206 + 1.207 + nsCOMPtr<nsIRequest> request(do_QueryInterface(channel)); 1.208 +#endif 1.209 + 1.210 + nsCOMPtr<nsIRequest> request; 1.211 + 1.212 + // setup a listener to receive the converted data. This guy is the end 1.213 + // listener in the chain, he wants the fully converted (toType) data. 1.214 + // An example of this listener in mozilla would be the DocLoader. 1.215 + nsIStreamListener *dataReceiver = new EndListener(); 1.216 + NS_ADDREF(dataReceiver); 1.217 + 1.218 + // setup a listener to push the data into. This listener sits inbetween the 1.219 + // unconverted data of fromType, and the final listener in the chain (in this case 1.220 + // the dataReceiver. 1.221 + nsIStreamListener *converterListener = nullptr; 1.222 + rv = StreamConvService->AsyncConvertData(fromStr, toStr, 1.223 + dataReceiver, nullptr, &converterListener); 1.224 + if (NS_FAILED(rv)) return -1; 1.225 + NS_RELEASE(dataReceiver); 1.226 + 1.227 + // at this point we have a stream listener to push data to, and the one 1.228 + // that will receive the converted data. Let's mimic On*() calls and get the conversion 1.229 + // going. Typically these On*() calls would be made inside their respective wrappers On*() 1.230 + // methods. 1.231 + rv = converterListener->OnStartRequest(request, nullptr); 1.232 + if (NS_FAILED(rv)) return -1; 1.233 + 1.234 + rv = SEND_DATA("aaa"); 1.235 + if (NS_FAILED(rv)) return -1; 1.236 + 1.237 + rv = SEND_DATA("aaa"); 1.238 + if (NS_FAILED(rv)) return -1; 1.239 + 1.240 + // Finish the request. 1.241 + rv = converterListener->OnStopRequest(request, nullptr, rv); 1.242 + if (NS_FAILED(rv)) return -1; 1.243 + 1.244 + NS_RELEASE(converterListener); 1.245 +#else 1.246 + // SYNCHRONOUS conversion 1.247 + nsCOMPtr<nsIInputStream> convertedData; 1.248 + rv = StreamConvService->Convert(inputData, fromStr, toStr, 1.249 + nullptr, getter_AddRefs(convertedData)); 1.250 + if (NS_FAILED(rv)) return -1; 1.251 +#endif 1.252 + 1.253 + // Enter the message pump to allow the URL load to proceed. 1.254 + while ( gKeepRunning ) { 1.255 + if (!NS_ProcessNextEvent(thread)) 1.256 + break; 1.257 + } 1.258 + } // this scopes the nsCOMPtrs 1.259 + // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM 1.260 + NS_ShutdownXPCOM(nullptr); 1.261 + return 0; 1.262 +}