|
Packit |
f0b94e |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
Packit |
f0b94e |
/* vim: set sw=2 ts=8 et tw=80 : */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "mozilla/net/NeckoChild.h"
|
|
Packit |
f0b94e |
#include "mozilla/net/ChannelDiverterChild.h"
|
|
Packit |
f0b94e |
#include "mozilla/net/FTPChannelChild.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/ContentChild.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/DocGroup.h"
|
|
Packit |
f0b94e |
#include "mozilla/dom/TabChild.h"
|
|
Packit |
f0b94e |
#include "nsContentUtils.h"
|
|
Packit |
f0b94e |
#include "nsFtpProtocolHandler.h"
|
|
Packit |
f0b94e |
#include "nsITabChild.h"
|
|
Packit |
f0b94e |
#include "nsStringStream.h"
|
|
Packit |
f0b94e |
#include "nsNetUtil.h"
|
|
Packit |
f0b94e |
#include "base/compiler_specific.h"
|
|
Packit |
f0b94e |
#include "mozilla/ipc/IPCStreamUtils.h"
|
|
Packit |
f0b94e |
#include "mozilla/ipc/URIUtils.h"
|
|
Packit |
f0b94e |
#include "SerializedLoadContext.h"
|
|
Packit |
f0b94e |
#include "mozilla/ipc/BackgroundUtils.h"
|
|
Packit |
f0b94e |
#include "nsIPrompt.h"
|
|
Packit |
f0b94e |
#include "nsIURIMutator.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
using mozilla::dom::ContentChild;
|
|
Packit |
f0b94e |
using namespace mozilla::ipc;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#undef LOG
|
|
Packit |
f0b94e |
#define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace mozilla {
|
|
Packit |
f0b94e |
namespace net {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
FTPChannelChild::FTPChannelChild(nsIURI* uri)
|
|
Packit |
f0b94e |
: mIPCOpen(false),
|
|
Packit |
f0b94e |
mUnknownDecoderInvolved(false),
|
|
Packit |
f0b94e |
mCanceled(false),
|
|
Packit |
f0b94e |
mSuspendCount(0),
|
|
Packit |
f0b94e |
mIsPending(false),
|
|
Packit |
f0b94e |
mLastModifiedTime(0),
|
|
Packit |
f0b94e |
mStartPos(0),
|
|
Packit |
f0b94e |
mDivertingToParent(false),
|
|
Packit |
f0b94e |
mFlushedForDiversion(false),
|
|
Packit |
f0b94e |
mSuspendSent(false) {
|
|
Packit |
f0b94e |
LOG(("Creating FTPChannelChild @%p\n", this));
|
|
Packit |
f0b94e |
// grab a reference to the handler to ensure that it doesn't go away.
|
|
Packit |
f0b94e |
NS_ADDREF(gFtpHandler);
|
|
Packit |
f0b94e |
SetURI(uri);
|
|
Packit |
f0b94e |
mEventQ = new ChannelEventQueue(static_cast<nsIFTPChannel*>(this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// We could support thread retargeting, but as long as we're being driven by
|
|
Packit |
f0b94e |
// IPDL on the main thread it doesn't buy us anything.
|
|
Packit |
f0b94e |
DisallowThreadRetargeting();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
FTPChannelChild::~FTPChannelChild() {
|
|
Packit |
f0b94e |
LOG(("Destroying FTPChannelChild @%p\n", this));
|
|
Packit |
f0b94e |
gFtpHandler->Release();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::AddIPDLReference() {
|
|
Packit |
f0b94e |
MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
|
|
Packit |
f0b94e |
mIPCOpen = true;
|
|
Packit |
f0b94e |
AddRef();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::ReleaseIPDLReference() {
|
|
Packit |
f0b94e |
MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
|
|
Packit |
f0b94e |
mIPCOpen = false;
|
|
Packit |
f0b94e |
Release();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
// FTPChannelChild::nsISupports
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMPL_ISUPPORTS_INHERITED(FTPChannelChild, nsBaseChannel, nsIFTPChannel,
|
|
Packit |
f0b94e |
nsIUploadChannel, nsIResumableChannel,
|
|
Packit |
f0b94e |
nsIProxiedChannel, nsIChildChannel,
|
|
Packit |
f0b94e |
nsIDivertableChannel)
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::GetLastModifiedTime(PRTime* lastModifiedTime) {
|
|
Packit |
f0b94e |
*lastModifiedTime = mLastModifiedTime;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::SetLastModifiedTime(PRTime lastModifiedTime) {
|
|
Packit |
f0b94e |
return NS_ERROR_NOT_AVAILABLE;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
|
Packit |
f0b94e |
mStartPos = aStartPos;
|
|
Packit |
f0b94e |
mEntityID = aEntityID;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::GetEntityID(nsACString& entityID) {
|
|
Packit |
f0b94e |
entityID = mEntityID;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::GetProxyInfo(nsIProxyInfo** aProxyInfo) { DROP_DEAD(); }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::SetUploadStream(nsIInputStream* stream,
|
|
Packit |
f0b94e |
const nsACString& contentType,
|
|
Packit |
f0b94e |
int64_t contentLength) {
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
|
Packit |
f0b94e |
mUploadStream = stream;
|
|
Packit |
f0b94e |
// NOTE: contentLength is intentionally ignored here.
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::GetUploadStream(nsIInputStream** stream) {
|
|
Packit |
f0b94e |
NS_ENSURE_ARG_POINTER(stream);
|
|
Packit |
f0b94e |
*stream = mUploadStream;
|
|
Packit |
f0b94e |
NS_IF_ADDREF(*stream);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::AsyncOpen(::nsIStreamListener* listener,
|
|
Packit |
f0b94e |
nsISupports* aContext) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::AsyncOpen [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(
|
|
Packit |
f0b94e |
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
|
|
Packit |
f0b94e |
NS_ERROR_FAILURE);
|
|
Packit |
f0b94e |
NS_ENSURE_ARG_POINTER(listener);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Port checked in parent, but duplicate here so we can return with error
|
|
Packit |
f0b94e |
// immediately, as we've done since before e10s.
|
|
Packit |
f0b94e |
nsresult rv;
|
|
Packit |
f0b94e |
rv = NS_CheckPortSafety(nsBaseChannel::URI()); // Need to disambiguate,
|
|
Packit |
f0b94e |
// because in the child ipdl,
|
|
Packit |
f0b94e |
// a typedef URI is defined...
|
|
Packit |
f0b94e |
if (NS_FAILED(rv)) return rv;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::dom::TabChild* tabChild = nullptr;
|
|
Packit |
f0b94e |
nsCOMPtr<nsITabChild> iTabChild;
|
|
Packit |
f0b94e |
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsITabChild),
|
|
Packit |
f0b94e |
getter_AddRefs(iTabChild));
|
|
Packit |
f0b94e |
GetCallback(iTabChild);
|
|
Packit |
f0b94e |
if (iTabChild) {
|
|
Packit |
f0b94e |
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
if (MissingRequiredTabChild(tabChild, "ftp")) {
|
|
Packit |
f0b94e |
return NS_ERROR_ILLEGAL_VALUE;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mListener = listener;
|
|
Packit |
f0b94e |
mListenerContext = aContext;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// add ourselves to the load group.
|
|
Packit |
f0b94e |
if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::AutoIPCStream autoStream;
|
|
Packit |
f0b94e |
autoStream.Serialize(mUploadStream,
|
|
Packit |
f0b94e |
static_cast<ContentChild*>(gNeckoChild->Manager()));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
FTPChannelOpenArgs openArgs;
|
|
Packit |
f0b94e |
SerializeURI(nsBaseChannel::URI(), openArgs.uri());
|
|
Packit |
f0b94e |
openArgs.startPos() = mStartPos;
|
|
Packit |
f0b94e |
openArgs.entityID() = mEntityID;
|
|
Packit |
f0b94e |
openArgs.uploadStream() = autoStream.TakeOptionalValue();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<nsILoadInfo> loadInfo;
|
|
Packit |
f0b94e |
GetLoadInfo(getter_AddRefs(loadInfo));
|
|
Packit |
f0b94e |
rv = mozilla::ipc::LoadInfoToLoadInfoArgs(loadInfo, &openArgs.loadInfo());
|
|
Packit |
f0b94e |
NS_ENSURE_SUCCESS(rv, rv);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// This must happen before the constructor message is sent.
|
|
Packit |
f0b94e |
SetupNeckoTarget();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
gNeckoChild->SendPFTPChannelConstructor(
|
|
Packit |
f0b94e |
this, tabChild, IPC::SerializedLoadContext(this), openArgs);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// The socket transport layer in the chrome process now has a logical ref to
|
|
Packit |
f0b94e |
// us until OnStopRequest is called.
|
|
Packit |
f0b94e |
AddIPDLReference();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mIsPending = true;
|
|
Packit |
f0b94e |
mWasOpened = true;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return rv;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::IsPending(bool* result) {
|
|
Packit |
f0b94e |
*result = mIsPending;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsresult FTPChannelChild::OpenContentStream(bool async, nsIInputStream** stream,
|
|
Packit |
f0b94e |
nsIChannel** channel) {
|
|
Packit |
f0b94e |
MOZ_CRASH("FTPChannel*Child* should never have OpenContentStream called!");
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
// FTPChannelChild::PFTPChannelChild
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class FTPStartRequestEvent : public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
FTPStartRequestEvent(FTPChannelChild* aChild, const nsresult& aChannelStatus,
|
|
Packit |
f0b94e |
const int64_t& aContentLength,
|
|
Packit |
f0b94e |
const nsCString& aContentType,
|
|
Packit |
f0b94e |
const PRTime& aLastModified, const nsCString& aEntityID,
|
|
Packit |
f0b94e |
const URIParams& aURI)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(aChild),
|
|
Packit |
f0b94e |
mChannelStatus(aChannelStatus),
|
|
Packit |
f0b94e |
mContentLength(aContentLength),
|
|
Packit |
f0b94e |
mContentType(aContentType),
|
|
Packit |
f0b94e |
mLastModified(aLastModified),
|
|
Packit |
f0b94e |
mEntityID(aEntityID),
|
|
Packit |
f0b94e |
mURI(aURI) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override {
|
|
Packit |
f0b94e |
mChild->DoOnStartRequest(mChannelStatus, mContentLength, mContentType,
|
|
Packit |
f0b94e |
mLastModified, mEntityID, mURI);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsresult mChannelStatus;
|
|
Packit |
f0b94e |
int64_t mContentLength;
|
|
Packit |
f0b94e |
nsCString mContentType;
|
|
Packit |
f0b94e |
PRTime mLastModified;
|
|
Packit |
f0b94e |
nsCString mEntityID;
|
|
Packit |
f0b94e |
URIParams mURI;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvOnStartRequest(
|
|
Packit |
f0b94e |
const nsresult& aChannelStatus, const int64_t& aContentLength,
|
|
Packit |
f0b94e |
const nsCString& aContentType, const PRTime& aLastModified,
|
|
Packit |
f0b94e |
const nsCString& aEntityID, const URIParams& aURI) {
|
|
Packit |
f0b94e |
// mFlushedForDiversion and mDivertingToParent should NEVER be set at this
|
|
Packit |
f0b94e |
// stage, as they are set in the listener's OnStartRequest.
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(
|
|
Packit |
f0b94e |
!mFlushedForDiversion,
|
|
Packit |
f0b94e |
"mFlushedForDiversion should be unset before OnStartRequest!");
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(
|
|
Packit |
f0b94e |
!mDivertingToParent,
|
|
Packit |
f0b94e |
"mDivertingToParent should be unset before OnStartRequest!");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::RecvOnStartRequest [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mEventQ->RunOrEnqueue(
|
|
Packit |
f0b94e |
new FTPStartRequestEvent(this, aChannelStatus, aContentLength,
|
|
Packit |
f0b94e |
aContentType, aLastModified, aEntityID, aURI));
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::DoOnStartRequest(const nsresult& aChannelStatus,
|
|
Packit |
f0b94e |
const int64_t& aContentLength,
|
|
Packit |
f0b94e |
const nsCString& aContentType,
|
|
Packit |
f0b94e |
const PRTime& aLastModified,
|
|
Packit |
f0b94e |
const nsCString& aEntityID,
|
|
Packit |
f0b94e |
const URIParams& aURI) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::DoOnStartRequest [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// mFlushedForDiversion and mDivertingToParent should NEVER be set at this
|
|
Packit |
f0b94e |
// stage, as they are set in the listener's OnStartRequest.
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(
|
|
Packit |
f0b94e |
!mFlushedForDiversion,
|
|
Packit |
f0b94e |
"mFlushedForDiversion should be unset before OnStartRequest!");
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(
|
|
Packit |
f0b94e |
!mDivertingToParent,
|
|
Packit |
f0b94e |
"mDivertingToParent should be unset before OnStartRequest!");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!mCanceled && NS_SUCCEEDED(mStatus)) {
|
|
Packit |
f0b94e |
mStatus = aChannelStatus;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mContentLength = aContentLength;
|
|
Packit |
f0b94e |
SetContentType(aContentType);
|
|
Packit |
f0b94e |
mLastModifiedTime = aLastModified;
|
|
Packit |
f0b94e |
mEntityID = aEntityID;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCString spec;
|
|
Packit |
f0b94e |
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
|
|
Packit |
f0b94e |
nsresult rv = uri->GetSpec(spec);
|
|
Packit |
f0b94e |
if (NS_SUCCEEDED(rv)) {
|
|
Packit |
f0b94e |
// Changes nsBaseChannel::URI()
|
|
Packit |
f0b94e |
rv = NS_MutateURI(mURI).SetSpec(spec).Finalize(mURI);
|
|
Packit |
f0b94e |
if (NS_FAILED(rv)) {
|
|
Packit |
f0b94e |
Cancel(rv);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
Cancel(rv);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
|
|
Packit |
f0b94e |
rv = mListener->OnStartRequest(this, mListenerContext);
|
|
Packit |
f0b94e |
if (NS_FAILED(rv)) Cancel(rv);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mDivertingToParent) {
|
|
Packit |
f0b94e |
mListener = nullptr;
|
|
Packit |
f0b94e |
mListenerContext = nullptr;
|
|
Packit |
f0b94e |
if (mLoadGroup) {
|
|
Packit |
f0b94e |
mLoadGroup->RemoveRequest(this, nullptr, mStatus);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class FTPDataAvailableEvent : public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
FTPDataAvailableEvent(FTPChannelChild* aChild, const nsresult& aChannelStatus,
|
|
Packit |
f0b94e |
const nsCString& aData, const uint64_t& aOffset,
|
|
Packit |
f0b94e |
const uint32_t& aCount)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(aChild),
|
|
Packit |
f0b94e |
mChannelStatus(aChannelStatus),
|
|
Packit |
f0b94e |
mData(aData),
|
|
Packit |
f0b94e |
mOffset(aOffset),
|
|
Packit |
f0b94e |
mCount(aCount) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override {
|
|
Packit |
f0b94e |
mChild->DoOnDataAvailable(mChannelStatus, mData, mOffset, mCount);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsresult mChannelStatus;
|
|
Packit |
f0b94e |
nsCString mData;
|
|
Packit |
f0b94e |
uint64_t mOffset;
|
|
Packit |
f0b94e |
uint32_t mCount;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvOnDataAvailable(
|
|
Packit |
f0b94e |
const nsresult& channelStatus, const nsCString& data,
|
|
Packit |
f0b94e |
const uint64_t& offset, const uint32_t& count) {
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
|
|
Packit |
f0b94e |
"Should not be receiving any more callbacks from parent!");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::RecvOnDataAvailable [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mEventQ->RunOrEnqueue(
|
|
Packit |
f0b94e |
new FTPDataAvailableEvent(this, channelStatus, data, offset, count),
|
|
Packit |
f0b94e |
mDivertingToParent);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class MaybeDivertOnDataFTPEvent
|
|
Packit |
f0b94e |
: public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
MaybeDivertOnDataFTPEvent(FTPChannelChild* child, const nsCString& data,
|
|
Packit |
f0b94e |
const uint64_t& offset, const uint32_t& count)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(child),
|
|
Packit |
f0b94e |
mData(data),
|
|
Packit |
f0b94e |
mOffset(offset),
|
|
Packit |
f0b94e |
mCount(count) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override { mChild->MaybeDivertOnData(mData, mOffset, mCount); }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsCString mData;
|
|
Packit |
f0b94e |
uint64_t mOffset;
|
|
Packit |
f0b94e |
uint32_t mCount;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::MaybeDivertOnData(const nsCString& data,
|
|
Packit |
f0b94e |
const uint64_t& offset,
|
|
Packit |
f0b94e |
const uint32_t& count) {
|
|
Packit |
f0b94e |
if (mDivertingToParent) {
|
|
Packit |
f0b94e |
SendDivertOnDataAvailable(data, offset, count);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::DoOnDataAvailable(const nsresult& channelStatus,
|
|
Packit |
f0b94e |
const nsCString& data,
|
|
Packit |
f0b94e |
const uint64_t& offset,
|
|
Packit |
f0b94e |
const uint32_t& count) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::DoOnDataAvailable [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!mCanceled && NS_SUCCEEDED(mStatus)) {
|
|
Packit |
f0b94e |
mStatus = channelStatus;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mDivertingToParent) {
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(
|
|
Packit |
f0b94e |
!mFlushedForDiversion,
|
|
Packit |
f0b94e |
"Should not be processing any more callbacks from parent!");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
SendDivertOnDataAvailable(data, offset, count);
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mCanceled) return;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mUnknownDecoderInvolved) {
|
|
Packit |
f0b94e |
mUnknownDecoderEventQ.AppendElement(
|
|
Packit |
f0b94e |
MakeUnique<MaybeDivertOnDataFTPEvent>(this, data, offset, count));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// NOTE: the OnDataAvailable contract requires the client to read all the data
|
|
Packit |
f0b94e |
// in the inputstream. This code relies on that ('data' will go away after
|
|
Packit |
f0b94e |
// this function). Apparently the previous, non-e10s behavior was to actually
|
|
Packit |
f0b94e |
// support only reading part of the data, allowing later calls to read the
|
|
Packit |
f0b94e |
// rest.
|
|
Packit |
f0b94e |
nsCOMPtr<nsIInputStream> stringStream;
|
|
Packit |
f0b94e |
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
|
|
Packit |
f0b94e |
count, NS_ASSIGNMENT_DEPEND);
|
|
Packit |
f0b94e |
if (NS_FAILED(rv)) {
|
|
Packit |
f0b94e |
Cancel(rv);
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
|
|
Packit |
f0b94e |
rv = mListener->OnDataAvailable(this, mListenerContext, stringStream, offset,
|
|
Packit |
f0b94e |
count);
|
|
Packit |
f0b94e |
if (NS_FAILED(rv)) Cancel(rv);
|
|
Packit |
f0b94e |
stringStream->Close();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class FTPStopRequestEvent : public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
FTPStopRequestEvent(FTPChannelChild* aChild, const nsresult& aChannelStatus,
|
|
Packit |
f0b94e |
const nsCString& aErrorMsg, bool aUseUTF8)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(aChild),
|
|
Packit |
f0b94e |
mChannelStatus(aChannelStatus),
|
|
Packit |
f0b94e |
mErrorMsg(aErrorMsg),
|
|
Packit |
f0b94e |
mUseUTF8(aUseUTF8) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override {
|
|
Packit |
f0b94e |
mChild->DoOnStopRequest(mChannelStatus, mErrorMsg, mUseUTF8);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsresult mChannelStatus;
|
|
Packit |
f0b94e |
nsCString mErrorMsg;
|
|
Packit |
f0b94e |
bool mUseUTF8;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvOnStopRequest(
|
|
Packit |
f0b94e |
const nsresult& aChannelStatus, const nsCString& aErrorMsg,
|
|
Packit |
f0b94e |
const bool& aUseUTF8) {
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
|
|
Packit |
f0b94e |
"Should not be receiving any more callbacks from parent!");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::RecvOnStopRequest [this=%p status=%" PRIx32 "]\n",
|
|
Packit |
f0b94e |
this, static_cast<uint32_t>(aChannelStatus)));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mEventQ->RunOrEnqueue(
|
|
Packit |
f0b94e |
new FTPStopRequestEvent(this, aChannelStatus, aErrorMsg, aUseUTF8));
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class nsFtpChildAsyncAlert : public Runnable {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
nsFtpChildAsyncAlert(nsIPrompt* aPrompter, nsString aResponseMsg)
|
|
Packit |
f0b94e |
: Runnable("nsFtpChildAsyncAlert"),
|
|
Packit |
f0b94e |
mPrompter(aPrompter),
|
|
Packit |
f0b94e |
mResponseMsg(aResponseMsg) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
protected:
|
|
Packit |
f0b94e |
virtual ~nsFtpChildAsyncAlert() {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
NS_IMETHOD Run() override {
|
|
Packit |
f0b94e |
if (mPrompter) {
|
|
Packit |
f0b94e |
mPrompter->Alert(nullptr, mResponseMsg.get());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsCOMPtr<nsIPrompt> mPrompter;
|
|
Packit |
f0b94e |
nsString mResponseMsg;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class MaybeDivertOnStopFTPEvent
|
|
Packit |
f0b94e |
: public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
MaybeDivertOnStopFTPEvent(FTPChannelChild* child,
|
|
Packit |
f0b94e |
const nsresult& aChannelStatus)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(child),
|
|
Packit |
f0b94e |
mChannelStatus(aChannelStatus) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override { mChild->MaybeDivertOnStop(mChannelStatus); }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsresult mChannelStatus;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus) {
|
|
Packit |
f0b94e |
if (mDivertingToParent) {
|
|
Packit |
f0b94e |
SendDivertOnStopRequest(aChannelStatus);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::DoOnStopRequest(const nsresult& aChannelStatus,
|
|
Packit |
f0b94e |
const nsCString& aErrorMsg,
|
|
Packit |
f0b94e |
bool aUseUTF8) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::DoOnStopRequest [this=%p status=%" PRIx32 "]\n", this,
|
|
Packit |
f0b94e |
static_cast<uint32_t>(aChannelStatus)));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mDivertingToParent) {
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(
|
|
Packit |
f0b94e |
!mFlushedForDiversion,
|
|
Packit |
f0b94e |
"Should not be processing any more callbacks from parent!");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
SendDivertOnStopRequest(aChannelStatus);
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!mCanceled) mStatus = aChannelStatus;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mUnknownDecoderInvolved) {
|
|
Packit |
f0b94e |
mUnknownDecoderEventQ.AppendElement(
|
|
Packit |
f0b94e |
MakeUnique<MaybeDivertOnStopFTPEvent>(this, aChannelStatus));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
{ // Ensure that all queued ipdl events are dispatched before
|
|
Packit |
f0b94e |
// we initiate protocol deletion below.
|
|
Packit |
f0b94e |
mIsPending = false;
|
|
Packit |
f0b94e |
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
|
|
Packit |
f0b94e |
(void)mListener->OnStopRequest(this, mListenerContext, aChannelStatus);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (NS_FAILED(aChannelStatus) && !aErrorMsg.IsEmpty()) {
|
|
Packit |
f0b94e |
nsCOMPtr<nsIPrompt> prompter;
|
|
Packit |
f0b94e |
GetCallback(prompter);
|
|
Packit |
f0b94e |
if (prompter) {
|
|
Packit |
f0b94e |
nsCOMPtr<nsIRunnable> alertEvent;
|
|
Packit |
f0b94e |
if (aUseUTF8) {
|
|
Packit |
f0b94e |
alertEvent = new nsFtpChildAsyncAlert(
|
|
Packit |
f0b94e |
prompter, NS_ConvertUTF8toUTF16(aErrorMsg));
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
alertEvent = new nsFtpChildAsyncAlert(
|
|
Packit |
f0b94e |
prompter, NS_ConvertASCIItoUTF16(aErrorMsg));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
Dispatch(alertEvent.forget());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mListener = nullptr;
|
|
Packit |
f0b94e |
mListenerContext = nullptr;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// This calls NeckoChild::DeallocPFTPChannelChild(), which deletes |this| if
|
|
Packit |
f0b94e |
// IPDL holds the last reference. Don't rely on |this| existing after here!
|
|
Packit |
f0b94e |
Send__delete__(this);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class FTPFailedAsyncOpenEvent
|
|
Packit |
f0b94e |
: public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
FTPFailedAsyncOpenEvent(FTPChannelChild* aChild, nsresult aStatus)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(aChild), mStatus(aStatus) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override { mChild->DoFailedAsyncOpen(mStatus); }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
private:
|
|
Packit |
f0b94e |
nsresult mStatus;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvFailedAsyncOpen(
|
|
Packit |
f0b94e |
const nsresult& statusCode) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::RecvFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
|
|
Packit |
f0b94e |
this, static_cast<uint32_t>(statusCode)));
|
|
Packit |
f0b94e |
mEventQ->RunOrEnqueue(new FTPFailedAsyncOpenEvent(this, statusCode));
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::DoFailedAsyncOpen(const nsresult& statusCode) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::DoFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
|
|
Packit |
f0b94e |
this, static_cast<uint32_t>(statusCode)));
|
|
Packit |
f0b94e |
mStatus = statusCode;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, statusCode);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mListener) {
|
|
Packit |
f0b94e |
mListener->OnStartRequest(this, mListenerContext);
|
|
Packit |
f0b94e |
mIsPending = false;
|
|
Packit |
f0b94e |
mListener->OnStopRequest(this, mListenerContext, statusCode);
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
mIsPending = false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mListener = nullptr;
|
|
Packit |
f0b94e |
mListenerContext = nullptr;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mIPCOpen) Send__delete__(this);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class FTPFlushedForDiversionEvent
|
|
Packit |
f0b94e |
: public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
explicit FTPFlushedForDiversionEvent(FTPChannelChild* aChild)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(aChild) {
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(aChild);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void Run() override { mChild->FlushedForDiversion(); }
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvFlushedForDiversion() {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
|
|
Packit |
f0b94e |
MOZ_ASSERT(mDivertingToParent);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mEventQ->RunOrEnqueue(new FTPFlushedForDiversionEvent(this), true);
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::FlushedForDiversion() {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::FlushedForDiversion [this=%p]\n", this));
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(mDivertingToParent);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Once this is set, it should not be unset before FTPChannelChild is taken
|
|
Packit |
f0b94e |
// down. After it is set, no OnStart/OnData/OnStop callbacks should be
|
|
Packit |
f0b94e |
// received from the parent channel, nor dequeued from the ChannelEventQueue.
|
|
Packit |
f0b94e |
mFlushedForDiversion = true;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
SendDivertComplete();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvDivertMessages() {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::RecvDivertMessages [this=%p]\n", this));
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(mDivertingToParent);
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(mSuspendCount > 0);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// DivertTo() has been called on parent, so we can now start sending queued
|
|
Packit |
f0b94e |
// IPDL messages back to parent listener.
|
|
Packit |
f0b94e |
if (NS_WARN_IF(NS_FAILED(Resume()))) {
|
|
Packit |
f0b94e |
return IPC_FAIL_NO_REASON(this);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class FTPDeleteSelfEvent : public NeckoTargetChannelEvent<FTPChannelChild> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
explicit FTPDeleteSelfEvent(FTPChannelChild* aChild)
|
|
Packit |
f0b94e |
: NeckoTargetChannelEvent<FTPChannelChild>(aChild) {}
|
|
Packit |
f0b94e |
void Run() override { mChild->DoDeleteSelf(); }
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::ipc::IPCResult FTPChannelChild::RecvDeleteSelf() {
|
|
Packit |
f0b94e |
mEventQ->RunOrEnqueue(new FTPDeleteSelfEvent(this));
|
|
Packit |
f0b94e |
return IPC_OK();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::DoDeleteSelf() {
|
|
Packit |
f0b94e |
if (mIPCOpen) Send__delete__(this);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::Cancel(nsresult status) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::Cancel [this=%p]\n", this));
|
|
Packit |
f0b94e |
if (mCanceled) return NS_OK;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mCanceled = true;
|
|
Packit |
f0b94e |
mStatus = status;
|
|
Packit |
f0b94e |
if (mIPCOpen) SendCancel(status);
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::Suspend() {
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::Suspend [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// SendSuspend only once, when suspend goes from 0 to 1.
|
|
Packit |
f0b94e |
// Don't SendSuspend at all if we're diverting callbacks to the parent;
|
|
Packit |
f0b94e |
// suspend will be called at the correct time in the parent itself.
|
|
Packit |
f0b94e |
if (!mSuspendCount++ && !mDivertingToParent) {
|
|
Packit |
f0b94e |
SendSuspend();
|
|
Packit |
f0b94e |
mSuspendSent = true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
mEventQ->Suspend();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::Resume() {
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::Resume [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// SendResume only once, when suspend count drops to 0.
|
|
Packit |
f0b94e |
// Don't SendResume at all if we're diverting callbacks to the parent (unless
|
|
Packit |
f0b94e |
// suspend was sent earlier); otherwise, resume will be called at the correct
|
|
Packit |
f0b94e |
// time in the parent itself.
|
|
Packit |
f0b94e |
if (!--mSuspendCount && (!mDivertingToParent || mSuspendSent)) {
|
|
Packit |
f0b94e |
SendResume();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
mEventQ->Resume();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
// FTPChannelChild::nsIChildChannel
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::ConnectParent(uint32_t id) {
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(
|
|
Packit |
f0b94e |
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
|
|
Packit |
f0b94e |
NS_ERROR_FAILURE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::ConnectParent [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mozilla::dom::TabChild* tabChild = nullptr;
|
|
Packit |
f0b94e |
nsCOMPtr<nsITabChild> iTabChild;
|
|
Packit |
f0b94e |
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsITabChild),
|
|
Packit |
f0b94e |
getter_AddRefs(iTabChild));
|
|
Packit |
f0b94e |
GetCallback(iTabChild);
|
|
Packit |
f0b94e |
if (iTabChild) {
|
|
Packit |
f0b94e |
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// This must happen before the constructor message is sent.
|
|
Packit |
f0b94e |
SetupNeckoTarget();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// The socket transport in the chrome process now holds a logical ref to us
|
|
Packit |
f0b94e |
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
|
|
Packit |
f0b94e |
AddIPDLReference();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
FTPChannelConnectArgs connectArgs(id);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!gNeckoChild->SendPFTPChannelConstructor(
|
|
Packit |
f0b94e |
this, tabChild, IPC::SerializedLoadContext(this), connectArgs)) {
|
|
Packit |
f0b94e |
return NS_ERROR_FAILURE;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::CompleteRedirectSetup(nsIStreamListener* listener,
|
|
Packit |
f0b94e |
nsISupports* aContext) {
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::CompleteRedirectSetup [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mIsPending = true;
|
|
Packit |
f0b94e |
mWasOpened = true;
|
|
Packit |
f0b94e |
mListener = listener;
|
|
Packit |
f0b94e |
mListenerContext = aContext;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// add ourselves to the load group.
|
|
Packit |
f0b94e |
if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// We already have an open IPDL connection to the parent. If on-modify-request
|
|
Packit |
f0b94e |
// listeners or load group observers canceled us, let the parent handle it
|
|
Packit |
f0b94e |
// and send it back to us naturally.
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
// FTPChannelChild::nsIDivertableChannel
|
|
Packit |
f0b94e |
//-----------------------------------------------------------------------------
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::DivertToParent(ChannelDiverterChild** aChild) {
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(aChild);
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(gNeckoChild);
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(!mDivertingToParent);
|
|
Packit |
f0b94e |
NS_ENSURE_TRUE(
|
|
Packit |
f0b94e |
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
|
|
Packit |
f0b94e |
NS_ERROR_FAILURE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
LOG(("FTPChannelChild::DivertToParent [this=%p]\n", this));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// We must fail DivertToParent() if there's no parent end of the channel (and
|
|
Packit |
f0b94e |
// won't be!) due to early failure.
|
|
Packit |
f0b94e |
if (NS_FAILED(mStatus) && !mIPCOpen) {
|
|
Packit |
f0b94e |
return mStatus;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsresult rv = Suspend();
|
|
Packit |
f0b94e |
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
Packit |
f0b94e |
return rv;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Once this is set, it should not be unset before the child is taken down.
|
|
Packit |
f0b94e |
mDivertingToParent = true;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
PChannelDiverterChild* diverter =
|
|
Packit |
f0b94e |
gNeckoChild->SendPChannelDiverterConstructor(this);
|
|
Packit |
f0b94e |
MOZ_RELEASE_ASSERT(diverter);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
*aChild = static_cast<ChannelDiverterChild*>(diverter);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::UnknownDecoderInvolvedKeepData() {
|
|
Packit |
f0b94e |
mUnknownDecoderInvolved = true;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::UnknownDecoderInvolvedOnStartRequestCalled() {
|
|
Packit |
f0b94e |
mUnknownDecoderInvolved = false;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsresult rv = NS_OK;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (mDivertingToParent) {
|
|
Packit |
f0b94e |
rv = mEventQ->PrependEvents(mUnknownDecoderEventQ);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
mUnknownDecoderEventQ.Clear();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return rv;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
NS_IMETHODIMP
|
|
Packit |
f0b94e |
FTPChannelChild::GetDivertingToParent(bool* aDiverting) {
|
|
Packit |
f0b94e |
NS_ENSURE_ARG_POINTER(aDiverting);
|
|
Packit |
f0b94e |
*aDiverting = mDivertingToParent;
|
|
Packit |
f0b94e |
return NS_OK;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
void FTPChannelChild::SetupNeckoTarget() {
|
|
Packit |
f0b94e |
if (mNeckoTarget) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsCOMPtr<nsILoadInfo> loadInfo;
|
|
Packit |
f0b94e |
GetLoadInfo(getter_AddRefs(loadInfo));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
mNeckoTarget =
|
|
Packit |
f0b94e |
nsContentUtils::GetEventTargetByLoadInfo(loadInfo, TaskCategory::Network);
|
|
Packit |
f0b94e |
if (!mNeckoTarget) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
gNeckoChild->SetEventTargetForActor(this, mNeckoTarget);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace net
|
|
Packit |
f0b94e |
} // namespace mozilla
|