bug #102779 (r=darin@netscape.com, sr=jst@netscape.com) data:// urls now use load groups... this allows onLoad events to fire (when appropriate).

This commit is contained in:
rpotts%netscape.com 2001-12-19 00:42:16 +00:00
parent dec7ea9f5b
commit 36c038dfd4
2 changed files with 112 additions and 30 deletions

View File

@ -43,8 +43,6 @@
#include "nsNetUtil.h"
#include "nsILoadGroup.h"
#include "plbase64.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPipe.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
@ -58,30 +56,32 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
nsDataChannel::nsDataChannel() {
NS_INIT_REFCNT();
mStatus = NS_OK;
mContentLength = -1;
mLoadFlags = nsIRequest::LOAD_NORMAL;
}
nsDataChannel::~nsDataChannel() {
}
NS_IMPL_ISUPPORTS3(nsDataChannel,
NS_IMPL_ISUPPORTS5(nsDataChannel,
nsIDataChannel,
nsIChannel,
nsIRequest)
nsIRequest,
nsIRequestObserver,
nsIStreamListener)
nsresult
nsDataChannel::Init(nsIURI* uri)
{
// we don't care about event sinks in data
nsresult rv;
// Data urls contain all the data within the url string itself.
mUrl = uri;
rv = ParseData();
if (NS_FAILED(rv)) return rv;
return NS_OK;
return rv;
}
typedef struct _writeData {
@ -247,21 +247,28 @@ nsDataChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
NS_IMETHODIMP
nsDataChannel::GetName(PRUnichar* *result)
{
NS_NOTREACHED("nsDataChannel::GetName");
return NS_ERROR_NOT_IMPLEMENTED;
nsXPIDLCString name;
if (mUrl) {
mUrl->GetSpec(getter_Copies(name));
}
*result = ToNewUnicode(name);
return NS_OK;
}
NS_IMETHODIMP
nsDataChannel::IsPending(PRBool *result)
{
NS_NOTREACHED("nsDataChannel::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
// This request is pending if there is an active stream listener...
*result = (mListener) ? PR_TRUE : PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsDataChannel::GetStatus(nsresult *status)
{
*status = NS_OK;
*status = mStatus;
return NS_OK;
}
@ -269,22 +276,23 @@ NS_IMETHODIMP
nsDataChannel::Cancel(nsresult status)
{
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
NS_NOTREACHED("nsDataChannel::Cancel");
return NS_ERROR_NOT_IMPLEMENTED;
mStatus = status;
return NS_OK;
}
NS_IMETHODIMP
nsDataChannel::Suspend(void)
{
NS_NOTREACHED("nsDataChannel::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
// This channel is not suspendable...
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDataChannel::Resume(void)
{
NS_NOTREACHED("nsDataChannel::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
// This channel is not resumable...
return NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
@ -339,21 +347,35 @@ nsDataChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
// we'll just fire everything off at once because we've already got all
// the data.
rv = NS_NewAsyncStreamListener(getter_AddRefs(listener), aListener, eventQ);
rv = NS_NewAsyncStreamListener(getter_AddRefs(listener), this, eventQ);
if (NS_FAILED(rv)) return rv;
rv = listener->OnStartRequest(this, ctxt);
if (NS_FAILED(rv)) return rv;
// Hold onto the real consumer...
mListener = aListener;
PRUint32 streamLen;
rv = mDataStream->Available(&streamLen);
if (NS_FAILED(rv)) return rv;
// Add the request to the loadgroup (if available)
if (mLoadGroup) {
mLoadGroup->AddRequest(this, nsnull);
}
rv = listener->OnDataAvailable(this, ctxt, mDataStream, 0, streamLen);
if (NS_FAILED(rv)) return rv;
// Next, queue up asynchronous stream notifications for OnStartRequest,
// a single OnDataAvailable (containing all of the data) and an
// OnStopRequest...
//
// These notifications will be processed when control returns to the
// message pump and the PLEvents are processed...
//
mStatus = listener->OnStartRequest(this, ctxt);
rv = listener->OnStopRequest(this, ctxt, NS_OK);
return rv;
// Only fire OnDataAvailable(...) if OnStartRequest(...) succeeded!
if (NS_SUCCEEDED(mStatus)) {
mStatus = listener->OnDataAvailable(this, ctxt, mDataStream,
0, mContentLength);
}
// Always fire OnStopRequest(...) even if an error occurred!
(void) listener->OnStopRequest(this, ctxt, mStatus);
return NS_OK;
}
NS_IMETHODIMP
@ -460,3 +482,59 @@ nsDataChannel::GetSecurityInfo(nsISupports **sec)
*sec = nsnull;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequestObserver methods:
NS_IMETHODIMP
nsDataChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
if (NS_SUCCEEDED(mStatus)) {
mStatus = mListener->OnStartRequest(request, ctxt);
}
return mStatus;
}
NS_IMETHODIMP
nsDataChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
nsresult status)
{
// If the request has already failed for some reason, then pass out that
// failure code...
//
if (NS_SUCCEEDED(mStatus)) {
mStatus = status;
}
if (mListener) {
(void) mListener->OnStopRequest(request, ctxt, mStatus);
}
// Drop the reference to the stream listener -- it is no longer needed.
mListener = nsnull;
// Remove this request from the load group -- it is complete.
if (mLoadGroup) {
mLoadGroup->RemoveRequest(this, nsnull, mStatus);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamListener methods:
NS_IMETHODIMP
nsDataChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
nsIInputStream *input,
PRUint32 offset, PRUint32 count)
{
if (NS_SUCCEEDED(mStatus)) {
mStatus = mListener->OnDataAvailable(request, ctxt, input,
offset, count);
}
return mStatus;
}

View File

@ -43,7 +43,6 @@
#include "nsIDataChannel.h"
#include "nsIURI.h"
#include "nsString.h"
#include "nsIEventQueue.h"
#include "nsILoadGroup.h"
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
@ -51,12 +50,15 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsCOMPtr.h"
class nsDataChannel : public nsIDataChannel {
class nsDataChannel : public nsIDataChannel,
public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSIDATACHANNEL
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
// nsFTPChannel methods:
nsDataChannel();
@ -74,11 +76,13 @@ protected:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIInputStream> mDataStream;
nsresult mStatus;
PRUint32 mLoadFlags;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCString mContentType;
PRInt32 mContentLength;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIStreamListener> mListener;
};
#endif /* nsFTPChannel_h___ */