LCOV - code coverage report
Current view: top level - netwerk/protocol/ftp - FTPChannelChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 414 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 79 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set sw=2 ts=8 et tw=80 : */
       3             : 
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : #include "mozilla/net/NeckoChild.h"
       9             : #include "mozilla/net/ChannelDiverterChild.h"
      10             : #include "mozilla/net/FTPChannelChild.h"
      11             : #include "mozilla/dom/ContentChild.h"
      12             : #include "mozilla/dom/DocGroup.h"
      13             : #include "mozilla/dom/TabChild.h"
      14             : #include "nsContentUtils.h"
      15             : #include "nsFtpProtocolHandler.h"
      16             : #include "nsITabChild.h"
      17             : #include "nsStringStream.h"
      18             : #include "nsNetUtil.h"
      19             : #include "base/compiler_specific.h"
      20             : #include "mozilla/ipc/IPCStreamUtils.h"
      21             : #include "mozilla/ipc/URIUtils.h"
      22             : #include "SerializedLoadContext.h"
      23             : #include "mozilla/ipc/BackgroundUtils.h"
      24             : #include "nsIPrompt.h"
      25             : 
      26             : using mozilla::dom::ContentChild;
      27             : using namespace mozilla::ipc;
      28             : 
      29             : #undef LOG
      30             : #define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
      31             : 
      32             : namespace mozilla {
      33             : namespace net {
      34             : 
      35           0 : FTPChannelChild::FTPChannelChild(nsIURI* uri)
      36             : : mIPCOpen(false)
      37             : , mUnknownDecoderInvolved(false)
      38             : , mCanceled(false)
      39             : , mSuspendCount(0)
      40             : , mIsPending(false)
      41             : , mLastModifiedTime(0)
      42             : , mStartPos(0)
      43             : , mDivertingToParent(false)
      44             : , mFlushedForDiversion(false)
      45           0 : , mSuspendSent(false)
      46             : {
      47           0 :   LOG(("Creating FTPChannelChild @%p\n", this));
      48             :   // grab a reference to the handler to ensure that it doesn't go away.
      49           0 :   NS_ADDREF(gFtpHandler);
      50           0 :   SetURI(uri);
      51           0 :   mEventQ = new ChannelEventQueue(static_cast<nsIFTPChannel*>(this));
      52             : 
      53             :   // We could support thread retargeting, but as long as we're being driven by
      54             :   // IPDL on the main thread it doesn't buy us anything.
      55           0 :   DisallowThreadRetargeting();
      56           0 : }
      57             : 
      58           0 : FTPChannelChild::~FTPChannelChild()
      59             : {
      60           0 :   LOG(("Destroying FTPChannelChild @%p\n", this));
      61           0 :   gFtpHandler->Release();
      62           0 : }
      63             : 
      64             : void
      65           0 : FTPChannelChild::AddIPDLReference()
      66             : {
      67           0 :   MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
      68           0 :   mIPCOpen = true;
      69           0 :   AddRef();
      70           0 : }
      71             : 
      72             : void
      73           0 : FTPChannelChild::ReleaseIPDLReference()
      74             : {
      75           0 :   MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
      76           0 :   mIPCOpen = false;
      77           0 :   Release();
      78           0 : }
      79             : 
      80             : //-----------------------------------------------------------------------------
      81             : // FTPChannelChild::nsISupports
      82             : //-----------------------------------------------------------------------------
      83             : 
      84           0 : NS_IMPL_ISUPPORTS_INHERITED(FTPChannelChild,
      85             :                             nsBaseChannel,
      86             :                             nsIFTPChannel,
      87             :                             nsIUploadChannel,
      88             :                             nsIResumableChannel,
      89             :                             nsIProxiedChannel,
      90             :                             nsIChildChannel,
      91             :                             nsIDivertableChannel)
      92             : 
      93             : //-----------------------------------------------------------------------------
      94             : 
      95             : NS_IMETHODIMP
      96           0 : FTPChannelChild::GetLastModifiedTime(PRTime* lastModifiedTime)
      97             : {
      98           0 :   *lastModifiedTime = mLastModifiedTime;
      99           0 :   return NS_OK;
     100             : }
     101             : 
     102             : NS_IMETHODIMP
     103           0 : FTPChannelChild::SetLastModifiedTime(PRTime lastModifiedTime)
     104             : {
     105           0 :   return NS_ERROR_NOT_AVAILABLE;
     106             : }
     107             : 
     108             : NS_IMETHODIMP
     109           0 : FTPChannelChild::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID)
     110             : {
     111           0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     112           0 :   mStartPos = aStartPos;
     113           0 :   mEntityID = aEntityID;
     114           0 :   return NS_OK;
     115             : }
     116             : 
     117             : NS_IMETHODIMP
     118           0 : FTPChannelChild::GetEntityID(nsACString& entityID)
     119             : {
     120           0 :   entityID = mEntityID;
     121           0 :   return NS_OK;
     122             : }
     123             : 
     124             : NS_IMETHODIMP
     125           0 : FTPChannelChild::GetProxyInfo(nsIProxyInfo** aProxyInfo)
     126             : {
     127           0 :   DROP_DEAD();
     128             : }
     129             : 
     130             : NS_IMETHODIMP
     131           0 : FTPChannelChild::SetUploadStream(nsIInputStream* stream,
     132             :                                  const nsACString& contentType,
     133             :                                  int64_t contentLength)
     134             : {
     135           0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     136           0 :   mUploadStream = stream;
     137             :   // NOTE: contentLength is intentionally ignored here.
     138           0 :   return NS_OK;
     139             : }
     140             : 
     141             : NS_IMETHODIMP
     142           0 : FTPChannelChild::GetUploadStream(nsIInputStream** stream)
     143             : {
     144           0 :   NS_ENSURE_ARG_POINTER(stream);
     145           0 :   *stream = mUploadStream;
     146           0 :   NS_IF_ADDREF(*stream);
     147           0 :   return NS_OK;
     148             : }
     149             : 
     150             : NS_IMETHODIMP
     151           0 : FTPChannelChild::AsyncOpen(::nsIStreamListener* listener, nsISupports* aContext)
     152             : {
     153           0 :   LOG(("FTPChannelChild::AsyncOpen [this=%p]\n", this));
     154             : 
     155           0 :   NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
     156           0 :   NS_ENSURE_TRUE(!static_cast<ContentChild*>(gNeckoChild->Manager())->
     157             :                    IsShuttingDown(), NS_ERROR_FAILURE);
     158           0 :   NS_ENSURE_ARG_POINTER(listener);
     159           0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     160           0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
     161             : 
     162             :   // Port checked in parent, but duplicate here so we can return with error
     163             :   // immediately, as we've done since before e10s.
     164             :   nsresult rv;
     165           0 :   rv = NS_CheckPortSafety(nsBaseChannel::URI()); // Need to disambiguate,
     166             :                                                  // because in the child ipdl,
     167             :                                                  // a typedef URI is defined...
     168           0 :   if (NS_FAILED(rv))
     169           0 :     return rv;
     170             : 
     171           0 :   mozilla::dom::TabChild* tabChild = nullptr;
     172           0 :   nsCOMPtr<nsITabChild> iTabChild;
     173           0 :   NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
     174             :                                 NS_GET_IID(nsITabChild),
     175           0 :                                 getter_AddRefs(iTabChild));
     176           0 :   GetCallback(iTabChild);
     177           0 :   if (iTabChild) {
     178           0 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
     179             :   }
     180           0 :   if (MissingRequiredTabChild(tabChild, "ftp")) {
     181           0 :     return NS_ERROR_ILLEGAL_VALUE;
     182             :   }
     183             : 
     184           0 :   mListener = listener;
     185           0 :   mListenerContext = aContext;
     186             : 
     187             :   // add ourselves to the load group.
     188           0 :   if (mLoadGroup)
     189           0 :     mLoadGroup->AddRequest(this, nullptr);
     190             : 
     191           0 :   mozilla::ipc::AutoIPCStream autoStream;
     192           0 :   autoStream.Serialize(mUploadStream,
     193           0 :                        static_cast<ContentChild*>(gNeckoChild->Manager()));
     194             : 
     195           0 :   FTPChannelOpenArgs openArgs;
     196           0 :   SerializeURI(nsBaseChannel::URI(), openArgs.uri());
     197           0 :   openArgs.startPos() = mStartPos;
     198           0 :   openArgs.entityID() = mEntityID;
     199           0 :   openArgs.uploadStream() = autoStream.TakeOptionalValue();
     200             : 
     201           0 :   nsCOMPtr<nsILoadInfo> loadInfo;
     202           0 :   GetLoadInfo(getter_AddRefs(loadInfo));
     203           0 :   rv = mozilla::ipc::LoadInfoToLoadInfoArgs(loadInfo, &openArgs.loadInfo());
     204           0 :   NS_ENSURE_SUCCESS(rv, rv);
     205             : 
     206             :   // This must happen before the constructor message is sent.
     207           0 :   SetupNeckoTarget();
     208             : 
     209             :   gNeckoChild->
     210           0 :     SendPFTPChannelConstructor(this, tabChild, IPC::SerializedLoadContext(this),
     211           0 :                                openArgs);
     212             : 
     213             :   // The socket transport layer in the chrome process now has a logical ref to
     214             :   // us until OnStopRequest is called.
     215           0 :   AddIPDLReference();
     216             : 
     217           0 :   mIsPending = true;
     218           0 :   mWasOpened = true;
     219             : 
     220           0 :   return rv;
     221             : }
     222             : 
     223             : NS_IMETHODIMP
     224           0 : FTPChannelChild::IsPending(bool* result)
     225             : {
     226           0 :   *result = mIsPending;
     227           0 :   return NS_OK;
     228             : }
     229             : 
     230             : nsresult
     231           0 : FTPChannelChild::OpenContentStream(bool async,
     232             :                                    nsIInputStream** stream,
     233             :                                    nsIChannel** channel)
     234             : {
     235           0 :   MOZ_CRASH("FTPChannel*Child* should never have OpenContentStream called!");
     236             :   return NS_OK;
     237             : }
     238             : 
     239             : //-----------------------------------------------------------------------------
     240             : // FTPChannelChild::PFTPChannelChild
     241             : //-----------------------------------------------------------------------------
     242             : 
     243           0 : class FTPStartRequestEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     244             : {
     245             : public:
     246           0 :   FTPStartRequestEvent(FTPChannelChild* aChild,
     247             :                        const nsresult& aChannelStatus,
     248             :                        const int64_t& aContentLength,
     249             :                        const nsCString& aContentType,
     250             :                        const PRTime& aLastModified,
     251             :                        const nsCString& aEntityID,
     252             :                        const URIParams& aURI)
     253           0 :     : NeckoTargetChannelEvent<FTPChannelChild>(aChild)
     254           0 :     , mChannelStatus(aChannelStatus)
     255           0 :     , mContentLength(aContentLength)
     256             :     , mContentType(aContentType)
     257           0 :     , mLastModified(aLastModified)
     258             :     , mEntityID(aEntityID)
     259           0 :     , mURI(aURI)
     260             :   {
     261           0 :   }
     262           0 :   void Run()
     263             :   {
     264           0 :     mChild->DoOnStartRequest(mChannelStatus, mContentLength, mContentType,
     265           0 :                              mLastModified, mEntityID, mURI);
     266           0 :   }
     267             : 
     268             : private:
     269             :   nsresult mChannelStatus;
     270             :   int64_t mContentLength;
     271             :   nsCString mContentType;
     272             :   PRTime mLastModified;
     273             :   nsCString mEntityID;
     274             :   URIParams mURI;
     275             : };
     276             : 
     277             : mozilla::ipc::IPCResult
     278           0 : FTPChannelChild::RecvOnStartRequest(const nsresult& aChannelStatus,
     279             :                                     const int64_t& aContentLength,
     280             :                                     const nsCString& aContentType,
     281             :                                     const PRTime& aLastModified,
     282             :                                     const nsCString& aEntityID,
     283             :                                     const URIParams& aURI)
     284             : {
     285             :   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
     286             :   // stage, as they are set in the listener's OnStartRequest.
     287           0 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     288             :     "mFlushedForDiversion should be unset before OnStartRequest!");
     289           0 :   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     290             :     "mDivertingToParent should be unset before OnStartRequest!");
     291             : 
     292           0 :   LOG(("FTPChannelChild::RecvOnStartRequest [this=%p]\n", this));
     293             : 
     294           0 :   mEventQ->RunOrEnqueue(new FTPStartRequestEvent(this, aChannelStatus,
     295             :                                                  aContentLength, aContentType,
     296             :                                                  aLastModified, aEntityID,
     297           0 :                                                  aURI));
     298           0 :   return IPC_OK();
     299             : }
     300             : 
     301             : void
     302           0 : FTPChannelChild::DoOnStartRequest(const nsresult& aChannelStatus,
     303             :                                   const int64_t& aContentLength,
     304             :                                   const nsCString& aContentType,
     305             :                                   const PRTime& aLastModified,
     306             :                                   const nsCString& aEntityID,
     307             :                                   const URIParams& aURI)
     308             : {
     309           0 :   LOG(("FTPChannelChild::DoOnStartRequest [this=%p]\n", this));
     310             : 
     311             :   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
     312             :   // stage, as they are set in the listener's OnStartRequest.
     313           0 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     314             :     "mFlushedForDiversion should be unset before OnStartRequest!");
     315           0 :   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     316             :     "mDivertingToParent should be unset before OnStartRequest!");
     317             : 
     318           0 :   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     319           0 :     mStatus = aChannelStatus;
     320             :   }
     321             : 
     322           0 :   mContentLength = aContentLength;
     323           0 :   SetContentType(aContentType);
     324           0 :   mLastModifiedTime = aLastModified;
     325           0 :   mEntityID = aEntityID;
     326             : 
     327           0 :   nsCString spec;
     328           0 :   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
     329           0 :   nsresult rv = uri->GetSpec(spec);
     330           0 :   if (NS_SUCCEEDED(rv)) {
     331           0 :     rv = nsBaseChannel::URI()->SetSpec(spec);
     332           0 :     if (NS_FAILED(rv)) {
     333           0 :       Cancel(rv);
     334             :     }
     335             :   } else {
     336           0 :     Cancel(rv);
     337             :   }
     338             : 
     339           0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     340           0 :   rv = mListener->OnStartRequest(this, mListenerContext);
     341           0 :   if (NS_FAILED(rv))
     342           0 :     Cancel(rv);
     343             : 
     344           0 :   if (mDivertingToParent) {
     345           0 :     mListener = nullptr;
     346           0 :     mListenerContext = nullptr;
     347           0 :     if (mLoadGroup) {
     348           0 :       mLoadGroup->RemoveRequest(this, nullptr, mStatus);
     349             :     }
     350             :   }
     351           0 : }
     352             : 
     353           0 : class FTPDataAvailableEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     354             : {
     355             : public:
     356           0 :   FTPDataAvailableEvent(FTPChannelChild* aChild,
     357             :                         const nsresult& aChannelStatus,
     358             :                         const nsCString& aData,
     359             :                         const uint64_t& aOffset,
     360             :                         const uint32_t& aCount)
     361           0 :     : NeckoTargetChannelEvent<FTPChannelChild>(aChild)
     362           0 :     , mChannelStatus(aChannelStatus)
     363             :     , mData(aData)
     364           0 :     , mOffset(aOffset)
     365           0 :     , mCount(aCount)
     366             :   {
     367           0 :   }
     368           0 :   void Run()
     369             :   {
     370           0 :     mChild->DoOnDataAvailable(mChannelStatus, mData, mOffset, mCount);
     371           0 :   }
     372             : 
     373             : private:
     374             :   nsresult mChannelStatus;
     375             :   nsCString mData;
     376             :   uint64_t mOffset;
     377             :   uint32_t mCount;
     378             : };
     379             : 
     380             : mozilla::ipc::IPCResult
     381           0 : FTPChannelChild::RecvOnDataAvailable(const nsresult& channelStatus,
     382             :                                      const nsCString& data,
     383             :                                      const uint64_t& offset,
     384             :                                      const uint32_t& count)
     385             : {
     386           0 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     387             :                      "Should not be receiving any more callbacks from parent!");
     388             : 
     389           0 :   LOG(("FTPChannelChild::RecvOnDataAvailable [this=%p]\n", this));
     390             : 
     391           0 :   mEventQ->RunOrEnqueue(new FTPDataAvailableEvent(this, channelStatus, data,
     392           0 :                                                   offset, count),
     393           0 :                         mDivertingToParent);
     394             : 
     395           0 :   return IPC_OK();
     396             : }
     397             : 
     398           0 : class MaybeDivertOnDataFTPEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     399             : {
     400             :  public:
     401           0 :   MaybeDivertOnDataFTPEvent(FTPChannelChild* child,
     402             :                             const nsCString& data,
     403             :                             const uint64_t& offset,
     404             :                             const uint32_t& count)
     405           0 :   : NeckoTargetChannelEvent<FTPChannelChild>(child)
     406             :   , mData(data)
     407           0 :   , mOffset(offset)
     408           0 :   , mCount(count) {}
     409             : 
     410           0 :   void Run()
     411             :   {
     412           0 :     mChild->MaybeDivertOnData(mData, mOffset, mCount);
     413           0 :   }
     414             : 
     415             :  private:
     416             :   nsCString mData;
     417             :   uint64_t mOffset;
     418             :   uint32_t mCount;
     419             : };
     420             : 
     421             : void
     422           0 : FTPChannelChild::MaybeDivertOnData(const nsCString& data,
     423             :                                    const uint64_t& offset,
     424             :                                    const uint32_t& count)
     425             : {
     426           0 :   if (mDivertingToParent) {
     427           0 :     SendDivertOnDataAvailable(data, offset, count);
     428             :   }
     429           0 : }
     430             : 
     431             : void
     432           0 : FTPChannelChild::DoOnDataAvailable(const nsresult& channelStatus,
     433             :                                    const nsCString& data,
     434             :                                    const uint64_t& offset,
     435             :                                    const uint32_t& count)
     436             : {
     437           0 :   LOG(("FTPChannelChild::DoOnDataAvailable [this=%p]\n", this));
     438             : 
     439           0 :   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     440           0 :     mStatus = channelStatus;
     441             :   }
     442             : 
     443           0 :   if (mDivertingToParent) {
     444           0 :     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     445             :       "Should not be processing any more callbacks from parent!");
     446             : 
     447           0 :     SendDivertOnDataAvailable(data, offset, count);
     448           0 :     return;
     449             :   }
     450             : 
     451           0 :   if (mCanceled)
     452           0 :     return;
     453             : 
     454           0 :   if (mUnknownDecoderInvolved) {
     455           0 :     mUnknownDecoderEventQ.AppendElement(
     456           0 :       MakeUnique<MaybeDivertOnDataFTPEvent>(this, data, offset, count));
     457             :   }
     458             : 
     459             :   // NOTE: the OnDataAvailable contract requires the client to read all the data
     460             :   // in the inputstream.  This code relies on that ('data' will go away after
     461             :   // this function).  Apparently the previous, non-e10s behavior was to actually
     462             :   // support only reading part of the data, allowing later calls to read the
     463             :   // rest.
     464           0 :   nsCOMPtr<nsIInputStream> stringStream;
     465           0 :   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
     466             :                                       data.get(),
     467           0 :                                       count,
     468           0 :                                       NS_ASSIGNMENT_DEPEND);
     469           0 :   if (NS_FAILED(rv)) {
     470           0 :     Cancel(rv);
     471           0 :     return;
     472             :   }
     473             : 
     474           0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     475           0 :   rv = mListener->OnDataAvailable(this, mListenerContext,
     476           0 :                                   stringStream, offset, count);
     477           0 :   if (NS_FAILED(rv))
     478           0 :     Cancel(rv);
     479           0 :   stringStream->Close();
     480             : }
     481             : 
     482           0 : class FTPStopRequestEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     483             : {
     484             : public:
     485           0 :   FTPStopRequestEvent(FTPChannelChild* aChild,
     486             :                       const nsresult& aChannelStatus,
     487             :                       const nsCString &aErrorMsg,
     488             :                       bool aUseUTF8)
     489           0 :     : NeckoTargetChannelEvent<FTPChannelChild>(aChild)
     490           0 :     , mChannelStatus(aChannelStatus)
     491             :     , mErrorMsg(aErrorMsg)
     492           0 :     , mUseUTF8(aUseUTF8)
     493             :   {
     494           0 :   }
     495           0 :   void Run()
     496             :   {
     497           0 :     mChild->DoOnStopRequest(mChannelStatus, mErrorMsg, mUseUTF8);
     498           0 :   }
     499             : 
     500             : private:
     501             :   nsresult mChannelStatus;
     502             :   nsCString mErrorMsg;
     503             :   bool mUseUTF8;
     504             : };
     505             : 
     506             : mozilla::ipc::IPCResult
     507           0 : FTPChannelChild::RecvOnStopRequest(const nsresult& aChannelStatus,
     508             :                                    const nsCString &aErrorMsg,
     509             :                                    const bool &aUseUTF8)
     510             : {
     511           0 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     512             :     "Should not be receiving any more callbacks from parent!");
     513             : 
     514           0 :   LOG(("FTPChannelChild::RecvOnStopRequest [this=%p status=%" PRIx32"]\n",
     515             :        this, static_cast<uint32_t>(aChannelStatus)));
     516             : 
     517           0 :   mEventQ->RunOrEnqueue(new FTPStopRequestEvent(this, aChannelStatus, aErrorMsg,
     518           0 :                                                 aUseUTF8));
     519           0 :   return IPC_OK();
     520             : }
     521             : 
     522             : class nsFtpChildAsyncAlert : public Runnable
     523             : {
     524             : public:
     525           0 :   nsFtpChildAsyncAlert(nsIPrompt *aPrompter, nsString aResponseMsg)
     526           0 :     : Runnable("nsFtpChildAsyncAlert")
     527             :     , mPrompter(aPrompter)
     528           0 :     , mResponseMsg(aResponseMsg)
     529             :   {
     530           0 :   }
     531             : protected:
     532           0 :   virtual ~nsFtpChildAsyncAlert()
     533           0 :   {
     534           0 :   }
     535             : public:
     536           0 :   NS_IMETHOD Run() override
     537             :   {
     538           0 :     if (mPrompter) {
     539           0 :       mPrompter->Alert(nullptr, mResponseMsg.get());
     540             :     }
     541           0 :     return NS_OK;
     542             :   }
     543             : private:
     544             :   nsCOMPtr<nsIPrompt> mPrompter;
     545             :   nsString mResponseMsg;
     546             : };
     547             : 
     548           0 : class MaybeDivertOnStopFTPEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     549             : {
     550             :  public:
     551           0 :   MaybeDivertOnStopFTPEvent(FTPChannelChild* child,
     552             :                             const nsresult& aChannelStatus)
     553           0 :   : NeckoTargetChannelEvent<FTPChannelChild>(child)
     554           0 :   , mChannelStatus(aChannelStatus) {}
     555             : 
     556           0 :   void Run()
     557             :   {
     558           0 :     mChild->MaybeDivertOnStop(mChannelStatus);
     559           0 :   }
     560             : 
     561             :  private:
     562             :   nsresult mChannelStatus;
     563             : };
     564             : 
     565             : void
     566           0 : FTPChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus)
     567             : {
     568           0 :   if (mDivertingToParent) {
     569           0 :     SendDivertOnStopRequest(aChannelStatus);
     570             :   }
     571           0 : }
     572             : 
     573             : void
     574           0 : FTPChannelChild::DoOnStopRequest(const nsresult& aChannelStatus,
     575             :                                  const nsCString &aErrorMsg,
     576             :                                  bool aUseUTF8)
     577             : {
     578           0 :   LOG(("FTPChannelChild::DoOnStopRequest [this=%p status=%" PRIx32 "]\n",
     579             :        this, static_cast<uint32_t>(aChannelStatus)));
     580             : 
     581           0 :   if (mDivertingToParent) {
     582           0 :     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     583             :       "Should not be processing any more callbacks from parent!");
     584             : 
     585           0 :     SendDivertOnStopRequest(aChannelStatus);
     586           0 :     return;
     587             :   }
     588             : 
     589           0 :   if (!mCanceled)
     590           0 :     mStatus = aChannelStatus;
     591             : 
     592           0 :   if (mUnknownDecoderInvolved) {
     593           0 :     mUnknownDecoderEventQ.AppendElement(
     594           0 :       MakeUnique<MaybeDivertOnStopFTPEvent>(this, aChannelStatus));
     595             :   }
     596             : 
     597             :   { // Ensure that all queued ipdl events are dispatched before
     598             :     // we initiate protocol deletion below.
     599           0 :     mIsPending = false;
     600           0 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     601           0 :     (void)mListener->OnStopRequest(this, mListenerContext, aChannelStatus);
     602             : 
     603           0 :     if (NS_FAILED(aChannelStatus) && !aErrorMsg.IsEmpty()) {
     604           0 :       nsCOMPtr<nsIPrompt> prompter;
     605           0 :       GetCallback(prompter);
     606           0 :       if (prompter) {
     607           0 :         nsCOMPtr<nsIRunnable> alertEvent;
     608           0 :         if (aUseUTF8) {
     609             :           alertEvent = new nsFtpChildAsyncAlert(prompter,
     610           0 :                              NS_ConvertUTF8toUTF16(aErrorMsg));
     611             :         } else {
     612             :           alertEvent = new nsFtpChildAsyncAlert(prompter,
     613           0 :                              NS_ConvertASCIItoUTF16(aErrorMsg));
     614             :         }
     615             : 
     616           0 :         Dispatch(alertEvent.forget());
     617             :       }
     618             :     }
     619             : 
     620           0 :     mListener = nullptr;
     621           0 :     mListenerContext = nullptr;
     622             : 
     623           0 :     if (mLoadGroup)
     624           0 :       mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus);
     625             :   }
     626             : 
     627             :   // This calls NeckoChild::DeallocPFTPChannelChild(), which deletes |this| if IPDL
     628             :   // holds the last reference.  Don't rely on |this| existing after here!
     629           0 :   Send__delete__(this);
     630             : }
     631             : 
     632           0 : class FTPFailedAsyncOpenEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     633             : {
     634             :  public:
     635           0 :   FTPFailedAsyncOpenEvent(FTPChannelChild* aChild, nsresult aStatus)
     636           0 :   : NeckoTargetChannelEvent<FTPChannelChild>(aChild)
     637           0 :   , mStatus(aStatus) {}
     638           0 :   void Run() { mChild->DoFailedAsyncOpen(mStatus); }
     639             : 
     640             :  private:
     641             :   nsresult mStatus;
     642             : };
     643             : 
     644             : mozilla::ipc::IPCResult
     645           0 : FTPChannelChild::RecvFailedAsyncOpen(const nsresult& statusCode)
     646             : {
     647           0 :   LOG(("FTPChannelChild::RecvFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
     648             :        this, static_cast<uint32_t>(statusCode)));
     649           0 :   mEventQ->RunOrEnqueue(new FTPFailedAsyncOpenEvent(this, statusCode));
     650           0 :   return IPC_OK();
     651             : }
     652             : 
     653             : void
     654           0 : FTPChannelChild::DoFailedAsyncOpen(const nsresult& statusCode)
     655             : {
     656           0 :   LOG(("FTPChannelChild::DoFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
     657             :        this, static_cast<uint32_t>(statusCode)));
     658           0 :   mStatus = statusCode;
     659             : 
     660           0 :   if (mLoadGroup)
     661           0 :     mLoadGroup->RemoveRequest(this, nullptr, statusCode);
     662             : 
     663           0 :   if (mListener) {
     664           0 :     mListener->OnStartRequest(this, mListenerContext);
     665           0 :     mIsPending = false;
     666           0 :     mListener->OnStopRequest(this, mListenerContext, statusCode);
     667             :   } else {
     668           0 :     mIsPending = false;
     669             :   }
     670             : 
     671           0 :   mListener = nullptr;
     672           0 :   mListenerContext = nullptr;
     673             : 
     674           0 :   if (mIPCOpen)
     675           0 :     Send__delete__(this);
     676           0 : }
     677             : 
     678           0 : class FTPFlushedForDiversionEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     679             : {
     680             :  public:
     681           0 :   explicit FTPFlushedForDiversionEvent(FTPChannelChild* aChild)
     682           0 :   : NeckoTargetChannelEvent<FTPChannelChild>(aChild)
     683             :   {
     684           0 :     MOZ_RELEASE_ASSERT(aChild);
     685           0 :   }
     686             : 
     687           0 :   void Run()
     688             :   {
     689           0 :     mChild->FlushedForDiversion();
     690           0 :   }
     691             : };
     692             : 
     693             : mozilla::ipc::IPCResult
     694           0 : FTPChannelChild::RecvFlushedForDiversion()
     695             : {
     696           0 :   LOG(("FTPChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
     697           0 :   MOZ_ASSERT(mDivertingToParent);
     698             : 
     699           0 :   mEventQ->RunOrEnqueue(new FTPFlushedForDiversionEvent(this), true);
     700           0 :   return IPC_OK();
     701             : }
     702             : 
     703             : void
     704           0 : FTPChannelChild::FlushedForDiversion()
     705             : {
     706           0 :   LOG(("FTPChannelChild::FlushedForDiversion [this=%p]\n", this));
     707           0 :   MOZ_RELEASE_ASSERT(mDivertingToParent);
     708             : 
     709             :   // Once this is set, it should not be unset before FTPChannelChild is taken
     710             :   // down. After it is set, no OnStart/OnData/OnStop callbacks should be
     711             :   // received from the parent channel, nor dequeued from the ChannelEventQueue.
     712           0 :   mFlushedForDiversion = true;
     713             : 
     714           0 :   SendDivertComplete();
     715           0 : }
     716             : 
     717             : mozilla::ipc::IPCResult
     718           0 : FTPChannelChild::RecvDivertMessages()
     719             : {
     720           0 :   LOG(("FTPChannelChild::RecvDivertMessages [this=%p]\n", this));
     721           0 :   MOZ_RELEASE_ASSERT(mDivertingToParent);
     722           0 :   MOZ_RELEASE_ASSERT(mSuspendCount > 0);
     723             : 
     724             :   // DivertTo() has been called on parent, so we can now start sending queued
     725             :   // IPDL messages back to parent listener.
     726           0 :   if (NS_WARN_IF(NS_FAILED(Resume()))) {
     727           0 :     return IPC_FAIL_NO_REASON(this);
     728             :   }
     729           0 :   return IPC_OK();
     730             : }
     731             : 
     732           0 : class FTPDeleteSelfEvent : public NeckoTargetChannelEvent<FTPChannelChild>
     733             : {
     734             :  public:
     735           0 :   explicit FTPDeleteSelfEvent(FTPChannelChild* aChild)
     736           0 :   : NeckoTargetChannelEvent<FTPChannelChild>(aChild) {}
     737           0 :   void Run() { mChild->DoDeleteSelf(); }
     738             : };
     739             : 
     740             : mozilla::ipc::IPCResult
     741           0 : FTPChannelChild::RecvDeleteSelf()
     742             : {
     743           0 :   mEventQ->RunOrEnqueue(new FTPDeleteSelfEvent(this));
     744           0 :   return IPC_OK();
     745             : }
     746             : 
     747             : void
     748           0 : FTPChannelChild::DoDeleteSelf()
     749             : {
     750           0 :   if (mIPCOpen)
     751           0 :     Send__delete__(this);
     752           0 : }
     753             : 
     754             : NS_IMETHODIMP
     755           0 : FTPChannelChild::Cancel(nsresult status)
     756             : {
     757           0 :   LOG(("FTPChannelChild::Cancel [this=%p]\n", this));
     758           0 :   if (mCanceled)
     759           0 :     return NS_OK;
     760             : 
     761           0 :   mCanceled = true;
     762           0 :   mStatus = status;
     763           0 :   if (mIPCOpen)
     764           0 :     SendCancel(status);
     765           0 :   return NS_OK;
     766             : }
     767             : 
     768             : NS_IMETHODIMP
     769           0 : FTPChannelChild::Suspend()
     770             : {
     771           0 :   NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
     772             : 
     773           0 :   LOG(("FTPChannelChild::Suspend [this=%p]\n", this));
     774             : 
     775             :   // SendSuspend only once, when suspend goes from 0 to 1.
     776             :   // Don't SendSuspend at all if we're diverting callbacks to the parent;
     777             :   // suspend will be called at the correct time in the parent itself.
     778           0 :   if (!mSuspendCount++ && !mDivertingToParent) {
     779           0 :     SendSuspend();
     780           0 :     mSuspendSent = true;
     781             :   }
     782           0 :   mEventQ->Suspend();
     783             : 
     784           0 :   return NS_OK;
     785             : }
     786             : 
     787             : NS_IMETHODIMP
     788           0 : FTPChannelChild::Resume()
     789             : {
     790           0 :   NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
     791             : 
     792           0 :   LOG(("FTPChannelChild::Resume [this=%p]\n", this));
     793             : 
     794             :   // SendResume only once, when suspend count drops to 0.
     795             :   // Don't SendResume at all if we're diverting callbacks to the parent (unless
     796             :   // suspend was sent earlier); otherwise, resume will be called at the correct
     797             :   // time in the parent itself.
     798           0 :   if (!--mSuspendCount && (!mDivertingToParent || mSuspendSent)) {
     799           0 :     SendResume();
     800             :   }
     801           0 :   mEventQ->Resume();
     802             : 
     803           0 :   return NS_OK;
     804             : }
     805             : 
     806             : //-----------------------------------------------------------------------------
     807             : // FTPChannelChild::nsIChildChannel
     808             : //-----------------------------------------------------------------------------
     809             : 
     810             : NS_IMETHODIMP
     811           0 : FTPChannelChild::ConnectParent(uint32_t id)
     812             : {
     813           0 :   NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
     814           0 :   NS_ENSURE_TRUE(!static_cast<ContentChild*>(gNeckoChild->Manager())->
     815             :                    IsShuttingDown(), NS_ERROR_FAILURE);
     816             : 
     817           0 :   LOG(("FTPChannelChild::ConnectParent [this=%p]\n", this));
     818             : 
     819           0 :   mozilla::dom::TabChild* tabChild = nullptr;
     820           0 :   nsCOMPtr<nsITabChild> iTabChild;
     821           0 :   NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
     822             :                                 NS_GET_IID(nsITabChild),
     823           0 :                                 getter_AddRefs(iTabChild));
     824           0 :   GetCallback(iTabChild);
     825           0 :   if (iTabChild) {
     826           0 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
     827             :   }
     828             : 
     829             :   // This must happen before the constructor message is sent.
     830           0 :   SetupNeckoTarget();
     831             : 
     832             :   // The socket transport in the chrome process now holds a logical ref to us
     833             :   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
     834           0 :   AddIPDLReference();
     835             : 
     836           0 :   FTPChannelConnectArgs connectArgs(id);
     837             : 
     838           0 :   if (!gNeckoChild->SendPFTPChannelConstructor(this, tabChild,
     839           0 :                                                IPC::SerializedLoadContext(this),
     840             :                                                connectArgs)) {
     841           0 :     return NS_ERROR_FAILURE;
     842             :   }
     843             : 
     844           0 :   return NS_OK;
     845             : }
     846             : 
     847             : NS_IMETHODIMP
     848           0 : FTPChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
     849             :                                        nsISupports *aContext)
     850             : {
     851           0 :   LOG(("FTPChannelChild::CompleteRedirectSetup [this=%p]\n", this));
     852             : 
     853           0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
     854           0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
     855             : 
     856           0 :   mIsPending = true;
     857           0 :   mWasOpened = true;
     858           0 :   mListener = listener;
     859           0 :   mListenerContext = aContext;
     860             : 
     861             :   // add ourselves to the load group.
     862           0 :   if (mLoadGroup)
     863           0 :     mLoadGroup->AddRequest(this, nullptr);
     864             : 
     865             :   // We already have an open IPDL connection to the parent. If on-modify-request
     866             :   // listeners or load group observers canceled us, let the parent handle it
     867             :   // and send it back to us naturally.
     868           0 :   return NS_OK;
     869             : }
     870             : 
     871             : //-----------------------------------------------------------------------------
     872             : // FTPChannelChild::nsIDivertableChannel
     873             : //-----------------------------------------------------------------------------
     874             : NS_IMETHODIMP
     875           0 : FTPChannelChild::DivertToParent(ChannelDiverterChild **aChild)
     876             : {
     877           0 :   MOZ_RELEASE_ASSERT(aChild);
     878           0 :   MOZ_RELEASE_ASSERT(gNeckoChild);
     879           0 :   MOZ_RELEASE_ASSERT(!mDivertingToParent);
     880           0 :   NS_ENSURE_TRUE(!static_cast<ContentChild*>(gNeckoChild->Manager())->
     881             :                    IsShuttingDown(), NS_ERROR_FAILURE);
     882             : 
     883           0 :   LOG(("FTPChannelChild::DivertToParent [this=%p]\n", this));
     884             : 
     885             :   // We must fail DivertToParent() if there's no parent end of the channel (and
     886             :   // won't be!) due to early failure.
     887           0 :   if (NS_FAILED(mStatus) && !mIPCOpen) {
     888           0 :     return mStatus;
     889             :   }
     890             : 
     891           0 :   nsresult rv = Suspend();
     892           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     893           0 :     return rv;
     894             :   }
     895             : 
     896             :   // Once this is set, it should not be unset before the child is taken down.
     897           0 :   mDivertingToParent = true;
     898             : 
     899             :   PChannelDiverterChild* diverter =
     900           0 :     gNeckoChild->SendPChannelDiverterConstructor(this);
     901           0 :   MOZ_RELEASE_ASSERT(diverter);
     902             : 
     903           0 :   *aChild = static_cast<ChannelDiverterChild*>(diverter);
     904             : 
     905           0 :   return NS_OK;
     906             : }
     907             : 
     908             : NS_IMETHODIMP
     909           0 : FTPChannelChild::UnknownDecoderInvolvedKeepData()
     910             : {
     911           0 :   mUnknownDecoderInvolved = true;
     912           0 :   return NS_OK;
     913             : }
     914             : 
     915             : NS_IMETHODIMP
     916           0 : FTPChannelChild::UnknownDecoderInvolvedOnStartRequestCalled()
     917             : {
     918           0 :   mUnknownDecoderInvolved = false;
     919             : 
     920           0 :   nsresult rv = NS_OK;
     921             : 
     922           0 :   if (mDivertingToParent) {
     923           0 :     rv = mEventQ->PrependEvents(mUnknownDecoderEventQ);
     924             :   }
     925           0 :   mUnknownDecoderEventQ.Clear();
     926             : 
     927           0 :   return rv;
     928             : }
     929             : 
     930             : NS_IMETHODIMP
     931           0 : FTPChannelChild::GetDivertingToParent(bool* aDiverting)
     932             : {
     933           0 :   NS_ENSURE_ARG_POINTER(aDiverting);
     934           0 :   *aDiverting = mDivertingToParent;
     935           0 :   return NS_OK;
     936             : }
     937             : 
     938             : void
     939           0 : FTPChannelChild::SetupNeckoTarget()
     940             : {
     941           0 :   if (mNeckoTarget) {
     942           0 :     return;
     943             :   }
     944             : 
     945           0 :   nsCOMPtr<nsILoadInfo> loadInfo;
     946           0 :   GetLoadInfo(getter_AddRefs(loadInfo));
     947             : 
     948           0 :   mNeckoTarget = nsContentUtils::GetEventTargetByLoadInfo(loadInfo, TaskCategory::Network);
     949           0 :   if (!mNeckoTarget) {
     950           0 :     return;
     951             :   }
     952             : 
     953           0 :   gNeckoChild->SetEventTargetForActor(this, mNeckoTarget);
     954             : }
     955             : 
     956             : } // namespace net
     957             : } // namespace mozilla
     958             : 

Generated by: LCOV version 1.13