(not part of the seamonkey build)

CanHandleContent now has an out parameter for desired content type.
Minor re-write of uri loder logic to incorporate stream conversion. If the content listener passes back
a desired content type that is different from the content type that we asked it to handle, we'll
automatically invoke a stream converter. This allows a doc shell which wants to handle say message/rfc822
to request that content be in the form of text/xul (i.e. if it was presenting the content).
This commit is contained in:
mscott%netscape.com 1999-11-18 01:02:31 +00:00
Родитель 7ecbc0a23d
Коммит 0fefbf1cb0
2 изменённых файлов: 93 добавлений и 37 удалений

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

@ -105,5 +105,6 @@ interface nsIURILoader : nsISupports
in nsIChannel aChannel,
in nsISupports aCtxt,
in nsIURIContentListener aContentListener,
out nsIStreamListener aTargetListener);
out string aDesiredContentType,
out nsIURIContentListener aTargetListener);
};

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

@ -31,6 +31,7 @@
#include "nsICapabilities.h"
#include "nsIProgressEventSink.h"
#include "nsIStreamConverterService.h"
#include "nsVoidArray.h"
#include "nsXPIDLString.h"
@ -38,6 +39,7 @@
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kURILoaderCID, NS_URI_LOADER_CID);
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
// mscott - i ripped this event sink getter class off of the one in the old
// webshell doc loader...
@ -87,6 +89,10 @@ public:
nsISupports * aOpenContext,
nsISupports ** aCurrentOpenContext);
nsresult DispatchContent(nsIChannel * aChannel, nsISupports * aCtxt);
nsresult RetargetOutput(nsIChannel * aChannel, const char * aSrcContentType,
const char * aOutContentType, nsIStreamListener * aStreamListener);
// nsIStreamObserver methods:
NS_DECL_NSISTREAMOBSERVER
@ -173,20 +179,9 @@ nsresult nsDocumentOpenInfo::Open(nsIURI *aURI,
NS_IMETHODIMP nsDocumentOpenInfo::OnStartRequest(nsIChannel * aChannel, nsISupports * aCtxt)
{
nsresult rv = NS_OK;
nsXPIDLCString aContentType;
rv = aChannel->GetContentType(getter_Copies(aContentType));
if (NS_FAILED(rv)) return rv;
// go to the uri dispatcher and give them our stuff...
NS_WITH_SERVICE(nsIURILoader, pURILoader, kURILoaderCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = pURILoader->DispatchContent(aContentType, "view", m_windowTarget,
aChannel, aCtxt, m_contentListener, getter_AddRefs(m_targetStreamListener));
if (m_targetStreamListener)
m_targetStreamListener->OnStartRequest(aChannel, aCtxt);
}
rv = DispatchContent(aChannel, aCtxt);
if (m_targetStreamListener)
m_targetStreamListener->OnStartRequest(aChannel, aCtxt);
return rv;
}
@ -211,6 +206,77 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStopRequest(nsIChannel * aChannel, nsISuppor
return NS_OK;
}
nsresult nsDocumentOpenInfo::DispatchContent(nsIChannel * aChannel, nsISupports * aCtxt)
{
nsXPIDLCString aContentType;
nsresult rv = aChannel->GetContentType(getter_Copies(aContentType));
if (NS_FAILED(rv)) return rv;
// go to the uri dispatcher and give them our stuff...
NS_WITH_SERVICE(nsIURILoader, pURILoader, kURILoaderCID, &rv);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIURIContentListener> aContentListener;
nsXPIDLCString aDesiredContentType;
rv = pURILoader->DispatchContent(aContentType, "view", m_windowTarget,
aChannel, aCtxt,
m_contentListener,
getter_Copies(aDesiredContentType),
getter_AddRefs(aContentListener));
if (NS_SUCCEEDED(rv) && aContentListener)
{
nsCOMPtr<nsIStreamListener> aContentStreamListener;
PRBool aAbortProcess = PR_FALSE;
nsCAutoString contentTypeToUse;
if (aDesiredContentType)
contentTypeToUse = aDesiredContentType;
else
contentTypeToUse = aContentType;
rv = aContentListener->DoContent(contentTypeToUse, "view", m_windowTarget,
aChannel, getter_AddRefs(aContentStreamListener),
&aAbortProcess);
// the listener is doing all the work from here...we are done!!!
if (aAbortProcess) return rv;
// okay, all registered listeners have had a chance to handle this content...
// did one of them give us a stream listener back? if so, let's start reading data
// into it...
rv = RetargetOutput(aChannel, aContentType, aDesiredContentType, aContentStreamListener);
}
}
return rv;
}
nsresult nsDocumentOpenInfo::RetargetOutput(nsIChannel * aChannel, const char * aSrcContentType, const char * aOutContentType,
nsIStreamListener * aStreamListener)
{
nsresult rv = NS_OK;
// do we need to invoke the stream converter service?
if (aOutContentType && *aOutContentType && nsCRT::strcasecmp(aSrcContentType, aOutContentType))
{
NS_WITH_SERVICE(nsIStreamConverterService, StreamConvService, kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsAutoString aUnicSrc (aSrcContentType);
nsAutoString aUniTo (aOutContentType);
// The following call binds this channelListener's mNextListener (typically
// the nsDocumentBindInfo) to the underlying stream converter, and returns
// the underlying stream converter which we then set to be this channelListener's
// mNextListener. This effectively nestles the stream converter down right
// in between the raw stream and the final listener.
nsIStreamListener *converterListener = nsnull;
rv = StreamConvService->AsyncConvertData(aUnicSrc.GetUnicode(), aUniTo.GetUnicode(), aStreamListener, aChannel,
getter_AddRefs(m_targetStreamListener));
}
else
m_targetStreamListener = aStreamListener; // no converter necessary so use a direct pipe
return rv;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Implementation of nsURILoader
///////////////////////////////////////////////////////////////////////////////////////////////
@ -298,7 +364,8 @@ nsresult nsURILoader::DispatchContent(const char * aContentType,
nsIChannel * aChannel,
nsISupports * aCtxt,
nsIURIContentListener * aContentListener,
nsIStreamListener ** aTargetListener)
char ** aContentTypeToUse,
nsIURIContentListener ** aContentListenerToUse)
{
// okay, now we've discovered the content type. We need to do the following:
// (1) Give our uri content listener first crack at handling this content type.
@ -308,7 +375,9 @@ nsresult nsURILoader::DispatchContent(const char * aContentType,
// find a content handler that can and will handle the content
PRBool canHandleContent = PR_FALSE;
if (listenerToUse)
listenerToUse->CanHandleContent(aContentType, aCommand, aWindowTarget, &canHandleContent);
listenerToUse->CanHandleContent(aContentType, aCommand, aWindowTarget,
aContentTypeToUse,
&canHandleContent);
if (!canHandleContent) // if it can't handle the content, scan through the list of registered listeners
{
PRInt32 i = 0;
@ -319,7 +388,9 @@ nsresult nsURILoader::DispatchContent(const char * aContentType,
nsIURIContentListener * listener =(nsIURIContentListener*)m_listeners->ElementAt(i);
if (listener)
{
rv = listener->CanHandleContent(aContentType, aCommand, aWindowTarget, &canHandleContent);
rv = listener->CanHandleContent(aContentType, aCommand, aWindowTarget,
aContentTypeToUse,
&canHandleContent);
if (canHandleContent)
listenerToUse = listener;
}
@ -329,25 +400,9 @@ nsresult nsURILoader::DispatchContent(const char * aContentType,
if (canHandleContent && listenerToUse)
{
nsCOMPtr<nsIStreamListener> aContentStreamListener;
PRBool aAbortProcess = PR_FALSE;
rv = listenerToUse->DoContent(aContentType, aCommand, aWindowTarget,
aChannel, getter_AddRefs(aContentStreamListener),
&aAbortProcess);
// the listener is doing all the work from here...we are done!!!
if (aAbortProcess) return rv;
// okay, all registered listeners have had a chance to handle this content...
// did one of them give us a stream listener back? if so, let's start reading data
// into it...
if (aContentStreamListener)
{
*aTargetListener = aContentStreamListener;
NS_IF_ADDREF(*aTargetListener);
return rv;
}
*aContentListenerToUse = listenerToUse;
NS_IF_ADDREF(*aContentListenerToUse);
return rv;
}
// no registered content listeners to handle this type!!! so go to the register