mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 20:49:27 +00:00
64804. r=dougt. fixing long broken stream converter chaining.
This commit is contained in:
parent
c01e2e45a9
commit
44570a6c2d
@ -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
|
||||
|
@ -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**)®istry);
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -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___
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user