mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 22:04:36 +00:00
Bug 537120 part 1: Make sure the multipart converter's part channels install a type sniffer as needed. r=jduell
This commit is contained in:
parent
e38734397e
commit
cd5d74649f
@ -48,6 +48,7 @@
|
||||
#include "nsCRT.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsURLHelper.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
|
||||
//
|
||||
// Helper function for determining the length of data bytes up to
|
||||
@ -67,7 +68,10 @@ LengthToToken(const char *cursor, const char *token)
|
||||
return len;
|
||||
}
|
||||
|
||||
nsPartChannel::nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID) :
|
||||
nsPartChannel::nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID,
|
||||
nsIStreamListener* aListener) :
|
||||
mMultipartChannel(aMultipartChannel),
|
||||
mListener(aListener),
|
||||
mStatus(NS_OK),
|
||||
mContentLength(LL_MAXUINT),
|
||||
mIsByteRangeRequest(PR_FALSE),
|
||||
@ -96,6 +100,26 @@ void nsPartChannel::InitializeByteRange(PRInt64 aStart, PRInt64 aEnd)
|
||||
mByteRangeEnd = aEnd;
|
||||
}
|
||||
|
||||
nsresult nsPartChannel::SendOnStartRequest(nsISupports* aContext)
|
||||
{
|
||||
return mListener->OnStartRequest(this, aContext);
|
||||
}
|
||||
|
||||
nsresult nsPartChannel::SendOnDataAvailable(nsISupports* aContext,
|
||||
nsIInputStream* aStream,
|
||||
PRUint32 aOffset, PRUint32 aLen)
|
||||
{
|
||||
return mListener->OnDataAvailable(this, aContext, aStream, aOffset, aLen);
|
||||
}
|
||||
|
||||
nsresult nsPartChannel::SendOnStopRequest(nsISupports* aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
// Drop the listener
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
listener.swap(mListener);
|
||||
return listener->OnStopRequest(this, aContext, aStatus);
|
||||
}
|
||||
|
||||
//
|
||||
// nsISupports implementation...
|
||||
@ -734,15 +758,30 @@ nsresult
|
||||
nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mContentType.IsEmpty())
|
||||
nsCOMPtr<nsIStreamListener> partListener(mFinalListener);
|
||||
if (mContentType.IsEmpty()) {
|
||||
mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
|
||||
nsCOMPtr<nsIStreamConverterService> serv =
|
||||
do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIStreamListener> converter;
|
||||
rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE,
|
||||
"*/*",
|
||||
mFinalListener,
|
||||
mContext,
|
||||
getter_AddRefs(converter));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
partListener = converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we already have an mPartChannel, that means we never sent a Stop()
|
||||
// before starting up another "part." that would be bad.
|
||||
NS_ASSERTION(!mPartChannel, "tisk tisk, shouldn't be overwriting a channel");
|
||||
|
||||
nsPartChannel *newChannel;
|
||||
newChannel = new nsPartChannel(aChannel, mCurrentPartID++);
|
||||
newChannel = new nsPartChannel(aChannel, mCurrentPartID++, partListener);
|
||||
if (!newChannel)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
@ -780,7 +819,7 @@ nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
|
||||
|
||||
// Let's start off the load. NOTE: we don't forward on the channel passed
|
||||
// into our OnDataAvailable() as it's the root channel for the raw stream.
|
||||
return mFinalListener->OnStartRequest(mPartChannel, mContext);
|
||||
return mPartChannel->SendOnStartRequest(mContext);
|
||||
}
|
||||
|
||||
|
||||
@ -789,7 +828,7 @@ nsMultiMixedConv::SendStop(nsresult aStatus) {
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (mPartChannel) {
|
||||
rv = mFinalListener->OnStopRequest(mPartChannel, mContext, aStatus);
|
||||
rv = mPartChannel->SendOnStopRequest(mContext, aStatus);
|
||||
// don't check for failure here, we need to remove the channel from
|
||||
// the loadgroup.
|
||||
|
||||
@ -836,7 +875,7 @@ nsMultiMixedConv::SendData(char *aBuffer, PRUint32 aLen) {
|
||||
nsCOMPtr<nsIInputStream> inStream(do_QueryInterface(ss, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return mFinalListener->OnDataAvailable(mPartChannel, mContext, inStream, offset, aLen);
|
||||
return mPartChannel->SendOnDataAvailable(mContext, inStream, offset, aLen);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
@ -68,10 +68,15 @@ class nsPartChannel : public nsIChannel,
|
||||
public nsIMultiPartChannel
|
||||
{
|
||||
public:
|
||||
nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID);
|
||||
nsPartChannel(nsIChannel *aMultipartChannel, PRUint32 aPartID,
|
||||
nsIStreamListener* aListener);
|
||||
|
||||
void InitializeByteRange(PRInt64 aStart, PRInt64 aEnd);
|
||||
void SetIsLastPart() { mIsLastPart = PR_TRUE; }
|
||||
nsresult SendOnStartRequest(nsISupports* aContext);
|
||||
nsresult SendOnDataAvailable(nsISupports* aContext, nsIInputStream* aStream,
|
||||
PRUint32 aOffset, PRUint32 aLen);
|
||||
nsresult SendOnStopRequest(nsISupports* aContext, nsresult aStatus);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUEST
|
||||
@ -84,6 +89,7 @@ protected:
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIChannel> mMultipartChannel;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
|
||||
nsresult mStatus;
|
||||
nsLoadFlags mLoadFlags;
|
||||
|
93
netwerk/test/unit/test_multipart_streamconv.js
Normal file
93
netwerk/test/unit/test_multipart_streamconv.js
Normal file
@ -0,0 +1,93 @@
|
||||
do_load_httpd_js();
|
||||
|
||||
var httpserver = null;
|
||||
var uri = "http://localhost:4444/multipart";
|
||||
|
||||
function make_channel(url) {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
return ios.newChannel(url, "", null);
|
||||
}
|
||||
|
||||
var multipartBody = "--boundary\r\n\r\nSome text\r\n--boundary\r\n\r\n<?xml version='1.0'?><root/>\r\n--boundary--";
|
||||
|
||||
function make_channel(url) {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
return ios.newChannel(url, "", null);
|
||||
}
|
||||
|
||||
function contentHandler(metadata, response)
|
||||
{
|
||||
response.setHeader("Content-Type", 'multipart/mixed; boundary="boundary"');
|
||||
response.bodyOutputStream.write(multipartBody, multipartBody.length);
|
||||
}
|
||||
|
||||
var numTests = 2;
|
||||
var testNum = 0;
|
||||
|
||||
var testData =
|
||||
[
|
||||
{ data: "Some text", type: "text/plain" },
|
||||
{ data: "<?xml version='1.0'?><root/>", type: "text/xml" }
|
||||
];
|
||||
|
||||
function responseHandler(request, buffer)
|
||||
{
|
||||
do_check_eq(buffer, testData[testNum].data);
|
||||
do_check_eq(request.QueryInterface(Ci.nsIChannel).contentType,
|
||||
testData[testNum].type);
|
||||
if (++testNum == numTests)
|
||||
httpserver.stop(do_test_finished);
|
||||
}
|
||||
|
||||
var multipartListener = {
|
||||
_buffer: "",
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsIStreamListener) ||
|
||||
iid.equals(Components.interfaces.nsIRequestObserver) ||
|
||||
iid.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
onStartRequest: function(request, context) {
|
||||
this._buffer = "";
|
||||
},
|
||||
|
||||
onDataAvailable: function(request, context, stream, offset, count) {
|
||||
try {
|
||||
this._buffer = this._buffer.concat(read_stream(stream, count));
|
||||
dump("BUFFEEE: " + this._buffer + "\n\n");
|
||||
} catch (ex) {
|
||||
do_throw("Error in onDataAvailable: " + ex);
|
||||
}
|
||||
},
|
||||
|
||||
onStopRequest: function(request, context, status) {
|
||||
try {
|
||||
responseHandler(request, this._buffer);
|
||||
} catch (ex) {
|
||||
do_throw("Error in closure function: " + ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function run_test()
|
||||
{
|
||||
httpserver = new nsHttpServer();
|
||||
httpserver.registerPathHandler("/multipart", contentHandler);
|
||||
httpserver.start(4444);
|
||||
|
||||
var streamConv = Cc["@mozilla.org/streamConverters;1"]
|
||||
.getService(Ci.nsIStreamConverterService);
|
||||
var conv = streamConv.asyncConvertData("multipart/mixed",
|
||||
"*/*",
|
||||
multipartListener,
|
||||
null);
|
||||
|
||||
var chan = make_channel(uri);
|
||||
chan.asyncOpen(conv, null);
|
||||
do_test_pending();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user