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