mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 915024 - Add ForcePending for HttpChannel. r=jduell
This commit is contained in:
parent
ca29747d5e
commit
2cd40ad8a5
@ -43,6 +43,7 @@ XPIDL_SOURCES += [
|
||||
'nsIExternalProtocolHandler.idl',
|
||||
'nsIFileStreams.idl',
|
||||
'nsIFileURL.idl',
|
||||
'nsIForcePendingChannel.idl',
|
||||
'nsIIncrementalDownload.idl',
|
||||
'nsIInputStreamChannel.idl',
|
||||
'nsIInputStreamPump.idl',
|
||||
|
22
netwerk/base/public/nsIForcePendingChannel.idl
Normal file
22
netwerk/base/public/nsIForcePendingChannel.idl
Normal file
@ -0,0 +1,22 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* nsIForcePending interface exposes a function that enables overwriting of the normal
|
||||
* behavior for the channel's IsPending(), forcing 'true' to be returned.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(225ab092-1554-423a-9492-606f6db3b4fb)]
|
||||
interface nsIForcePendingChannel : nsISupports
|
||||
{
|
||||
|
||||
/**
|
||||
* forcePending(true) overrides the normal behavior for the
|
||||
* channel's IsPending(), forcing 'true' to be returned. A call to
|
||||
* forcePending(false) reverts IsPending() back to normal behavior.
|
||||
*/
|
||||
void forcePending(in boolean aForcePending);
|
||||
};
|
@ -9,6 +9,9 @@
|
||||
#include "nsFTPChannel.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsFtpProtocolHandler.h"
|
||||
#include "nsIEncodedChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIForcePendingChannel.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/unused.h"
|
||||
@ -57,7 +60,8 @@ NS_IMPL_ISUPPORTS(FTPChannelParent,
|
||||
nsIStreamListener,
|
||||
nsIParentChannel,
|
||||
nsIInterfaceRequestor,
|
||||
nsIRequestObserver)
|
||||
nsIRequestObserver,
|
||||
nsIChannelEventSink)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FTPChannelParent::PFTPChannelParent
|
||||
@ -114,13 +118,16 @@ FTPChannelParent::DoAsyncOpen(const URIParams& aURI,
|
||||
if (NS_FAILED(rv))
|
||||
return SendFailedAsyncOpen(rv);
|
||||
|
||||
mChannel = static_cast<nsFtpChannel*>(chan.get());
|
||||
mChannel = chan;
|
||||
|
||||
// later on mChannel may become an HTTP channel (we'll be redirected to one
|
||||
// if we're using a proxy), but for now this is safe
|
||||
nsFtpChannel* ftpChan = static_cast<nsFtpChannel*>(mChannel.get());
|
||||
|
||||
if (mPBOverride != kPBOverride_Unset) {
|
||||
mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
|
||||
ftpChan->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
|
||||
}
|
||||
|
||||
rv = mChannel->SetNotificationCallbacks(this);
|
||||
rv = ftpChan->SetNotificationCallbacks(this);
|
||||
if (NS_FAILED(rv))
|
||||
return SendFailedAsyncOpen(rv);
|
||||
|
||||
@ -128,16 +135,16 @@ FTPChannelParent::DoAsyncOpen(const URIParams& aURI,
|
||||
nsCOMPtr<nsIInputStream> upload = DeserializeInputStream(aUploadStream, fds);
|
||||
if (upload) {
|
||||
// contentType and contentLength are ignored
|
||||
rv = mChannel->SetUploadStream(upload, EmptyCString(), 0);
|
||||
rv = ftpChan->SetUploadStream(upload, EmptyCString(), 0);
|
||||
if (NS_FAILED(rv))
|
||||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
rv = mChannel->ResumeAt(aStartPos, aEntityID);
|
||||
rv = ftpChan->ResumeAt(aStartPos, aEntityID);
|
||||
if (NS_FAILED(rv))
|
||||
return SendFailedAsyncOpen(rv);
|
||||
|
||||
rv = mChannel->AsyncOpen(this, nullptr);
|
||||
rv = ftpChan->AsyncOpen(this, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return SendFailedAsyncOpen(rv);
|
||||
|
||||
@ -154,7 +161,7 @@ FTPChannelParent::ConnectChannel(const uint32_t& channelId)
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mChannel = static_cast<nsFtpChannel*>(channel.get());
|
||||
mChannel = channel;
|
||||
|
||||
LOG((" found channel %p, rv=%08x", mChannel.get(), rv));
|
||||
|
||||
@ -240,7 +247,10 @@ FTPChannelParent::RecvDivertOnStopRequest(const nsresult& statusCode)
|
||||
|
||||
// Reset fake pending status in case OnStopRequest has already been called.
|
||||
if (mChannel) {
|
||||
mChannel->ForcePending(false);
|
||||
nsCOMPtr<nsIForcePendingChannel> forcePendingIChan = do_QueryInterface(mChannel);
|
||||
if (forcePendingIChan) {
|
||||
forcePendingIChan->ForcePending(false);
|
||||
}
|
||||
}
|
||||
|
||||
OnStopRequest(mChannel, nullptr, status);
|
||||
@ -297,14 +307,14 @@ FTPChannelParent::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
||||
resChan->GetEntityID(entityID);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFTPChannel> ftpChan = do_QueryInterface(aRequest);
|
||||
PRTime lastModified = 0;
|
||||
nsCOMPtr<nsIFTPChannel> ftpChan = do_QueryInterface(aRequest);
|
||||
if (ftpChan) {
|
||||
ftpChan->GetLastModifiedTime(&lastModified);
|
||||
} else {
|
||||
// Temporary hack: if we were redirected to use an HTTP channel (ie FTP is
|
||||
// using an HTTP proxy), cancel, as we don't support those redirects yet.
|
||||
aRequest->Cancel(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpChan = do_QueryInterface(aRequest);
|
||||
if (httpChan) {
|
||||
httpChan->GetLastModifiedTime(&lastModified);
|
||||
}
|
||||
|
||||
URIParams uriparam;
|
||||
@ -499,7 +509,10 @@ FTPChannelParent::StartDiversion()
|
||||
|
||||
// Fake pending status in case OnStopRequest has already been called.
|
||||
if (mChannel) {
|
||||
mChannel->ForcePending(true);
|
||||
nsCOMPtr<nsIForcePendingChannel> forcePendingIChan = do_QueryInterface(mChannel);
|
||||
if (forcePendingIChan) {
|
||||
forcePendingIChan->ForcePending(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Call OnStartRequest for the "DivertTo" listener.
|
||||
@ -567,8 +580,10 @@ FTPChannelParent::NotifyDiversionFailed(nsresult aErrorCode,
|
||||
MOZ_RELEASE_ASSERT(mChannel);
|
||||
|
||||
mChannel->Cancel(aErrorCode);
|
||||
|
||||
mChannel->ForcePending(false);
|
||||
nsCOMPtr<nsIForcePendingChannel> forcePendingIChan = do_QueryInterface(mChannel);
|
||||
if (forcePendingIChan) {
|
||||
forcePendingIChan->ForcePending(false);
|
||||
}
|
||||
|
||||
bool isPending = false;
|
||||
nsresult rv = mChannel->IsPending(&isPending);
|
||||
@ -581,9 +596,15 @@ FTPChannelParent::NotifyDiversionFailed(nsresult aErrorCode,
|
||||
// Channel has already sent OnStartRequest to the child, so ensure that we
|
||||
// call it here if it hasn't already been called.
|
||||
if (!mDivertedOnStartRequest) {
|
||||
mChannel->ForcePending(true);
|
||||
nsCOMPtr<nsIForcePendingChannel> forcePendingIChan = do_QueryInterface(mChannel);
|
||||
if (forcePendingIChan) {
|
||||
forcePendingIChan->ForcePending(true);
|
||||
}
|
||||
mDivertToListener->OnStartRequest(mChannel, nullptr);
|
||||
mChannel->ForcePending(false);
|
||||
|
||||
if (forcePendingIChan) {
|
||||
forcePendingIChan->ForcePending(false);
|
||||
}
|
||||
}
|
||||
// If the channel is pending, it will call OnStopRequest itself; otherwise, do
|
||||
// it here.
|
||||
@ -598,6 +619,29 @@ FTPChannelParent::NotifyDiversionFailed(nsresult aErrorCode,
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FTPChannelParent::nsIChannelEventSink
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
FTPChannelParent::AsyncOnChannelRedirect(
|
||||
nsIChannel *oldChannel,
|
||||
nsIChannel *newChannel,
|
||||
uint32_t redirectFlags,
|
||||
nsIAsyncVerifyRedirectCallback* callback)
|
||||
{
|
||||
nsCOMPtr<nsIFTPChannel> ftpChan = do_QueryInterface(newChannel);
|
||||
if (!ftpChan) {
|
||||
// when FTP is set to use HTTP proxying, we wind up getting redirected to an HTTP channel.
|
||||
nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(newChannel);
|
||||
if (!httpChan)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
mChannel = newChannel;
|
||||
callback->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//---------------------
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -24,6 +24,7 @@ class FTPChannelParent : public PFTPChannelParent
|
||||
, public nsIParentChannel
|
||||
, public nsIInterfaceRequestor
|
||||
, public ADivertableParentChannel
|
||||
, public nsIChannelEventSink
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -31,6 +32,7 @@ public:
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIPARENTCHANNEL
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
FTPChannelParent(nsILoadContext* aLoadContext, PBOverrideStatus aOverrideStatus);
|
||||
|
||||
@ -77,7 +79,8 @@ protected:
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
||||
nsRefPtr<nsFtpChannel> mChannel;
|
||||
// if configured to use HTTP proxy for FTP, this can an an HTTP channel.
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
|
||||
bool mIPCClosed;
|
||||
|
||||
|
@ -29,7 +29,8 @@ NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel,
|
||||
nsIUploadChannel,
|
||||
nsIResumableChannel,
|
||||
nsIFTPChannel,
|
||||
nsIProxiedChannel)
|
||||
nsIProxiedChannel,
|
||||
nsIForcePendingChannel)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -199,7 +200,7 @@ nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
|
||||
aResult = mFTPEventSink;
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP
|
||||
nsFtpChannel::ForcePending(bool aForcePending)
|
||||
{
|
||||
// Set true here so IsPending will return true.
|
||||
@ -207,6 +208,8 @@ nsFtpChannel::ForcePending(bool aForcePending)
|
||||
// OnStopRequest can be called in the parent before callbacks are diverted
|
||||
// back from the child to the listener in the parent.
|
||||
mForcePending = aForcePending;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIFTPChannel.h"
|
||||
#include "nsIForcePendingChannel.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsIProxiedChannel.h"
|
||||
@ -23,7 +24,8 @@ class nsFtpChannel : public nsBaseChannel,
|
||||
public nsIFTPChannel,
|
||||
public nsIUploadChannel,
|
||||
public nsIResumableChannel,
|
||||
public nsIProxiedChannel
|
||||
public nsIProxiedChannel,
|
||||
public nsIForcePendingChannel
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -88,8 +90,8 @@ public:
|
||||
// Helper function for getting the nsIFTPEventSink.
|
||||
void GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult);
|
||||
|
||||
public: /* Internal Necko use only. */
|
||||
void ForcePending(bool aForcePending);
|
||||
public:
|
||||
NS_IMETHOD ForcePending(bool aForcePending);
|
||||
|
||||
protected:
|
||||
virtual ~nsFtpChannel() {}
|
||||
|
@ -164,6 +164,7 @@ NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIForcePendingChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRedirectHistory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
|
||||
@ -1638,6 +1639,18 @@ HttpBaseChannel::ForcePending(bool aForcePending)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetLastModifiedTime(PRTime* lastModifiedTime)
|
||||
{
|
||||
if (!mResponseHead)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
uint32_t lastMod;
|
||||
mResponseHead->GetLastModifiedValue(&lastMod);
|
||||
*lastModifiedTime = lastMod;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpBaseChannel::nsISupportsPriority
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIForcePendingChannel.h"
|
||||
#include "nsIRedirectHistory.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
@ -63,6 +64,7 @@ class HttpBaseChannel : public nsHashPropertyBag
|
||||
, public nsITraceableChannel
|
||||
, public PrivateBrowsingChannel<HttpBaseChannel>
|
||||
, public nsITimedChannel
|
||||
, public nsIForcePendingChannel
|
||||
{
|
||||
protected:
|
||||
virtual ~HttpBaseChannel();
|
||||
@ -173,6 +175,7 @@ public:
|
||||
NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable);
|
||||
NS_IMETHOD AddRedirect(nsIPrincipal *aRedirect);
|
||||
NS_IMETHOD ForcePending(bool aForcePending);
|
||||
NS_IMETHOD GetLastModifiedTime(PRTime* lastModifiedTime);
|
||||
|
||||
inline void CleanRedirectCacheChainIfNecessary()
|
||||
{
|
||||
|
@ -200,10 +200,5 @@ interface nsIHttpChannelInternal : nsISupports
|
||||
*/
|
||||
void addRedirect(in nsIPrincipal aPrincipal);
|
||||
|
||||
/**
|
||||
* ForcePending(true) overrides the normal behavior for the
|
||||
* channel's IsPending(), forcing 'true' to be returned. A call to
|
||||
* ForcePending(false) reverts IsPending() back to normal behavior.
|
||||
*/
|
||||
void ForcePending(in boolean aForcePending);
|
||||
readonly attribute PRTime lastModifiedTime;
|
||||
};
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "nsIViewSourceChannel.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIForcePendingChannel.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
@ -204,9 +204,9 @@ nsUnknownDecoder::OnStopRequest(nsIRequest* request, nsISupports *aCtxt,
|
||||
// Make sure channel listeners see channel as pending while we call
|
||||
// OnStartRequest/OnDataAvailable, even though the underlying channel
|
||||
// has already hit OnStopRequest.
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(request);
|
||||
if (httpChannel) {
|
||||
httpChannel->ForcePending(true);
|
||||
nsCOMPtr<nsIForcePendingChannel> forcePendingChannel = do_QueryInterface(request);
|
||||
if (forcePendingChannel) {
|
||||
forcePendingChannel->ForcePending(true);
|
||||
}
|
||||
|
||||
rv = FireListenerNotifications(request, aCtxt);
|
||||
@ -216,8 +216,8 @@ nsUnknownDecoder::OnStopRequest(nsIRequest* request, nsISupports *aCtxt,
|
||||
}
|
||||
|
||||
// now we need to set pending state to false before calling OnStopRequest
|
||||
if (httpChannel) {
|
||||
httpChannel->ForcePending(false);
|
||||
if (forcePendingChannel) {
|
||||
forcePendingChannel->ForcePending(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user