зеркало из https://github.com/mozilla/gecko-dev.git
Back out changeset a8eb5fc88c01: relanding bug 455311. Treat .url files as redirects. r+sr=biesi
This commit is contained in:
Родитель
88512b418e
Коммит
43a6ea85c9
|
@ -62,7 +62,7 @@ class ScopedRequestSuspender {
|
|||
public:
|
||||
ScopedRequestSuspender(nsIRequest *request)
|
||||
: mRequest(request) {
|
||||
if (NS_FAILED(mRequest->Suspend())) {
|
||||
if (mRequest && NS_FAILED(mRequest->Suspend())) {
|
||||
NS_WARNING("Couldn't suspend pump");
|
||||
mRequest = nsnull;
|
||||
}
|
||||
|
@ -94,7 +94,8 @@ nsBaseChannel::nsBaseChannel()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsBaseChannel::Redirect(nsIChannel *newChannel, PRUint32 redirectFlags)
|
||||
nsBaseChannel::Redirect(nsIChannel *newChannel, PRUint32 redirectFlags,
|
||||
PRBool openNewChannel)
|
||||
{
|
||||
SUSPEND_PUMP_FOR_SCOPE();
|
||||
|
||||
|
@ -147,9 +148,11 @@ nsBaseChannel::Redirect(nsIChannel *newChannel, PRUint32 redirectFlags)
|
|||
// unaffected, so we defer tearing down our channel until we have succeeded
|
||||
// with the redirect.
|
||||
|
||||
rv = newChannel->AsyncOpen(mListener, mListenerContext);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (openNewChannel) {
|
||||
rv = newChannel->AsyncOpen(mListener, mListenerContext);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// close down this channel
|
||||
Cancel(NS_BINDING_REDIRECTED);
|
||||
|
@ -216,10 +219,17 @@ nsresult
|
|||
nsBaseChannel::BeginPumpingData()
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = OpenContentStream(PR_TRUE, getter_AddRefs(stream));
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv = OpenContentStream(PR_TRUE, getter_AddRefs(stream),
|
||||
getter_AddRefs(channel));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ASSERTION(!stream || !channel, "Got both a channel and a stream?");
|
||||
|
||||
if (channel)
|
||||
return NS_DispatchToCurrentThread(new RedirectRunnable(this, channel));
|
||||
|
||||
// By assigning mPump, we flag this channel as pending (see IsPending). It's
|
||||
// important that the pending flag is set when we call into the stream (the
|
||||
// call to AsyncRead results in the stream's AsyncWait method being called)
|
||||
|
@ -234,6 +244,29 @@ nsBaseChannel::BeginPumpingData()
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsBaseChannel::HandleAsyncRedirect(nsIChannel* newChannel)
|
||||
{
|
||||
NS_ASSERTION(!mPump, "Shouldn't have gotten here");
|
||||
nsresult rv = Redirect(newChannel, nsIChannelEventSink::REDIRECT_INTERNAL,
|
||||
PR_TRUE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Notify our consumer ourselves
|
||||
Cancel(rv);
|
||||
mListener->OnStartRequest(this, mListenerContext);
|
||||
mListener->OnStopRequest(this, mListenerContext, mStatus);
|
||||
mListener = nsnull;
|
||||
mListenerContext = nsnull;
|
||||
}
|
||||
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nsnull, mStatus);
|
||||
|
||||
// Drop notification callbacks to prevent cycles.
|
||||
mCallbacks = nsnull;
|
||||
CallbacksChanged();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsBaseChannel::nsISupports
|
||||
|
||||
|
@ -451,8 +484,15 @@ nsBaseChannel::Open(nsIInputStream **result)
|
|||
NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS);
|
||||
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
|
||||
|
||||
nsresult rv = OpenContentStream(PR_FALSE, result);
|
||||
if (rv == NS_ERROR_NOT_IMPLEMENTED)
|
||||
nsCOMPtr<nsIChannel> chan;
|
||||
nsresult rv = OpenContentStream(PR_FALSE, result, getter_AddRefs(chan));
|
||||
NS_ASSERTION(!chan || !*result, "Got both a channel and a stream?");
|
||||
if (NS_SUCCEEDED(rv) && chan) {
|
||||
rv = Redirect(chan, nsIChannelEventSink::REDIRECT_INTERNAL, PR_FALSE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = chan->Open(result);
|
||||
} else if (rv == NS_ERROR_NOT_IMPLEMENTED)
|
||||
return NS_ImplementChannelOpen(this, result);
|
||||
|
||||
mWasOpened = NS_SUCCEEDED(rv);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsBaseChannel is designed to be subclassed. The subclass is responsible for
|
||||
|
@ -103,7 +104,12 @@ private:
|
|||
// need to implement ReadSegments. If async is false, this method may return
|
||||
// NS_ERROR_NOT_IMPLEMENTED to cause the basechannel to implement Open in
|
||||
// terms of AsyncOpen (see NS_ImplementChannelOpen).
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **stream) = 0;
|
||||
// A callee is allowed to return an nsIChannel instead of an nsIInputStream.
|
||||
// That case will be treated as a redirect to the new channel. By default
|
||||
// *channel will be set to null by the caller, so callees who don't want to
|
||||
// return one an just not touch it.
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **stream,
|
||||
nsIChannel** channel) = 0;
|
||||
|
||||
// The basechannel calls this method from its OnTransportStatus method to
|
||||
// determine whether to call nsIProgressEventSink::OnStatus in addition to
|
||||
|
@ -126,12 +132,14 @@ public:
|
|||
// Methods provided for use by the derived class:
|
||||
|
||||
// Redirect to another channel. This method takes care of notifying
|
||||
// observers of this redirect as well as of opening the new channel. It also
|
||||
// cancels |this| with the status code NS_BINDING_REDIRECTED. A failure
|
||||
// return from this method means that the redirect could not be performed (no
|
||||
// channel was opened; this channel wasn't canceled.) The redirectFlags
|
||||
// parameter consists of the flag values defined on nsIChannelEventSink.
|
||||
nsresult Redirect(nsIChannel *newChannel, PRUint32 redirectFlags);
|
||||
// observers of this redirect as well as of opening the new channel, if asked
|
||||
// to do so. It also cancels |this| with the status code
|
||||
// NS_BINDING_REDIRECTED. A failure return from this method means that the
|
||||
// redirect could not be performed (no channel was opened; this channel
|
||||
// wasn't canceled.) The redirectFlags parameter consists of the flag values
|
||||
// defined on nsIChannelEventSink.
|
||||
nsresult Redirect(nsIChannel *newChannel, PRUint32 redirectFlags,
|
||||
PRBool openNewChannel);
|
||||
|
||||
// Tests whether a type hint was set. Subclasses can use this to decide
|
||||
// whether to call SetContentType.
|
||||
|
@ -233,6 +241,31 @@ private:
|
|||
OnCallbacksChanged();
|
||||
}
|
||||
|
||||
// Handle an async redirect callback. This will only be called if we
|
||||
// returned success from AsyncOpen while posting a redirect runnable.
|
||||
void HandleAsyncRedirect(nsIChannel* newChannel);
|
||||
|
||||
class RedirectRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
RedirectRunnable(nsBaseChannel* chan, nsIChannel* newChannel)
|
||||
: mChannel(chan), mNewChannel(newChannel)
|
||||
{
|
||||
NS_PRECONDITION(newChannel, "Must have channel to redirect to");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mChannel->HandleAsyncRedirect(mNewChannel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsBaseChannel> mChannel;
|
||||
nsCOMPtr<nsIChannel> mNewChannel;
|
||||
};
|
||||
friend class RedirectRunnable;
|
||||
|
||||
nsRefPtr<nsInputStreamPump> mPump;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
nsCOMPtr<nsIProgressEventSink> mProgressSink;
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
// nsInputStreamChannel
|
||||
|
||||
nsresult
|
||||
nsInputStreamChannel::OpenContentStream(PRBool async, nsIInputStream **result)
|
||||
nsInputStreamChannel::OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel)
|
||||
{
|
||||
NS_ENSURE_TRUE(mContentStream, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ public:
|
|||
protected:
|
||||
virtual ~nsInputStreamChannel() {}
|
||||
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIInputStream> mContentStream;
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
#include "prmem.h"
|
||||
|
||||
nsresult
|
||||
nsDataChannel::OpenContentStream(PRBool async, nsIInputStream **result)
|
||||
nsDataChannel::OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel)
|
||||
{
|
||||
NS_ENSURE_TRUE(URI(), NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel);
|
||||
};
|
||||
|
||||
#endif /* nsDataChannel_h___ */
|
||||
|
|
|
@ -307,7 +307,8 @@ nsFileChannel::MakeFileInputStream(nsIFile *file,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFileChannel::OpenContentStream(PRBool async, nsIInputStream **result)
|
||||
nsFileChannel::OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel)
|
||||
{
|
||||
// NOTE: the resulting file is a clone, so it is safe to pass it to the
|
||||
// file input stream which will be read on a background thread.
|
||||
|
@ -316,6 +317,24 @@ nsFileChannel::OpenContentStream(PRBool async, nsIInputStream **result)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIFileProtocolHandler> fileHandler;
|
||||
rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
rv = fileHandler->ReadURLFile(file, getter_AddRefs(newURI));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIChannel> newChannel;
|
||||
rv = NS_NewChannel(getter_AddRefs(newChannel), newURI);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*result = nsnull;
|
||||
newChannel.forget(channel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
|
||||
if (mUploadStream) {
|
||||
|
|
|
@ -65,7 +65,8 @@ protected:
|
|||
nsresult MakeFileInputStream(nsIFile *file, nsCOMPtr<nsIInputStream> &stream,
|
||||
nsCString &contentType);
|
||||
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIInputStream> mUploadStream;
|
||||
|
|
|
@ -278,30 +278,12 @@ nsFileProtocolHandler::NewURI(const nsACString &spec,
|
|||
NS_IMETHODIMP
|
||||
nsFileProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// This file may be a url file
|
||||
nsCOMPtr<nsIFileURL> url(do_QueryInterface(uri));
|
||||
if (url) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = url->GetFile(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = ReadURLFile(file, getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = NS_NewChannel(result, uri);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsFileChannel *chan = new nsFileChannel(uri);
|
||||
if (!chan)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(chan);
|
||||
|
||||
rv = chan->Init();
|
||||
nsresult rv = chan->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(chan);
|
||||
return rv;
|
||||
|
|
|
@ -143,7 +143,8 @@ nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsFtpChannel::OpenContentStream(PRBool async, nsIInputStream **result)
|
||||
nsFtpChannel::OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel)
|
||||
{
|
||||
if (!async)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
|
|
@ -117,7 +117,8 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~nsFtpChannel() {}
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel);
|
||||
virtual PRBool GetStatusArg(nsresult status, nsString &statusArg);
|
||||
virtual void OnCallbacksChanged();
|
||||
|
||||
|
|
|
@ -469,7 +469,8 @@ nsGopherChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsGopherChannel::OpenContentStream(PRBool async, nsIInputStream **result)
|
||||
nsGopherChannel::OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel)
|
||||
{
|
||||
// Implement nsIChannel::Open in terms of nsIChannel::AsyncOpen
|
||||
if (!async)
|
||||
|
|
|
@ -59,7 +59,8 @@ public:
|
|||
protected:
|
||||
virtual ~nsGopherChannel() {}
|
||||
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
|
||||
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result,
|
||||
nsIChannel** channel);
|
||||
virtual PRBool GetStatusArg(nsresult status, nsString &statusArg);
|
||||
|
||||
private:
|
||||
|
|
Загрузка…
Ссылка в новой задаче