64804. r=dougt. fixing long broken stream converter chaining.

This commit is contained in:
valeski%netscape.com 2001-03-08 00:41:53 +00:00
parent c01e2e45a9
commit 44570a6c2d
6 changed files with 366 additions and 432 deletions

View File

@ -174,12 +174,120 @@ UnregisterBasicAuth(nsIComponentManager *aCompMgr, nsIFile *aPath,
#include "nsUnknownDecoder.h"
#include "nsTXTToHTMLConv.h"
#include "nsIndexedToHTML.h"
nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
nsresult NS_NewMultiMixedConv (nsMultiMixedConv** result);
nsresult MOZ_NewTXTToHTMLConv (mozTXTToHTMLConv** result);
nsresult NS_NewHTTPChunkConv (nsHTTPChunkConv ** result);
nsresult NS_NewHTTPCompressConv (nsHTTPCompressConv ** result);
nsresult NS_NewNSTXTToHTMLConv(nsTXTToHTMLConv** result);
nsresult NS_NewStreamConv(nsStreamConverterService **aStreamConv);
#define FTP_UNIX_TO_INDEX "?from=text/ftp-dir-unix&to=application/http-index-format"
#define FTP_NT_TO_INDEX "?from=text/ftp-dir-nt&to=application/http-index-format"
#define INDEX_TO_HTML "?from=application/http-index-format&to=text/html"
#define MULTI_MIXED_X "?from=multipart/x-mixed-replace&to=*/*"
#define MULTI_MIXED "?from=multipart/mixed&to=*/*"
#define UNKNOWN_CONTENT "?from=application/x-unknown-content-type&to=*/*"
#define CHUNKED_TO_UNCHUNKED "?from=chunked&to=unchunked"
#define UNCHUNKED_TO_CHUNKED "?from=unchunked&to=chunked"
#define GZIP_TO_UNCOMPRESSED "?from=gzip&to=uncompressed"
#define XGZIP_TO_UNCOMPRESSED "?from=x-gzip&to=uncompressed"
#define COMPRESS_TO_UNCOMPRESSED "?from=compress&to=uncompressed"
#define XCOMPRESS_TO_UNCOMPRESSED "?from=x-compress&to=uncompressed"
#define DEFLATE_TO_UNCOMPRESSED "?from=deflate&to=uncompressed"
#define PLAIN_TO_HTML "?from=text/plain&to=text/html"
static PRUint32 g_StreamConverterCount = 14;
static char *g_StreamConverterArray[] = {
FTP_UNIX_TO_INDEX,
FTP_NT_TO_INDEX,
INDEX_TO_HTML,
MULTI_MIXED_X,
MULTI_MIXED,
UNKNOWN_CONTENT,
CHUNKED_TO_UNCHUNKED,
UNCHUNKED_TO_CHUNKED,
GZIP_TO_UNCOMPRESSED,
XGZIP_TO_UNCOMPRESSED,
COMPRESS_TO_UNCOMPRESSED,
XCOMPRESS_TO_UNCOMPRESSED,
DEFLATE_TO_UNCOMPRESSED,
PLAIN_TO_HTML
};
// each stream converter must add its from/to key to the category manager
// in RegisterStreamConverters(). This provides a string representation
// of each registered converter, rooted in the NS_ISTREAMCONVERTER_KEY
// category. These keys are then (when the stream converter service
// needs to chain converters together) enumerated and parsed to build
// a graph of converters for potential chaining.
static NS_METHOD
RegisterStreamConverters(nsIComponentManager *aCompMgr, nsIFile *aPath,
const char *registryLocation, const char *componentType) {
nsresult rv;
nsCOMPtr<nsICategoryManager> catmgr =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString previous;
PRUint32 count = 0;
while (count < g_StreamConverterCount) {
(void) catmgr->AddCategoryEntry(NS_ISTREAMCONVERTER_KEY, g_StreamConverterArray[count],
"", PR_TRUE, PR_TRUE, getter_Copies(previous));
if (NS_FAILED(rv)) NS_ASSERTION(0, "adding a cat entry failed");
count++;
}
return rv;
}
// same as RegisterStreamConverters except the reverse.
static NS_METHOD
UnregisterStreamConverters(nsIComponentManager *aCompMgr, nsIFile *aPath,
const char *registryLocation) {
nsresult rv;
nsCOMPtr<nsICategoryManager> catmgr =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString entry;
PRUint32 count = 0;
while (count < g_StreamConverterCount) {
rv = catmgr->DeleteCategoryEntry(NS_ISTREAMCONVERTER_KEY, g_StreamConverterArray[count],
PR_TRUE, getter_Copies(entry));
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(entry, "deleting an entry that doesn't exist");
count++;
}
return rv;
}
static NS_IMETHODIMP
CreateNewStreamConvServiceFactory(nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
if (!aResult) {
return NS_ERROR_INVALID_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
nsStreamConverterService* inst = nsnull;
nsresult rv = NS_NewStreamConv(&inst);
if (NS_FAILED(rv)) {
*aResult = nsnull;
return rv;
}
rv = inst->QueryInterface(aIID, aResult);
if (NS_FAILED(rv)) {
*aResult = nsnull;
}
NS_RELEASE(inst); /* get rid of extra refcnt */
return rv;
}
static NS_IMETHODIMP
CreateNewFTPDirListingConv(nsISupports* aOuter, REFNSIID aIID, void **aResult)
@ -498,90 +606,98 @@ static nsModuleComponentInfo gNetModuleInfo[] = {
nsProtocolProxyService::Create },
// from netwerk/streamconv:
// this converter is "always" part of a build.
// HACK-ALERT, register *all* converters
// in this converters component manager
// registration. just piggy backing here until
// you can add registration functions to
// the generic module macro.
{ "Stream Converter Service",
NS_STREAMCONVERTERSERVICE_CID,
"@mozilla.org/streamConverters;1",
nsStreamConverterService::Create },
CreateNewStreamConvServiceFactory,
RegisterStreamConverters, // registers *all* converters
UnregisterStreamConverters // unregisters *all* converters
},
// from netwerk/streamconv/converters:
{ "FTPDirListingConverter",
NS_FTPDIRLISTINGCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=text/ftp-dir-unix&to=application/http-index-format",
NS_FTPDIRLISTINGCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY FTP_UNIX_TO_INDEX,
CreateNewFTPDirListingConv
},
{ "FTPDirListingConverter",
NS_FTPDIRLISTINGCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=text/ftp-dir-nt&to=application/http-index-format",
NS_ISTREAMCONVERTER_KEY FTP_NT_TO_INDEX,
CreateNewFTPDirListingConv
},
{ "Indexed to HTML Converter",
NS_NSINDEXEDTOHTMLCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=application/http-index-format&to=text/html",
NS_ISTREAMCONVERTER_KEY INDEX_TO_HTML,
nsIndexedToHTML::Create
},
{ "MultiMixedConverter",
NS_MULTIMIXEDCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=multipart/x-mixed-replace&to=*/*",
NS_ISTREAMCONVERTER_KEY MULTI_MIXED_X,
CreateNewMultiMixedConvFactory
},
// There are servers that hand back "multipart/mixed" to
// indicate they want x-mixed-replace behavior.
{ "MultiMixedConverter2",
NS_MULTIMIXEDCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=multipart/mixed&to=*/*",
NS_ISTREAMCONVERTER_KEY MULTI_MIXED,
CreateNewMultiMixedConvFactory
},
{ "Unknown Content-Type Decoder",
NS_UNKNOWNDECODER_CID,
NS_ISTREAMCONVERTER_KEY "?from=application/x-unknown-content-type&to=*/*",
NS_ISTREAMCONVERTER_KEY UNKNOWN_CONTENT,
CreateNewUnknownDecoderFactory
},
{ "HttpChunkConverter",
NS_HTTPCHUNKCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=chunked&to=unchunked",
NS_ISTREAMCONVERTER_KEY CHUNKED_TO_UNCHUNKED,
CreateNewHTTPChunkConvFactory
},
{ "HttpChunkConverter",
NS_HTTPCHUNKCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=unchunked&to=chunked",
NS_ISTREAMCONVERTER_KEY UNCHUNKED_TO_CHUNKED,
CreateNewHTTPChunkConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=gzip&to=uncompressed",
NS_ISTREAMCONVERTER_KEY GZIP_TO_UNCOMPRESSED,
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=x-gzip&to=uncompressed",
NS_ISTREAMCONVERTER_KEY XGZIP_TO_UNCOMPRESSED,
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=compress&to=uncompressed",
NS_ISTREAMCONVERTER_KEY COMPRESS_TO_UNCOMPRESSED,
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=x-compress&to=uncompressed",
NS_ISTREAMCONVERTER_KEY XCOMPRESS_TO_UNCOMPRESSED,
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=deflate&to=uncompressed",
NS_ISTREAMCONVERTER_KEY DEFLATE_TO_UNCOMPRESSED,
CreateNewHTTPCompressConvFactory
},
{ "NSTXTToHTMLConverter",
NS_NSTXTTOHTMLCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=text/plain&to=text/html",
NS_ISTREAMCONVERTER_KEY PLAIN_TO_HTML,
CreateNewNSTXTToHTMLConvFactory
},
// This is not a real stream converter, it's just

View File

@ -39,12 +39,12 @@
#include "nsString2.h"
#include "nsIAtom.h"
#include "nsDeque.h"
#include "nsIRegistry.h"
#include "nsIEnumerator.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIStreamConverter.h"
#include "nsCOMPtr.h"
#include "nsICategoryManager.h"
#include "nsISupportsPrimitives.h"
#include "nsXPIDLString.h"
////////////////////////////////////////////////////////////
// nsISupports methods
@ -64,18 +64,9 @@ nsStreamConverterService::nsStreamConverterService() {
// Delete all the entries in the adjacency list
static PRBool PR_CALLBACK DeleteAdjacencyEntry(nsHashKey *aKey, void *aData, void* closure) {
SCTableData *entry = (SCTableData*)aData;
NS_ASSERTION(entry->key && entry->keyString && entry->data, "malformed adjacency list entry");
NS_ASSERTION(entry->key && entry->data.edges, "malformed adjacency list entry");
delete entry->key;
delete entry->keyString;
// clear out the edges
nsVoidArray *edges = (nsVoidArray*)entry->data;
nsIAtom *vertex;
while ( (vertex = (nsIAtom*)edges->ElementAt(0)) ) {
NS_RELEASE(vertex);
edges->RemoveElementAt(0);
}
delete (nsVoidArray *)entry->data;
NS_RELEASE(entry->data.edges);
delete entry;
return PR_TRUE;
};
@ -94,10 +85,10 @@ nsStreamConverterService::Init() {
}
// Builds the graph represented as an adjacency list (and built up in
// memory using an nsHashtable and nsVoidArray combination).
// memory using an nsHashtable and nsISupportsArray combination).
//
// :BuildGraph() consults the registry for all stream converter CONTRACTIDS then fills the
// adjacency list with edges.
// :BuildGraph() consults the category manager for all stream converter
// CONTRACTIDS then fills the adjacency list with edges.
// An edge in this case is comprised of a FROM and TO MIME type combination.
//
// CONTRACTID format:
@ -111,59 +102,35 @@ nsresult
nsStreamConverterService::BuildGraph() {
nsresult rv;
// enumerate the registry subkeys
nsIRegistry *registry = nsnull;
nsRegistryKey key;
nsIEnumerator *components = nsnull;
rv = nsServiceManager::GetService(NS_REGISTRY_CONTRACTID,
NS_GET_IID(nsIRegistry),
(nsISupports**)&registry);
nsCOMPtr<nsICategoryManager> catmgr(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
if (NS_FAILED(rv)) return rv;
rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry);
nsCOMPtr<nsISimpleEnumerator> entries;
rv = catmgr->EnumerateCategory(NS_ISTREAMCONVERTER_KEY, getter_AddRefs(entries));
if (NS_FAILED(rv)) return rv;
rv = registry->GetSubtree(nsIRegistry::Common,
NS_ISTREAMCONVERTER_KEY,
&key);
if (NS_FAILED(rv)) return rv;
// go through each entry to build the graph
nsCOMPtr<nsISupportsString> entry;
rv = entries->GetNext(getter_AddRefs(entry));
while (NS_SUCCEEDED(rv)) {
rv = registry->EnumerateSubtrees(key, &components);
if (NS_FAILED(rv)) return rv;
// go ahead and enumerate through.
rv = components->First();
while (NS_SUCCEEDED(rv) && (NS_OK != components->IsDone())) {
nsISupports *base = nsnull;
rv = components->CurrentItem(&base);
// get the entry string
nsXPIDLCString entryString;
rv = entry->GetData(getter_Copies(entryString));
if (NS_FAILED(rv)) return rv;
nsIRegistryNode *node = nsnull;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
rv = base->QueryInterface(nodeIID, (void**)&node);
if (NS_FAILED(rv)) return rv;
char *name = nsnull;
rv = node->GetNameUTF8(&name);
if (NS_FAILED(rv)) return rv;
nsCString actualContractID(NS_ISTREAMCONVERTER_KEY);
actualContractID.Append(name);
// cobble the entry string w/ the converter key to produce a full contractID.
nsCString contractID(NS_ISTREAMCONVERTER_KEY);
contractID.Append((const char *)entryString);
// now we've got the CONTRACTID, let's parse it up.
rv = AddAdjacency(actualContractID.get());
rv = AddAdjacency(contractID.get());
if (NS_FAILED(rv)) return rv;
// cleanup
nsCRT::free(name);
NS_RELEASE(node);
NS_RELEASE(base);
rv = components->Next();
rv = entries->GetNext(getter_AddRefs(entry));
}
NS_IF_RELEASE( components );
nsServiceManager::ReleaseService( NS_REGISTRY_CONTRACTID, registry );
return NS_OK;
}
@ -184,88 +151,69 @@ nsStreamConverterService::AddAdjacency(const char *aContractID) {
// Each MIME-type is a vertex in the graph, so first lets make sure
// each MIME-type is represented as a key in our hashtable.
PRBool delFrom = PR_TRUE, delTo = PR_TRUE;
nsCStringKey *fromKey = new nsCStringKey(fromStr);
nsCStringKey *fromKey = new nsCStringKey(fromStr.ToNewCString(), -1, nsCStringKey::OWN);
if (!fromKey) return NS_ERROR_OUT_OF_MEMORY;
nsCStringKey *toKey = new nsCStringKey(toStr);
if (!toKey) {
delete fromKey;
return NS_ERROR_OUT_OF_MEMORY;
}
SCTableData *edges = (SCTableData*)mAdjacencyList->Get(fromKey);
if (!edges) {
SCTableData *fromEdges = (SCTableData*)mAdjacencyList->Get(fromKey);
if (!fromEdges) {
// There is no fromStr vertex, create one.
SCTableData *data = new SCTableData;
if (!data) {
delete fromKey;
delete toKey;
return NS_ERROR_OUT_OF_MEMORY;
}
data->key = fromKey;
delFrom = PR_FALSE;
data->keyString = new nsCString(fromStr);
if (!data->keyString) {
nsCOMPtr<nsISupportsArray> edgeArray;
rv = NS_NewISupportsArray(getter_AddRefs(edgeArray));
if (NS_FAILED(rv)) {
delete fromKey;
delete toKey;
delete data;
return NS_ERROR_OUT_OF_MEMORY;
}
data->data = new nsVoidArray();
if (!data->data) {
delete data->keyString;
delete fromKey;
delete toKey;
delete data;
return NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(data->data.edges = edgeArray.get());
mAdjacencyList->Put(fromKey, data);
fromEdges = data;
} else {
delete fromKey;
fromKey = nsnull;
}
edges = (SCTableData*)mAdjacencyList->Get(toKey);
if (!edges) {
nsCStringKey *toKey = new nsCStringKey(toStr.ToNewCString(), -1, nsCStringKey::OWN);
if (!toKey) return NS_ERROR_OUT_OF_MEMORY;
if (!mAdjacencyList->Get(toKey)) {
// There is no toStr vertex, create one.
SCTableData *data = new SCTableData;
if (!data) {
delete fromKey;
delete toKey;
return NS_ERROR_OUT_OF_MEMORY;
}
data->key = toKey;
delTo = PR_FALSE;
data->keyString = new nsCString(toStr);
if (!data->keyString) {
delete fromKey;
nsCOMPtr<nsISupportsArray> edgeArray;
rv = NS_NewISupportsArray(getter_AddRefs(edgeArray));
if (NS_FAILED(rv)) {
delete toKey;
delete data;
return NS_ERROR_OUT_OF_MEMORY;
}
data->data = new nsVoidArray();
if (!data->data) {
delete data->keyString;
delete fromKey;
delete toKey;
delete data;
return NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(data->data.edges = edgeArray.get());
mAdjacencyList->Put(toKey, data);
}
if (delTo)
} else {
delete toKey;
toKey = nsnull;
}
// Now we know the FROM and TO types are represented as keys in the hashtable.
// Let's "connect" the verticies, making an edge.
edges = (SCTableData*)mAdjacencyList->Get(fromKey);
if (delFrom)
delete fromKey;
NS_ASSERTION(edges, "something wrong in adjacency list construction");
const char *toCStr = toStr.get();
nsIAtom *vertex = NS_NewAtom(toCStr);
nsIAtom *vertex = NS_NewAtom(toStr.get());
if (!vertex) return NS_ERROR_OUT_OF_MEMORY;
nsVoidArray *adjacencyList = (nsVoidArray*)edges->data;
rv = adjacencyList->AppendElement(vertex) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
return rv;
NS_ASSERTION(fromEdges, "something wrong in adjacency list construction");
nsCOMPtr<nsISupportsArray> adjacencyList = fromEdges->data.edges;
return adjacencyList->AppendElement(vertex) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
}
nsresult
@ -292,6 +240,8 @@ nsStreamConverterService::ParseFromTo(const char *aContractID, nsCString &aFromR
// Initializes the BFS state table.
static PRBool PR_CALLBACK InitBFSTable(nsHashKey *aKey, void *aData, void* closure) {
NS_ASSERTION((SCTableData*)aData, "no data in the table enumeration");
nsHashtable *BFSTable = (nsHashtable*)closure;
if (!BFSTable) return PR_FALSE;
@ -304,12 +254,8 @@ static PRBool PR_CALLBACK InitBFSTable(nsHashKey *aKey, void *aData, void* closu
SCTableData *data = new SCTableData;
if (!data) return NS_ERROR_OUT_OF_MEMORY;
data->key = aKey->Clone();
SCTableData *origData = (SCTableData*)aData;
NS_ASSERTION(origData, "no data in the table enumeration");
data->keyString = new nsCString(*origData->keyString);
data->data = state;
data->key = (nsCStringKey*)aKey->Clone();
data->data.state = state;
BFSTable->Put(aKey, data);
return PR_TRUE;
@ -319,8 +265,7 @@ static PRBool PR_CALLBACK InitBFSTable(nsHashKey *aKey, void *aData, void* closu
static PRBool PR_CALLBACK DeleteBFSEntry(nsHashKey *aKey, void *aData, void *closure) {
SCTableData *data = (SCTableData*)aData;
delete data->key;
delete data->keyString;
BFSState *state = (BFSState*)data->data;
BFSState *state = data->data.state;
if (state->predecessor) // there might not be a predecessor depending on the graph
delete state->predecessor;
delete state;
@ -341,8 +286,7 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
// walk the graph in search of the appropriate converter.
PRInt32 vertexCount = mAdjacencyList->Count();
if (0 >= vertexCount)
return NS_ERROR_FAILURE;
if (0 >= vertexCount) return NS_ERROR_FAILURE;
// Create a corresponding color table for each vertex in the graph.
nsHashtable lBFSTable;
@ -355,52 +299,52 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
rv = ParseFromTo(aContractID, fromC, toC);
if (NS_FAILED(rv)) return rv;
nsCStringKey *source = new nsCStringKey(fromC);
if (!source) return NS_ERROR_OUT_OF_MEMORY;
nsCStringKey *source = new nsCStringKey(fromC.get());
SCTableData *data = (SCTableData*)lBFSTable.Get(source);
if (!data) return NS_ERROR_FAILURE;
BFSState *state = (BFSState*)data->data;
BFSState *state = data->data.state;
state->color = gray;
state->distance = 0;
nsDeque *grayQ = new nsDeque(0);
nsDeque grayQ(0);
// Now generate the shortest path tree.
grayQ->Push(source);
while (0 < grayQ->GetSize()) {
nsHashKey *currentHead = (nsHashKey*)grayQ->PeekFront();
grayQ.Push(source);
while (0 < grayQ.GetSize()) {
nsHashKey *currentHead = (nsHashKey*)grayQ.PeekFront();
SCTableData *data2 = (SCTableData*)mAdjacencyList->Get(currentHead);
if (!data2) return NS_ERROR_FAILURE;
nsVoidArray *edges = (nsVoidArray*)data2->data;
nsCOMPtr<nsISupportsArray> edges = data2->data.edges;
NS_ASSERTION(edges, "something went wrong with BFS strmconv algorithm");
// Get the state of the current head to calculate the distance of each
// reachable vertex in the loop.
data2 = (SCTableData*)lBFSTable.Get(currentHead);
BFSState *headVertexState = (BFSState*)data2->data;
BFSState *headVertexState = data2->data.state;
NS_ASSERTION(headVertexState, "problem with the BFS strmconv algorithm");
PRInt32 edgeCount = edges->Count();
for (int i = 0; i < edgeCount; i++) {
PRUint32 edgeCount = 0;
rv = edges->Count(&edgeCount);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < edgeCount; i++) {
nsIAtom *curVertexAtom = (nsIAtom*)edges->ElementAt(i);
nsString2 curVertexStr;
nsStr::Initialize(curVertexStr, eOneByte);
nsAutoString curVertexStr;
curVertexAtom->ToString(curVertexStr);
char * curVertexCString = curVertexStr.ToNewCString();
nsCStringKey *curVertex = new nsCStringKey(curVertexCString);
nsMemory::Free(curVertexCString);
nsCStringKey *curVertex = new nsCStringKey(curVertexStr.ToNewCString(),
curVertexStr.Length(), nsCStringKey::OWN);
SCTableData *data3 = (SCTableData*)lBFSTable.Get(curVertex);
BFSState *curVertexState = (BFSState*)data3->data;
BFSState *curVertexState = data3->data.state;
NS_ASSERTION(curVertexState, "something went wrong with the BFS strmconv algorithm");
if (white == curVertexState->color) {
curVertexState->color = gray;
curVertexState->distance = headVertexState->distance + 1;
curVertexState->predecessor = currentHead->Clone();
grayQ->Push(curVertex);
grayQ.Push(curVertex);
} else {
delete curVertex; // if this vertex has already been discovered, we don't want
// to leak it. (non-discovered vertex's get cleaned up when
@ -408,11 +352,10 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
}
}
headVertexState->color = black;
nsCStringKey *cur = (nsCStringKey*)grayQ->PopFront();
nsCStringKey *cur = (nsCStringKey*)grayQ.PopFront();
delete cur;
cur = nsnull;
}
delete grayQ;
// The shortest path (if any) has been generated and is represetned by the chain of
// BFSState->predecessor keys. Start at the bottom and work our way up.
@ -425,10 +368,8 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
// get the root CONTRACTID
nsCString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
nsCStringArray *shortestPath = new nsCStringArray();
//nsVoidArray *shortestPath = new nsVoidArray();
nsCStringKey *toMIMEType = new nsCStringKey(toStr);
data = (SCTableData*)lBFSTable.Get(toMIMEType);
delete toMIMEType;
nsCStringKey toMIMEType(toStr);
data = (SCTableData*)lBFSTable.Get(&toMIMEType);
if (!data) {
// If this vertex isn't in the BFSTable, then no-one has registered for it,
@ -438,9 +379,11 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
}
while (data) {
BFSState *curState = (BFSState*)data->data;
BFSState *curState = data->data.state;
if (data->keyString->Equals(fromStr)) {
nsCStringKey *key = (nsCStringKey*)data->key;
if (fromStr.Equals(key->GetString())) {
// found it. We're done here.
*aEdgeList = shortestPath;
lBFSTable.Reset(DeleteBFSEntry, nsnull);
@ -453,16 +396,17 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
if (!predecessorData) break; // no predecessor, chain doesn't exist.
// build out the CONTRACTID.
nsCString *newContractID = new nsCString(ContractIDPrefix);
newContractID->Append("?from=");
nsCString newContractID(ContractIDPrefix);
newContractID.Append("?from=");
newContractID->Append(*predecessorData->keyString);
nsCStringKey *predecessorKey = (nsCStringKey*)predecessorData->key;
newContractID.Append(predecessorKey->GetString());
newContractID->Append("&to=");
newContractID->Append(*data->keyString);
newContractID.Append("&to=");
newContractID.Append(key->GetString());
// Add this CONTRACTID to the chain.
rv = shortestPath->AppendCString(*newContractID) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
rv = shortestPath->AppendCString(newContractID) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
NS_ASSERTION(NS_SUCCEEDED(rv), "AppendElement failed");
// move up the tree.
@ -500,10 +444,7 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
rv = NS_GetGlobalComponentManager(&comMgr);
if (NS_FAILED(rv)) return rv;
nsISupports *converter = nsnull;
rv = comMgr->CreateInstanceByContractID(cContractID, nsnull,
NS_GET_IID(nsIStreamConverter),
(void**)&converter);
nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(cContractID, &rv));
if (NS_FAILED(rv)) {
// couldn't go direct, let's try walking the graph of converters.
rv = BuildGraph();
@ -524,9 +465,8 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
// convert the stream using each edge of the graph as a step.
// this is our stream conversion traversal.
nsIInputStream *dataToConvert = aFromStream;
nsIInputStream *convertedData = nsnull;
NS_ADDREF(dataToConvert);
nsCOMPtr<nsIInputStream> dataToConvert = aFromStream;
nsCOMPtr<nsIInputStream> convertedData;
for (PRInt32 i = edgeCount-1; i >= 0; i--) {
nsCString *contractIDStr = converterChain->CStringAt(i);
@ -536,9 +476,7 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
}
const char *lContractID = contractIDStr->get();
rv = comMgr->CreateInstanceByContractID(lContractID, nsnull,
NS_GET_IID(nsIStreamConverter),
(void**)&converter);
converter = do_CreateInstance(lContractID, &rv);
if (NS_FAILED(rv)) {
delete converterChain;
@ -552,21 +490,20 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
return rv;
}
nsIStreamConverter *conv = nsnull;
rv = converter->QueryInterface(NS_GET_IID(nsIStreamConverter), (void**)&conv);
NS_RELEASE(converter);
if (NS_FAILED(rv)) {
delete converterChain;
return rv;
}
PRUnichar *fromUni = fromStr.ToNewUnicode();
if (!fromUni) {
delete converterChain;
return NS_ERROR_OUT_OF_MEMORY;
}
PRUnichar *toUni = toStr.ToNewUnicode();
rv = conv->Convert(dataToConvert, fromUni, toUni, aContext, &convertedData);
if (!toUni) {
delete fromUni;
delete converterChain;
return NS_ERROR_OUT_OF_MEMORY;
}
rv = converter->Convert(dataToConvert, fromUni, toUni, aContext, getter_AddRefs(convertedData));
nsMemory::Free(fromUni);
nsMemory::Free(toUni);
NS_RELEASE(conv);
NS_RELEASE(dataToConvert);
dataToConvert = convertedData;
if (NS_FAILED(rv)) {
delete converterChain;
@ -576,15 +513,11 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
delete converterChain;
*_retval = convertedData;
NS_ADDREF(*_retval);
} else {
// we're going direct.
nsIStreamConverter *conv = nsnull;
rv = converter->QueryInterface(NS_GET_IID(nsIStreamConverter), (void**)&conv);
NS_RELEASE(converter);
if (NS_FAILED(rv)) return rv;
rv = conv->Convert(aFromStream, aFromType, aToType, aContext, _retval);
NS_RELEASE(conv);
rv = converter->Convert(aFromStream, aFromType, aToType, aContext, _retval);
}
return rv;
@ -614,10 +547,7 @@ nsStreamConverterService::AsyncConvertData(const PRUnichar *aFromType,
rv = NS_GetGlobalComponentManager(&comMgr);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIStreamConverter> listener;
rv = comMgr->CreateInstanceByContractID(cContractID, nsnull,
NS_GET_IID(nsIStreamConverter),
getter_AddRefs(listener));
nsCOMPtr<nsIStreamConverter> listener(do_CreateInstance(cContractID, &rv));
if (NS_FAILED(rv)) {
// couldn't go direct, let's try walking the graph of converters.
rv = BuildGraph();
@ -649,10 +579,7 @@ nsStreamConverterService::AsyncConvertData(const PRUnichar *aFromType,
}
const char *lContractID = contractIDStr->get();
nsCOMPtr<nsIStreamConverter> converter;
rv = comMgr->CreateInstanceByContractID(lContractID, nsnull,
NS_GET_IID(nsIStreamConverter),
getter_AddRefs(converter));
nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(lContractID, &rv));
NS_ASSERTION(NS_SUCCEEDED(rv), "graph construction problem, built a contractid that wasn't registered");
nsCString fromStr, toStr;
@ -663,7 +590,17 @@ nsStreamConverterService::AsyncConvertData(const PRUnichar *aFromType,
}
PRUnichar *fromStrUni = fromStr.ToNewUnicode();
if (!fromStrUni) {
delete converterChain;
return NS_ERROR_OUT_OF_MEMORY;
}
PRUnichar *toStrUni = toStr.ToNewUnicode();
if (!toStrUni) {
delete fromStrUni;
delete converterChain;
return NS_ERROR_OUT_OF_MEMORY;
}
rv = converter->AsyncConvertData(fromStrUni, toStrUni, forwardListener, aContext);
nsMemory::Free(fromStrUni);
@ -695,10 +632,7 @@ nsStreamConverterService::AsyncConvertData(const PRUnichar *aFromType,
*_retval = listener;
NS_ADDREF(*_retval);
nsCOMPtr<nsIStreamConverter> conv(do_QueryInterface(listener, &rv));
if (NS_FAILED(rv)) return rv;
rv = conv->AsyncConvertData(aFromType, aToType, aListener, aContext);
rv = listener->AsyncConvertData(aFromType, aToType, aListener, aContext);
}
return rv;
@ -709,15 +643,11 @@ nsresult
NS_NewStreamConv(nsStreamConverterService** aStreamConv)
{
NS_PRECONDITION(aStreamConv != nsnull, "null ptr");
if (! aStreamConv)
return NS_ERROR_NULL_POINTER;
if (!aStreamConv) return NS_ERROR_NULL_POINTER;
*aStreamConv = new nsStreamConverterService();
if (! *aStreamConv)
return NS_ERROR_OUT_OF_MEMORY;
if (!*aStreamConv) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aStreamConv);
(*aStreamConv)->Init();
return NS_OK;
return (*aStreamConv)->Init();
}

View File

@ -26,6 +26,7 @@
#include "nsIStreamConverterService.h"
#include "nsIStreamListener.h"
#include "nsHashtable.h"
#include "nsISupportsArray.h"
#include "nsVoidArray.h"
class nsStreamConverterService : public nsIStreamConverterService {
@ -47,26 +48,6 @@ public:
// Initialization routine. Must be called after this object is constructed.
nsresult Init();
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
nsresult rv;
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
nsStreamConverterService* _s = new nsStreamConverterService();
if (_s == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(_s);
rv = _s->Init();
if (NS_FAILED(rv)) {
delete _s;
return rv;
}
rv = _s->QueryInterface(aIID, aResult);
NS_RELEASE(_s);
return rv;
}
private:
// Responsible for finding a converter for the given MIME-type.
nsresult FindConverter(const char *aContractID, nsCStringArray **aEdgeList);
@ -81,13 +62,6 @@ private:
///////////////////////////////////////////////////////////////////
// Breadth-First-Search (BFS) algorithm state classes and types.
// adjacency list and BFS hashtable data class.
typedef struct _tableData {
nsHashKey *key;
nsCString *keyString;
void *data;
} SCTableData;
// used to establish discovered vertecies.
enum BFScolors {white, gray, black};
@ -97,4 +71,13 @@ typedef struct _BFSState {
nsHashKey *predecessor;
} BFSState;
// adjacency list and BFS hashtable data class.
typedef struct _tableData {
nsCStringKey *key;
union _data {
BFSState *state;
nsISupportsArray *edges;
} data;
} SCTableData;
#endif // __nsstreamconverterservice__h___

View File

@ -1,5 +1,6 @@
#include "Converters.h"
#include "nsIStringStream.h"
#include "nsCOMPtr.h"
//////////////////////////////////////////////////
// TestConverter
@ -20,7 +21,7 @@ TestConverter::Convert(nsIInputStream *aFromStream,
const PRUnichar *aToType,
nsISupports *ctxt,
nsIInputStream **_retval) {
char buf[1024];
char buf[1024+1];
PRUint32 read;
nsresult rv = aFromStream->Read(buf, 1024, &read);
if (NS_FAILED(rv) || read == 0) return rv;
@ -34,19 +35,18 @@ TestConverter::Convert(nsIInputStream *aFromStream,
for (PRUint32 i = 0; i < read; i++)
buf[i] = toChar;
buf[read] = '\0';
nsString convDataStr;
convDataStr.AssignWithConversion(buf);
nsIInputStream *inputData = nsnull;
nsISupports *inputDataSup = nsnull;
nsCOMPtr<nsISupports> inputDataSup;
rv = NS_NewStringInputStream(&inputDataSup, convDataStr);
rv = NS_NewStringInputStream(getter_AddRefs(inputDataSup), convDataStr);
if (NS_FAILED(rv)) return rv;
rv = inputDataSup->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inputData);
NS_RELEASE(inputDataSup);
nsCOMPtr<nsIInputStream> inputData(do_QueryInterface(inputDataSup));
*_retval = inputData;
if (NS_FAILED(rv)) return rv;
NS_ADDREF(*_retval);
return NS_OK;
}
@ -60,7 +60,6 @@ TestConverter::AsyncConvertData(const PRUnichar *aFromType,
NS_ASSERTION(aListener, "null listener");
mListener = aListener;
NS_ADDREF(mListener);
// based on these types, setup internal state to handle the appropriate conversion.
fromType = aFromType;
@ -78,11 +77,11 @@ TestConverter::OnDataAvailable(nsIRequest* request,
PRUint32 sourceOffset,
PRUint32 count) {
nsresult rv;
nsIInputStream *convertedStream = nsnull;
nsCOMPtr<nsIInputStream> convertedStream;
// just make a syncronous call to the Convert() method.
// Anything can happen here, I just happen to be using the sync call to
// do the actual conversion.
rv = Convert(inStr, fromType.GetUnicode(), toType.GetUnicode(), ctxt, &convertedStream);
rv = Convert(inStr, fromType.GetUnicode(), toType.GetUnicode(), ctxt, getter_AddRefs(convertedStream));
if (NS_FAILED(rv)) return rv;
PRUint32 len;
@ -141,10 +140,6 @@ TestConverterFactory::CreateInstance(nsISupports *aOuter,
TestConverter *conv = new TestConverter();
if (!conv) return NS_ERROR_OUT_OF_MEMORY;
conv->QueryInterface(NS_GET_IID(nsISupports), (void**)&inst);
} else if (mClassID.Equals(kTestConverter1CID)) {
TestConverter1 *conv = new TestConverter1();
if (!conv) return NS_ERROR_OUT_OF_MEMORY;
conv->QueryInterface(NS_GET_IID(nsISupports), (void**)&inst);
}
else {
return NS_ERROR_NO_INTERFACE;

View File

@ -1,6 +1,7 @@
#include "nsIStreamConverter.h"
#include "nsString.h"
#include "nsIFactory.h"
#include "nsCOMPtr.h"
/* This file defines stream converter components, and their accompanying factory class.
* These converters implement the nsIStreamConverter interface and support both
@ -36,26 +37,11 @@ public:
nsIStreamListener *aListener, nsISupports *ctxt);
// member data
nsIStreamListener *mListener;
nsCOMPtr<nsIStreamListener> mListener;
nsString fromType;
nsString toType;
};
//////////////////////////////////////////////////
// TestConverter1
#define NS_TESTCONVERTER1_CID \
{ /* 2BA20BB0-5598-11d3-9E63-0010A4053FD0 */ \
0x2ba20bb0, \
0x5598, \
0x11d3, \
{0x9e, 0x63, 0x00, 0x10, 0xa4, 0x5, 0x3f, 0xd0} \
}
static NS_DEFINE_CID(kTestConverter1CID, NS_TESTCONVERTER1_CID);
// Derrives solely from TestConverter.
class TestConverter1 : public TestConverter {
};
//////////////////////////////////////////////////
// FACTORY
class TestConverterFactory : public nsIFactory

View File

@ -24,18 +24,14 @@
#include "nsIComponentManager.h"
#include "nsIStreamConverterService.h"
#include "nsIStreamConverter.h"
#include "nsIRegistry.h"
#include "nsICategoryManager.h"
#include "nsIFactory.h"
#include "nsIStringStream.h"
#include "nsIIOService.h"
#include "nsCOMPtr.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "nspr.h"
#define ASYNC_TEST // undefine this if you want to test sycnronous conversion.
/////////////////////////////////
@ -65,7 +61,6 @@ static nsIEventQueue* gEventQ = nsnull;
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kRegistryCID, NS_REGISTRY_CID);
////////////////////////////////////////////////////////////////////////
// EndListener - This listener is the final one in the chain. It
@ -102,16 +97,10 @@ public:
}
// nsIStreamObserver methods
NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt)
{
return NS_OK;
}
NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt) { return NS_OK; }
NS_IMETHOD OnStopRequest(nsIRequest* request, nsISupports *ctxt,
nsresult aStatus, const PRUnichar* aStatusArg)
{
return NS_OK;
}
nsresult aStatus, const PRUnichar* aStatusArg) { return NS_OK; }
};
NS_IMPL_ISUPPORTS1(EndListener, nsIStreamListener);
@ -123,15 +112,14 @@ NS_IMPL_ISUPPORTS1(EndListener, nsIStreamListener);
nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* request) {
nsString data;
data.AssignWithConversion(aData);
nsCOMPtr<nsIInputStream> dataStream;
nsCOMPtr<nsISupports> sup;
nsresult rv = NS_NewStringInputStream(getter_AddRefs(sup), data);
if (NS_FAILED(rv)) return rv;
dataStream = do_QueryInterface(sup, &rv);
nsCOMPtr<nsISupports> dataSup;
nsresult rv = NS_NewStringInputStream(getter_AddRefs(dataSup), data);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStream> dataStream(do_QueryInterface(dataSup));
return aListener->OnDataAvailable(request, nsnull, dataStream, 0, -1);
}
#define SEND_DATA(x) SendData(x, converterListener, nsnull)
#define SEND_DATA(x) SendData(x, converterListener, request)
int
main(int argc, char* argv[])
@ -150,194 +138,130 @@ main(int argc, char* argv[])
rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, NULL /* default */);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsICategoryManager> catman =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString previous;
///////////////////////////////////////////
// BEGIN - Stream converter registration
// All stream converters must register with the ComponentManager, _and_ make
// a registry entry.
// All stream converters must register with the ComponentManager
///////////////////////////////////////////
// these stream converters are just for testing. running this harness
// from the dist/bin dir will also pickup converters registered
// in other modules (necko converters for example).
PRUint32 converterListSize = 7;
char *converterList[] = {
"?from=a/foo&to=b/foo",
"?from=b/foo&to=c/foo",
"?from=b/foo&to=d/foo",
"?from=c/foo&to=d/foo",
"?from=d/foo&to=e/foo",
"?from=d/foo&to=f/foo",
"?from=t/foo&to=k/foo",
};
TestConverterFactory *convFactory = new TestConverterFactory(kTestConverterCID, "TestConverter", NS_ISTREAMCONVERTER_KEY);
nsIFactory *convFactSup = nsnull;
rv = convFactory->QueryInterface(NS_GET_IID(nsIFactory), (void**)&convFactSup);
nsCOMPtr<nsIFactory> convFactSup(do_QueryInterface(convFactory, &rv));
if (NS_FAILED(rv)) return rv;
TestConverterFactory *convFactory1 = new TestConverterFactory(kTestConverter1CID, "TestConverter1", NS_ISTREAMCONVERTER_KEY);
nsIFactory *convFactSup1 = nsnull;
rv = convFactory1->QueryInterface(NS_GET_IID(nsIFactory), (void**)&convFactSup1);
if (NS_FAILED(rv)) return rv;
// register the TestConverter with the component manager. One contractid registration
// per conversion pair (from - to pair).
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
NS_ISTREAMCONVERTER_KEY "?from=a/foo&to=b/foo",
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::RegisterFactory(kTestConverter1CID,
"TestConverter1",
NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=c/foo",
convFactSup1,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=d/foo",
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
NS_ISTREAMCONVERTER_KEY "?from=c/foo&to=d/foo",
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=e/foo",
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=f/foo",
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
NS_ISTREAMCONVERTER_KEY "?from=t/foo&to=k/foo",
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
// register the converters with the registry. One contractid registration
// per conversion pair.
NS_WITH_SERVICE(nsIRegistry, registry, kRegistryCID, &rv);
if (NS_FAILED(rv)) return rv;
// open the registry
rv = registry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry);
if (NS_FAILED(rv)) return rv;
// set the key
nsRegistryKey key, key1;
rv = registry->AddSubtree(nsIRegistry::Common, NS_ISTREAMCONVERTER_KEY, &key);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=a/foo&to=b/foo", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=b/foo&to=c/foo", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=multipart/x-mixed-replace&to=text/html", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=b/foo&to=d/foo", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=c/foo&to=d/foo", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=d/foo&to=e/foo", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=d/foo&to=f/foo", &key1);
if (NS_FAILED(rv)) return rv;
rv = registry->AddSubtreeRaw(key, "?from=t/foo&to=k/foo", &key1);
if (NS_FAILED(rv)) return rv;
registry = 0; // close the registry
PRUint32 count = 0;
while (count < converterListSize) {
// register the TestConverter with the component manager. One contractid registration
// per conversion pair (from - to pair).
nsCString contractID(NS_ISTREAMCONVERTER_KEY);
contractID.Append(converterList[count]);
rv = nsComponentManager::RegisterFactory(kTestConverterCID,
"TestConverter",
contractID.get(),
convFactSup,
PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = catman->AddCategoryEntry(NS_ISTREAMCONVERTER_KEY, converterList[count], "x",
PR_TRUE, PR_TRUE, getter_Copies(previous));
if (NS_FAILED(rv)) return rv;
count++;
}
NS_WITH_SERVICE(nsIStreamConverterService, StreamConvService, kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
// Define the *from* content type and *to* content-type for conversion.
nsString fromStr;
fromStr.AssignWithConversion("multipart/x-mixed-replace");
fromStr.AssignWithConversion("a/foo");
nsString toStr;
toStr.AssignWithConversion("text/html");
toStr.AssignWithConversion("c/foo");
#ifdef ASYNC_TEST
// ASYNCRONOUS conversion
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
// Build up a channel that represents the content we're
// starting the transaction with.
//
// sample multipart mixed content-type string:
// "multipart/x-mixed-replacE;boundary=thisrandomstring"
/*nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIURI> dummyURI;
rv = NS_NewURI(getter_AddRefs(dummyURI), "http://meaningless");
if (NS_FAILED(rv)) return rv;
// we need a dummy channel for the async calls.
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIURI> dummyURI;
rv = serv->NewURI("http://neverneverland.com", nsnull, getter_AddRefs(dummyURI));
if (NS_FAILED(rv)) return rv;
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
dummyURI,
nsnull, // inStr
"multipart/x-mixed-replacE;boundary=thisrandomstring",
"text/plain", // content-type
-1); // XXX fix contentLength
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRequest> request(do_QueryInterface(channel));*/
nsCOMPtr<nsIRequest> request;
// setup a listener to receive the converted data. This guy is the end
// listener in the chain, he wants the fully converted (toType) data.
// An example of this listener in mozilla would be the DocLoader.
nsCOMPtr<nsIStreamListener> dataReceiver = new EndListener();
nsIStreamListener *dataReceiver = new EndListener();
NS_ADDREF(dataReceiver);
// setup a listener to push the data into. This listener sits inbetween the
// unconverted data of fromType, and the final listener in the chain (in this case
// the dataReceiver.
nsCOMPtr<nsIStreamListener> converterListener;
rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(), toStr.GetUnicode(), dataReceiver, nsnull, getter_AddRefs(converterListener));
nsIStreamListener *converterListener = nsnull;
rv = StreamConvService->AsyncConvertData(fromStr.GetUnicode(), toStr.GetUnicode(),
dataReceiver, nsnull, &converterListener);
if (NS_FAILED(rv)) return rv;
NS_RELEASE(dataReceiver);
// at this point we have a stream listener to push data to, and the one
// that will receive the converted data. Let's mimic On*() calls and get the conversion
// going. Typically these On*() calls would be made inside their respective wrappers On*()
// methods.
rv = converterListener->OnStartRequest(nsnull, nsnull);
rv = converterListener->OnStartRequest(request, nsnull);
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA("--thisrandomstring\r\nContent-type: text/html\r\n\r\n<p>Please stand by... <p>\r\n");
rv = SEND_DATA("aaa");
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA("\r\n--thisrandomstring\r\nContent-type: text/html\r\n");
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA("Set-Cookie: LASTORDER=bugs.bug_id ; path=/; expires=Sun, 30-Jun-2029 00:00:00 GMT\r\n");
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA("Set-Cookie: BUGLIST=12012:1750:2023:11112:11948:13288:14960:17164:1485:1582:1596:4528:848:1043:2267:3692:9446:12122:3371:1219:1277:1896:4233:1044:1119:1177:1238:1378:1758:2079:2478:3457:5387:12451:17567:845:1036:1039:1040:1041:1045:1047:1048:1049:1050:1051:1052:1053:1055:1057:1058:1059:1060:1120:1122:1184:1206:1237:1274:1275:1276:1278:1279:1281:1300:1360:1580:1595:1605:1606:1759:1770:1781:1787:1807:1808:1812:1820:1834:1851:1863:1864:1985:2006:2007:2010:2011:2012:2013:2014:2015:2018:2019:2022:2025:2032:2033:2035:2037:2038:2044:2052:2056:2058:2059:2062:2064:2072:2109:2261:2285:2353:2354:2436:2441:2442:2452:2479:2501:2502:2525:2592:2765:2771:2842:2844:2867:2868:2925:2926:2942:2947:2948:2949:2950:2951:2952:2987:2990:2992:2993:3000:3027:3089:3116:3143:3152:3153:3160:3195:3221:3222:3240:3366:3454:3458:3460:3474:3486:4445:4515:4519:5849:6052:6403:8905:9740:9777:9778:9779:9781:9850:12272:12401:12906:2031:3088:850:1042:1046:1141:1414:3013:8044:15992:16934:17418:17519:3950:4580:5850:6518:8032:8088:9024:9236:9593:10176:10273:10296:14310:16586:16848:17645:4387:4426:6357:6519:8045:8071:8565:9013:9474:9738:10268:10269:10274:11960:12217:12398:13140:15315:16490:16585:16624:16636:16936:1038:1413:4042:4050:4092:4234:4510:4529:4572:4615:4831:4833:");
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA("4834:5154:5194:5195:5272:5277:5406:5407:5469:5688:5693:5818:5886:6033:6046:6069:6071:6073:6125:6152:6166:6282:6404:6546:6732:6789:6901:6903:7588:7774:7833:7834:7835:8051:8468:8586:8595:8886:8893:8912:8914:9075:9076:9127:9136:9189:9191:9250:9271:9280:9285:9300:9301:9421:9439:9442:9479:9611:9690:9691:9696:9730:9741:9747:9885:9927:10013:10064:10085:10107:10109:10140:10169:10207:10209:10216:10292:10330:10403:10455:10485:10497:10509:10577:10580:10649:10712:10763:10831:11559:11565:11932:11936:12152:12154:12155:12193:12194:12231:12232:12233:12302:12304:12341:12348:12350:12385:12386:12403:12449:12450:12452:12453:12461:12462:12542:12750:12764:12765:12766:12945:12962:12997:12998:13034:13035:13131:13214:13219:13245:13281:12324:14290:13626:14169:14957:14959:14961:15439:15440:15441");
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA(":15459:15649:15891:15904:15909:15931:15932:16200:16252:16256:16258:15945:16362:16377:16548:16555:16569:16584:16590:16591:16603:16605:16606:16609:16610:16625:16640:16651:16808:16813:16852:16876:16879:16881:16882:16888:16938:17010:17159:17161:17517:17522:17524:17586:17595:17598:17640:17648:17726:17861:17827:1301:2024:4832:5080:6882:10395:13625:15558:12339:12686:17594:3975:6782:9302:16376:16379:17612:16647:1054:10593:17799:1583:9689:1749:2055:8042\r\n\r\n");
if (NS_FAILED(rv)) return rv;
rv = SEND_DATA("TEST DATA--thisrandomstring--");
rv = SEND_DATA("aaa");
if (NS_FAILED(rv)) return rv;
// Finish the request.
rv = converterListener->OnStopRequest(nsnull, nsnull, rv, nsnull);
rv = converterListener->OnStopRequest(request, nsnull, rv, nsnull);
if (NS_FAILED(rv)) return rv;
NS_RELEASE(converterListener);
#else
// SYNCRONOUS conversion
nsIInputStream *convertedData = nsnull;
rv = StreamConvService->Convert(inputData, fromStr.GetUnicode(), toStr.GetUnicode(), nsnull, &convertedData);
#endif
NS_RELEASE(convFactSup);
nsCOMPtr<nsIInputStream> convertedData;
rv = StreamConvService->Convert(inputData, fromStr.GetUnicode(), toStr.GetUnicode(),
nsnull, getter_AddRefs(convertedData));
if (NS_FAILED(rv)) return rv;
#endif
// Enter the message pump to allow the URL load to proceed.
while ( gKeepRunning ) {
@ -370,5 +294,5 @@ main(int argc, char* argv[])
#endif /* !WIN32 */
}
return NS_ShutdownXPCOM(NULL);
//return NS_ShutdownXPCOM(NULL);
}