bug #81937 (r=valeski, sr=mscott, a=selmer) multipart/x-mixed-replace content was not being retargetted correctly...

This commit is contained in:
rpotts%netscape.com 2001-05-29 22:10:50 +00:00
Родитель e3b9cde2ff
Коммит 5b394a26a3
4 изменённых файлов: 343 добавлений и 54 удалений

Просмотреть файл

@ -3737,6 +3737,9 @@ nsDocShell::CreateContentViewer(const char *aContentType,
if (currentLoadGroup)
currentLoadGroup->RemoveRequest(request, nsnull, NS_OK);
// Update the notification callbacks, so that progress and
// status information are sent to the right docshell...
aOpenedChannel->SetNotificationCallbacks(this);
}
NS_ENSURE_SUCCESS(Embed(viewer, "", (nsISupports *) nsnull),

Просмотреть файл

@ -30,13 +30,311 @@
#include "nsMimeTypes.h"
#include "nsIByteArrayInputStream.h"
//
// nsPartChannel is a "dummy" channel which represents an individual part of
// a multipart/mixed stream...
//
// Instances on this channel are passed out to the consumer through the
// nsIStreamListener interface.
//
class nsPartChannel : public nsIChannel,
public nsIByteRangeRequest
{
public:
nsPartChannel(nsIChannel *aMultipartChannel);
void InitializeByteRange(PRInt32 aStart, PRInt32 aEnd);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSIBYTERANGEREQUEST
protected:
virtual ~nsPartChannel();
protected:
nsCOMPtr<nsIChannel> mMultipartChannel;
nsresult mStatus;
nsLoadFlags mLoadFlags;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCString mContentType;
PRInt32 mContentLength;
PRBool mIsByteRangeRequest;
PRInt32 mByteRangeStart;
PRInt32 mByteRangeEnd;
};
nsPartChannel::nsPartChannel(nsIChannel *aMultipartChannel) :
mStatus(NS_OK),
mContentLength(-1),
mIsByteRangeRequest(PR_FALSE),
mByteRangeStart(0),
mByteRangeEnd(0)
{
NS_INIT_ISUPPORTS();
mMultipartChannel = aMultipartChannel;
// Inherit the load flags from the original channel...
mMultipartChannel->GetLoadFlags(&mLoadFlags);
mMultipartChannel->GetLoadGroup(getter_AddRefs(mLoadGroup));
}
nsPartChannel::~nsPartChannel()
{
}
void nsPartChannel::InitializeByteRange(PRInt32 aStart, PRInt32 aEnd)
{
mIsByteRangeRequest = PR_TRUE;
mByteRangeStart = aStart;
mByteRangeEnd = aEnd;
}
//
// nsISupports implementation...
//
NS_IMPL_ADDREF(nsPartChannel)
NS_IMPL_RELEASE(nsPartChannel)
NS_INTERFACE_MAP_BEGIN(nsPartChannel)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
NS_INTERFACE_MAP_ENTRY(nsIChannel)
NS_INTERFACE_MAP_ENTRY(nsIByteRangeRequest)
NS_INTERFACE_MAP_END
//
// nsIRequest implementation...
//
NS_IMETHODIMP
nsPartChannel::GetName(PRUnichar * *aResult)
{
return mMultipartChannel->GetName(aResult);
}
NS_IMETHODIMP
nsPartChannel::IsPending(PRBool *aResult)
{
// For now, consider the active lifetime of each part the same as
// the underlying multipart channel... This is not exactly right,
// but it is good enough :-)
return mMultipartChannel->IsPending(aResult);
}
NS_IMETHODIMP
nsPartChannel::GetStatus(nsresult *aResult)
{
nsresult rv = NS_OK;
if (NS_FAILED(mStatus)) {
*aResult = mStatus;
} else {
rv = mMultipartChannel->GetStatus(aResult);
}
return rv;
}
NS_IMETHODIMP
nsPartChannel::Cancel(nsresult aStatus)
{
// Cancelling an individual part must not cancel the underlying
// multipart channel...
mStatus = aStatus;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::Suspend(void)
{
// Suspending an individual part must not suspend the underlying
// multipart channel...
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::Resume(void)
{
// Resuming an individual part must not resume the underlying
// multipart channel...
return NS_OK;
}
//
// nsIChannel implementation
//
NS_IMETHODIMP
nsPartChannel::GetOriginalURI(nsIURI * *aURI)
{
return mMultipartChannel->GetOriginalURI(aURI);
}
NS_IMETHODIMP
nsPartChannel::SetOriginalURI(nsIURI *aURI)
{
return mMultipartChannel->SetOriginalURI(aURI);
}
NS_IMETHODIMP
nsPartChannel::GetURI(nsIURI * *aURI)
{
return mMultipartChannel->GetURI(aURI);
}
NS_IMETHODIMP
nsPartChannel::Open(nsIInputStream **result)
{
// This channel cannot be opened!
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPartChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
{
// This channel cannot be opened!
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPartChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
{
*aLoadFlags = mLoadFlags;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
{
mLoadFlags = aLoadFlags;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::GetOwner(nsISupports* *aOwner)
{
return mMultipartChannel->GetOwner(aOwner);
}
NS_IMETHODIMP
nsPartChannel::SetOwner(nsISupports* aOwner)
{
return mMultipartChannel->SetOwner(aOwner);
}
NS_IMETHODIMP
nsPartChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
{
return mMultipartChannel->GetNotificationCallbacks(aCallbacks);
}
NS_IMETHODIMP
nsPartChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
{
return mMultipartChannel->SetNotificationCallbacks(aCallbacks);
}
NS_IMETHODIMP
nsPartChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
return mMultipartChannel->GetSecurityInfo(aSecurityInfo);
}
NS_IMETHODIMP
nsPartChannel::GetContentType(char * *aContentType)
{
*aContentType = mContentType.ToNewCString();
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::SetContentType(const char *aContentType)
{
mContentType.Assign(aContentType);
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::SetContentLength(PRInt32 aContentLength)
{
mContentLength = aContentLength;
return NS_OK;
}
//
// nsIByteRangeRequest implementation...
//
NS_IMETHODIMP
nsPartChannel::GetIsByteRangeRequest(PRBool *aIsByteRangeRequest)
{
*aIsByteRangeRequest = mIsByteRangeRequest;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::GetStartRange(PRInt32 *aStartRange)
{
*aStartRange = mByteRangeStart;
return NS_OK;
}
NS_IMETHODIMP
nsPartChannel::GetEndRange(PRInt32 *aEndRange)
{
*aEndRange = mByteRangeEnd;
return NS_OK;
}
// nsISupports implementation
NS_IMPL_THREADSAFE_ISUPPORTS5(nsMultiMixedConv,
NS_IMPL_THREADSAFE_ISUPPORTS3(nsMultiMixedConv,
nsIStreamConverter,
nsIStreamListener,
nsIRequestObserver,
nsIByteRangeRequest,
nsIChannel);
nsIStreamListener,
nsIRequestObserver);
// nsIStreamConverter implementation
@ -321,28 +619,6 @@ nsMultiMixedConv::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
}
NS_IMETHODIMP
nsMultiMixedConv::GetIsByteRangeRequest(PRBool *aIsByteRangeRequest)
{
*aIsByteRangeRequest = mIsByteRangeRequest;
return NS_OK;
}
NS_IMETHODIMP
nsMultiMixedConv::GetStartRange(PRInt32 *aStartRange)
{
*aStartRange = mByteRangeStart;
return NS_OK;
}
NS_IMETHODIMP
nsMultiMixedConv::GetEndRange(PRInt32 *aEndRange)
{
*aEndRange = mByteRangeEnd;
return NS_OK;
}
// nsMultiMixedConv methods
nsMultiMixedConv::nsMultiMixedConv() {
NS_INIT_ISUPPORTS();
@ -359,6 +635,10 @@ nsMultiMixedConv::nsMultiMixedConv() {
nsMultiMixedConv::~nsMultiMixedConv() {
NS_ASSERTION(!mBuffer, "all buffered data should be gone");
if (mBuffer) {
nsMemory::Free(mBuffer);
mBuffer = nsnull;
}
}
nsresult
@ -377,12 +657,7 @@ nsMultiMixedConv::BufferData(char *aData, PRUint32 aLen) {
nsresult
nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
nsresult rv = NS_OK;
// First build up a dummy uri.
nsCOMPtr<nsIURI> partURI;
rv = aChannel->GetURI(getter_AddRefs(partURI));
if (NS_FAILED(rv)) return rv;
nsresult rv = NS_OK;
if (mContentType.IsEmpty())
mContentType = UNKNOWN_CONTENT_TYPE;
@ -391,11 +666,22 @@ nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
// before starting up another "part." that would be bad.
NS_ASSERTION(!mPartChannel, "tisk tisk, shouldn't be overwriting a channel");
rv = NS_NewInputStreamChannel(getter_AddRefs(mPartChannel),
partURI,
nsnull, // inStr
mContentType.get(),
mContentLength);
nsPartChannel *newChannel;
newChannel = new nsPartChannel(aChannel);
if (!newChannel)
return NS_ERROR_OUT_OF_MEMORY;
if (mIsByteRangeRequest) {
newChannel->InitializeByteRange(mByteRangeStart, mByteRangeEnd);
}
// Set up the new part channel...
mPartChannel = newChannel;
rv = mPartChannel->SetContentType(mContentType);
if (NS_FAILED(rv)) return rv;
mPartChannel->SetContentLength(mContentLength);
if (NS_FAILED(rv)) return rv;
nsLoadFlags loadFlags = 0;
@ -403,19 +689,18 @@ nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
loadFlags |= nsIChannel::LOAD_REPLACE;
mPartChannel->SetLoadFlags(loadFlags);
nsCOMPtr<nsILoadGroup> loadGroup;
(void)aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
nsCOMPtr<nsILoadGroup> loadGroup;
(void)mPartChannel->GetLoadGroup(getter_AddRefs(loadGroup));
// Add the new channel to the load group (if any)
if (loadGroup) {
rv = mPartChannel->SetLoadGroup(loadGroup);
if (NS_FAILED(rv)) return rv;
rv = loadGroup->AddRequest(mPartChannel, nsnull);
if (NS_FAILED(rv)) return rv;
}
// 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(this, mContext);
return mFinalListener->OnStartRequest(mPartChannel, mContext);
}
@ -424,7 +709,7 @@ nsMultiMixedConv::SendStop(nsresult aStatus) {
nsresult rv = NS_OK;
if (mPartChannel) {
rv = mFinalListener->OnStopRequest(this, mContext, aStatus);
rv = mFinalListener->OnStopRequest(mPartChannel, mContext, aStatus);
// don't check for failure here, we need to remove the channel from
// the loadgroup.
@ -466,7 +751,7 @@ nsMultiMixedConv::SendData(char *aBuffer, PRUint32 aLen) {
rv = inStream->Available(&len);
if (NS_FAILED(rv)) return rv;
return mFinalListener->OnDataAvailable(this, mContext, inStream, 0, len);
return mFinalListener->OnDataAvailable(mPartChannel, mContext, inStream, 0, len);
}
PRInt32

Просмотреть файл

@ -76,16 +76,12 @@ static NS_DEFINE_CID(kMultiMixedConverterCID, NS_MULTIMIXEDCONVERTER_CI
//
//
class nsMultiMixedConv : public nsIStreamConverter, public nsIByteRangeRequest, public nsIChannel {
class nsMultiMixedConv : public nsIStreamConverter {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMCONVERTER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSIBYTERANGEREQUEST
NS_FORWARD_SAFE_NSICHANNEL(mPartChannel)
NS_FORWARD_SAFE_NSIREQUEST(mPartChannel)
nsMultiMixedConv();
virtual ~nsMultiMixedConv();
@ -102,10 +98,10 @@ protected:
// member data
PRBool mNewPart; // Are we processing the beginning of a part?
PRBool mProcessingHeaders;
PRBool mProcessingHeaders;
nsCOMPtr<nsIStreamListener> mFinalListener; // this guy gets the converted data via his OnDataAvailable()
nsXPIDLCString mToken;
nsXPIDLCString mToken;
PRUint32 mTokenLen;
nsCOMPtr<nsIChannel>mPartChannel; // the channel for the given part we're processing.
@ -118,6 +114,9 @@ protected:
PRUint32 mBufLen;
PRBool mFirstOnData; // used to determine if we're in our first OnData callback.
// The following members are for tracking the byte ranges in
// multipart/mixed content which specified the 'Content-Range:'
// header...
PRInt32 mByteRangeStart;
PRInt32 mByteRangeEnd;
PRBool mIsByteRangeRequest;

Просмотреть файл

@ -431,11 +431,13 @@ nsDocLoaderImpl::OnStartRequest(nsIRequest *request, nsISupports *aCtxt)
count));
}
#endif /* PR_LOGGING */
PRBool bJustStartedLoading = PR_FALSE;
PRUint32 loadFlags = 0;
request->GetLoadFlags(&loadFlags);
if (!mIsLoadingDocument && (loadFlags & nsIChannel::LOAD_DOCUMENT_URI)) {
bJustStartedLoading = PR_TRUE;
mIsLoadingDocument = PR_TRUE;
ClearInternalProgress(); // only clear our progress if we are starting a new load....
}
@ -468,7 +470,7 @@ nsDocLoaderImpl::OnStartRequest(nsIRequest *request, nsISupports *aCtxt)
// Only fire the start document load notification for the first
// document URI... Do not fire it again for redirections
//
if (!(loadFlags & nsIChannel::LOAD_REPLACE)) {
if (bJustStartedLoading) {
// Update the progress status state
mProgressStateFlags = nsIWebProgressListener::STATE_START;