netwerk/protocol/ftp/FTPChannelChild.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=8 et tw=80 : */
     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/. */
     8 #include "mozilla/net/NeckoChild.h"
     9 #include "mozilla/net/ChannelDiverterChild.h"
    10 #include "mozilla/net/FTPChannelChild.h"
    11 #include "mozilla/dom/TabChild.h"
    12 #include "nsFtpProtocolHandler.h"
    13 #include "nsITabChild.h"
    14 #include "nsStringStream.h"
    15 #include "nsNetUtil.h"
    16 #include "base/compiler_specific.h"
    17 #include "mozilla/ipc/InputStreamUtils.h"
    18 #include "mozilla/ipc/URIUtils.h"
    19 #include "SerializedLoadContext.h"
    21 using namespace mozilla::ipc;
    23 #undef LOG
    24 #define LOG(args) PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
    26 namespace mozilla {
    27 namespace net {
    29 FTPChannelChild::FTPChannelChild(nsIURI* uri)
    30 : mIPCOpen(false)
    31 , mCanceled(false)
    32 , mSuspendCount(0)
    33 , mIsPending(false)
    34 , mWasOpened(false)
    35 , mLastModifiedTime(0)
    36 , mStartPos(0)
    37 , mDivertingToParent(false)
    38 , mFlushedForDiversion(false)
    39 , mSuspendSent(false)
    40 {
    41   LOG(("Creating FTPChannelChild @%x\n", this));
    42   // grab a reference to the handler to ensure that it doesn't go away.
    43   NS_ADDREF(gFtpHandler);
    44   SetURI(uri);
    45   mEventQ = new ChannelEventQueue(static_cast<nsIFTPChannel*>(this));
    46 }
    48 FTPChannelChild::~FTPChannelChild()
    49 {
    50   LOG(("Destroying FTPChannelChild @%x\n", this));
    51   gFtpHandler->Release();
    52 }
    54 void
    55 FTPChannelChild::AddIPDLReference()
    56 {
    57   NS_ABORT_IF_FALSE(!mIPCOpen, "Attempt to retain more than one IPDL reference");
    58   mIPCOpen = true;
    59   AddRef();
    60 }
    62 void
    63 FTPChannelChild::ReleaseIPDLReference()
    64 {
    65   NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
    66   mIPCOpen = false;
    67   Release();
    68 }
    70 //-----------------------------------------------------------------------------
    71 // FTPChannelChild::nsISupports
    72 //-----------------------------------------------------------------------------
    74 NS_IMPL_ISUPPORTS_INHERITED(FTPChannelChild,
    75                             nsBaseChannel,
    76                             nsIFTPChannel,
    77                             nsIUploadChannel,
    78                             nsIResumableChannel,
    79                             nsIProxiedChannel,
    80                             nsIChildChannel,
    81                             nsIDivertableChannel)
    83 //-----------------------------------------------------------------------------
    85 NS_IMETHODIMP
    86 FTPChannelChild::GetLastModifiedTime(PRTime* lastModifiedTime)
    87 {
    88   *lastModifiedTime = mLastModifiedTime;
    89   return NS_OK;
    90 }
    92 NS_IMETHODIMP
    93 FTPChannelChild::SetLastModifiedTime(PRTime lastModifiedTime)
    94 {
    95   return NS_ERROR_NOT_AVAILABLE;
    96 }
    98 NS_IMETHODIMP
    99 FTPChannelChild::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID)
   100 {
   101   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   102   mStartPos = aStartPos;
   103   mEntityID = aEntityID;
   104   return NS_OK;
   105 }
   107 NS_IMETHODIMP
   108 FTPChannelChild::GetEntityID(nsACString& entityID)
   109 {
   110   entityID = mEntityID;
   111   return NS_OK;
   112 }
   114 NS_IMETHODIMP
   115 FTPChannelChild::GetProxyInfo(nsIProxyInfo** aProxyInfo)
   116 {
   117   DROP_DEAD();
   118 }
   120 NS_IMETHODIMP
   121 FTPChannelChild::SetUploadStream(nsIInputStream* stream,
   122                                  const nsACString& contentType,
   123                                  int64_t contentLength)
   124 {
   125   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   126   mUploadStream = stream;
   127   // NOTE: contentLength is intentionally ignored here.
   128   return NS_OK;
   129 }
   131 NS_IMETHODIMP
   132 FTPChannelChild::GetUploadStream(nsIInputStream** stream)
   133 {
   134   NS_ENSURE_ARG_POINTER(stream);
   135   *stream = mUploadStream;
   136   NS_IF_ADDREF(*stream);
   137   return NS_OK;
   138 }
   140 //-----------------------------------------------------------------------------
   142 NS_IMETHODIMP
   143 FTPChannelChild::AsyncOpen(::nsIStreamListener* listener, nsISupports* aContext)
   144 {
   145   LOG(("FTPChannelChild::AsyncOpen [this=%p]\n", this));
   147   NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
   148   NS_ENSURE_ARG_POINTER(listener);
   149   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   150   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
   152   // Port checked in parent, but duplicate here so we can return with error
   153   // immediately, as we've done since before e10s.
   154   nsresult rv;
   155   rv = NS_CheckPortSafety(nsBaseChannel::URI()); // Need to disambiguate,
   156                                                  // because in the child ipdl,
   157                                                  // a typedef URI is defined...
   158   if (NS_FAILED(rv))
   159     return rv;
   161   mozilla::dom::TabChild* tabChild = nullptr;
   162   nsCOMPtr<nsITabChild> iTabChild;
   163   NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
   164                                 NS_GET_IID(nsITabChild),
   165                                 getter_AddRefs(iTabChild));
   166   GetCallback(iTabChild);
   167   if (iTabChild) {
   168     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
   169   }
   170   if (MissingRequiredTabChild(tabChild, "ftp")) {
   171     return NS_ERROR_ILLEGAL_VALUE;
   172   }
   174   mListener = listener;
   175   mListenerContext = aContext;
   177   // add ourselves to the load group. 
   178   if (mLoadGroup)
   179     mLoadGroup->AddRequest(this, nullptr);
   181   OptionalInputStreamParams uploadStream;
   182   nsTArray<mozilla::ipc::FileDescriptor> fds;
   183   SerializeInputStream(mUploadStream, uploadStream, fds);
   185   MOZ_ASSERT(fds.IsEmpty());
   187   FTPChannelOpenArgs openArgs;
   188   SerializeURI(nsBaseChannel::URI(), openArgs.uri());
   189   openArgs.startPos() = mStartPos;
   190   openArgs.entityID() = mEntityID;
   191   openArgs.uploadStream() = uploadStream;
   193   gNeckoChild->
   194     SendPFTPChannelConstructor(this, tabChild, IPC::SerializedLoadContext(this),
   195                                openArgs);
   197   // The socket transport layer in the chrome process now has a logical ref to
   198   // us until OnStopRequest is called.
   199   AddIPDLReference();
   201   mIsPending = true;
   202   mWasOpened = true;
   204   return rv;
   205 }
   207 NS_IMETHODIMP
   208 FTPChannelChild::IsPending(bool* result)
   209 {
   210   *result = mIsPending;
   211   return NS_OK;
   212 }
   214 nsresult
   215 FTPChannelChild::OpenContentStream(bool async,
   216                                    nsIInputStream** stream,
   217                                    nsIChannel** channel)
   218 {
   219   NS_RUNTIMEABORT("FTPChannel*Child* should never have OpenContentStream called!");
   220   return NS_OK;
   221 }
   223 //-----------------------------------------------------------------------------
   224 // FTPChannelChild::PFTPChannelChild
   225 //-----------------------------------------------------------------------------
   227 class FTPStartRequestEvent : public ChannelEvent
   228 {
   229 public:
   230   FTPStartRequestEvent(FTPChannelChild* aChild,
   231                        const nsresult& aChannelStatus,
   232                        const int64_t& aContentLength,
   233                        const nsCString& aContentType,
   234                        const PRTime& aLastModified,
   235                        const nsCString& aEntityID,
   236                        const URIParams& aURI)
   237     : mChild(aChild)
   238     , mChannelStatus(aChannelStatus)
   239     , mContentLength(aContentLength)
   240     , mContentType(aContentType)
   241     , mLastModified(aLastModified)
   242     , mEntityID(aEntityID)
   243     , mURI(aURI)
   244   {
   245   }
   246   void Run()
   247   {
   248     mChild->DoOnStartRequest(mChannelStatus, mContentLength, mContentType,
   249                              mLastModified, mEntityID, mURI);
   250   }
   252 private:
   253   FTPChannelChild* mChild;
   254   nsresult mChannelStatus;
   255   int64_t mContentLength;
   256   nsCString mContentType;
   257   PRTime mLastModified;
   258   nsCString mEntityID;
   259   URIParams mURI;
   260 };
   262 bool
   263 FTPChannelChild::RecvOnStartRequest(const nsresult& aChannelStatus,
   264                                     const int64_t& aContentLength,
   265                                     const nsCString& aContentType,
   266                                     const PRTime& aLastModified,
   267                                     const nsCString& aEntityID,
   268                                     const URIParams& aURI)
   269 {
   270   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   271   // stage, as they are set in the listener's OnStartRequest.
   272   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
   273     "mFlushedForDiversion should be unset before OnStartRequest!");
   274   MOZ_RELEASE_ASSERT(!mDivertingToParent,
   275     "mDivertingToParent should be unset before OnStartRequest!");
   277   if (mEventQ->ShouldEnqueue()) {
   278     mEventQ->Enqueue(new FTPStartRequestEvent(this, aChannelStatus,
   279                                               aContentLength, aContentType,
   280                                               aLastModified, aEntityID, aURI));
   281   } else {
   282     DoOnStartRequest(aChannelStatus, aContentLength, aContentType,
   283                      aLastModified, aEntityID, aURI);
   284   }
   285   return true;
   286 }
   288 void
   289 FTPChannelChild::DoOnStartRequest(const nsresult& aChannelStatus,
   290                                   const int64_t& aContentLength,
   291                                   const nsCString& aContentType,
   292                                   const PRTime& aLastModified,
   293                                   const nsCString& aEntityID,
   294                                   const URIParams& aURI)
   295 {
   296   LOG(("FTPChannelChild::RecvOnStartRequest [this=%p]\n", this));
   298   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   299   // stage, as they are set in the listener's OnStartRequest.
   300   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
   301     "mFlushedForDiversion should be unset before OnStartRequest!");
   302   MOZ_RELEASE_ASSERT(!mDivertingToParent,
   303     "mDivertingToParent should be unset before OnStartRequest!");
   305   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
   306     mStatus = aChannelStatus;
   307   }
   309   mContentLength = aContentLength;
   310   SetContentType(aContentType);
   311   mLastModifiedTime = aLastModified;
   312   mEntityID = aEntityID;
   314   nsCString spec;
   315   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
   316   uri->GetSpec(spec);
   317   nsBaseChannel::URI()->SetSpec(spec);
   319   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
   320   nsresult rv = mListener->OnStartRequest(this, mListenerContext);
   321   if (NS_FAILED(rv))
   322     Cancel(rv);
   324   if (mDivertingToParent) {
   325     mListener = nullptr;
   326     mListenerContext = nullptr;
   327     if (mLoadGroup) {
   328       mLoadGroup->RemoveRequest(this, nullptr, mStatus);
   329     }
   330   }
   331 }
   333 class FTPDataAvailableEvent : public ChannelEvent
   334 {
   335 public:
   336   FTPDataAvailableEvent(FTPChannelChild* aChild,
   337                         const nsresult& aChannelStatus,
   338                         const nsCString& aData,
   339                         const uint64_t& aOffset,
   340                         const uint32_t& aCount)
   341     : mChild(aChild)
   342     , mChannelStatus(aChannelStatus)
   343     , mData(aData)
   344     , mOffset(aOffset)
   345     , mCount(aCount)
   346   {
   347   }
   348   void Run()
   349   {
   350     mChild->DoOnDataAvailable(mChannelStatus, mData, mOffset, mCount);
   351   }
   353 private:
   354   FTPChannelChild* mChild;
   355   nsresult mChannelStatus;
   356   nsCString mData;
   357   uint64_t mOffset;
   358   uint32_t mCount;
   359 };
   361 bool
   362 FTPChannelChild::RecvOnDataAvailable(const nsresult& channelStatus,
   363                                      const nsCString& data,
   364                                      const uint64_t& offset,
   365                                      const uint32_t& count)
   366 {
   367   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
   368                      "Should not be receiving any more callbacks from parent!");
   370   if (mEventQ->ShouldEnqueue()) {
   371     mEventQ->Enqueue(
   372       new FTPDataAvailableEvent(this, channelStatus, data, offset, count));
   373   } else {
   374     MOZ_RELEASE_ASSERT(!mDivertingToParent,
   375                        "ShouldEnqueue when diverting to parent!");
   377     DoOnDataAvailable(channelStatus, data, offset, count);
   378   }
   379   return true;
   380 }
   382 void
   383 FTPChannelChild::DoOnDataAvailable(const nsresult& channelStatus,
   384                                    const nsCString& data,
   385                                    const uint64_t& offset,
   386                                    const uint32_t& count)
   387 {
   388   LOG(("FTPChannelChild::RecvOnDataAvailable [this=%p]\n", this));
   390   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
   391     mStatus = channelStatus;
   392   }
   394   if (mDivertingToParent) {
   395     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
   396       "Should not be processing any more callbacks from parent!");
   398     SendDivertOnDataAvailable(data, offset, count);
   399     return;
   400   }
   402   if (mCanceled)
   403     return;
   405   // NOTE: the OnDataAvailable contract requires the client to read all the data
   406   // in the inputstream.  This code relies on that ('data' will go away after
   407   // this function).  Apparently the previous, non-e10s behavior was to actually
   408   // support only reading part of the data, allowing later calls to read the
   409   // rest.
   410   nsCOMPtr<nsIInputStream> stringStream;
   411   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
   412                                       data.get(),
   413                                       count,
   414                                       NS_ASSIGNMENT_DEPEND);
   415   if (NS_FAILED(rv)) {
   416     Cancel(rv);
   417     return;
   418   }
   420   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
   421   rv = mListener->OnDataAvailable(this, mListenerContext,
   422                                   stringStream, offset, count);
   423   if (NS_FAILED(rv))
   424     Cancel(rv);
   425   stringStream->Close();
   426 }
   428 class FTPStopRequestEvent : public ChannelEvent
   429 {
   430 public:
   431   FTPStopRequestEvent(FTPChannelChild* aChild,
   432                       const nsresult& aChannelStatus)
   433     : mChild(aChild)
   434     , mChannelStatus(aChannelStatus)
   435   {
   436   }
   437   void Run()
   438   {
   439     mChild->DoOnStopRequest(mChannelStatus);
   440   }
   442 private:
   443   FTPChannelChild* mChild;
   444   nsresult mChannelStatus;
   445 };
   447 bool
   448 FTPChannelChild::RecvOnStopRequest(const nsresult& aChannelStatus)
   449 {
   450   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
   451     "Should not be receiving any more callbacks from parent!");
   453   if (mEventQ->ShouldEnqueue()) {
   454     mEventQ->Enqueue(new FTPStopRequestEvent(this, aChannelStatus));
   455   } else {
   456     DoOnStopRequest(aChannelStatus);
   457   }
   458   return true;
   459 }
   461 void
   462 FTPChannelChild::DoOnStopRequest(const nsresult& aChannelStatus)
   463 {
   464   LOG(("FTPChannelChild::RecvOnStopRequest [this=%p status=%u]\n",
   465        this, aChannelStatus));
   467   if (mDivertingToParent) {
   468     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
   469       "Should not be processing any more callbacks from parent!");
   471     SendDivertOnStopRequest(aChannelStatus);
   472     return;
   473   }
   475   if (!mCanceled)
   476     mStatus = aChannelStatus;
   478   { // Ensure that all queued ipdl events are dispatched before
   479     // we initiate protocol deletion below.
   480     mIsPending = false;
   481     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
   482     (void)mListener->OnStopRequest(this, mListenerContext, aChannelStatus);
   483     mListener = nullptr;
   484     mListenerContext = nullptr;
   486     if (mLoadGroup)
   487       mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus);
   488   }
   490   // This calls NeckoChild::DeallocPFTPChannelChild(), which deletes |this| if IPDL
   491   // holds the last reference.  Don't rely on |this| existing after here!
   492   Send__delete__(this);
   493 }
   495 class FTPFailedAsyncOpenEvent : public ChannelEvent
   496 {
   497  public:
   498   FTPFailedAsyncOpenEvent(FTPChannelChild* aChild, nsresult aStatus)
   499   : mChild(aChild), mStatus(aStatus) {}
   500   void Run() { mChild->DoFailedAsyncOpen(mStatus); }
   501  private:
   502   FTPChannelChild* mChild;
   503   nsresult mStatus;
   504 };
   506 bool
   507 FTPChannelChild::RecvFailedAsyncOpen(const nsresult& statusCode)
   508 {
   509   if (mEventQ->ShouldEnqueue()) {
   510     mEventQ->Enqueue(new FTPFailedAsyncOpenEvent(this, statusCode));
   511   } else {
   512     DoFailedAsyncOpen(statusCode);
   513   }
   514   return true;
   515 }
   517 void
   518 FTPChannelChild::DoFailedAsyncOpen(const nsresult& statusCode)
   519 {
   520   mStatus = statusCode;
   522   if (mLoadGroup)
   523     mLoadGroup->RemoveRequest(this, nullptr, statusCode);
   525   if (mListener) {
   526     mListener->OnStartRequest(this, mListenerContext);
   527     mIsPending = false;
   528     mListener->OnStopRequest(this, mListenerContext, statusCode);
   529   } else {
   530     mIsPending = false;
   531   }
   533   mListener = nullptr;
   534   mListenerContext = nullptr;
   536   if (mIPCOpen)
   537     Send__delete__(this);
   538 }
   540 class FTPFlushedForDiversionEvent : public ChannelEvent
   541 {
   542  public:
   543   FTPFlushedForDiversionEvent(FTPChannelChild* aChild)
   544   : mChild(aChild)
   545   {
   546     MOZ_RELEASE_ASSERT(aChild);
   547   }
   549   void Run()
   550   {
   551     mChild->FlushedForDiversion();
   552   }
   553  private:
   554   FTPChannelChild* mChild;
   555 };
   557 bool
   558 FTPChannelChild::RecvFlushedForDiversion()
   559 {
   560   MOZ_ASSERT(mDivertingToParent);
   562   if (mEventQ->ShouldEnqueue()) {
   563     mEventQ->Enqueue(new FTPFlushedForDiversionEvent(this));
   564   } else {
   565     MOZ_CRASH();
   566   }
   567   return true;
   568 }
   570 void
   571 FTPChannelChild::FlushedForDiversion()
   572 {
   573   MOZ_RELEASE_ASSERT(mDivertingToParent);
   575   // Once this is set, it should not be unset before FTPChannelChild is taken
   576   // down. After it is set, no OnStart/OnData/OnStop callbacks should be
   577   // received from the parent channel, nor dequeued from the ChannelEventQueue.
   578   mFlushedForDiversion = true;
   580   SendDivertComplete();
   581 }
   583 bool
   584 FTPChannelChild::RecvDivertMessages()
   585 {
   586   MOZ_RELEASE_ASSERT(mDivertingToParent);
   587   MOZ_RELEASE_ASSERT(mSuspendCount > 0);
   589   // DivertTo() has been called on parent, so we can now start sending queued
   590   // IPDL messages back to parent listener.
   591   if (NS_WARN_IF(NS_FAILED(Resume()))) {
   592     return false;
   593   }
   594   return true;
   595 }
   597 class FTPDeleteSelfEvent : public ChannelEvent
   598 {
   599  public:
   600   FTPDeleteSelfEvent(FTPChannelChild* aChild)
   601   : mChild(aChild) {}
   602   void Run() { mChild->DoDeleteSelf(); }
   603  private:
   604   FTPChannelChild* mChild;
   605 };
   607 bool
   608 FTPChannelChild::RecvDeleteSelf()
   609 {
   610   if (mEventQ->ShouldEnqueue()) {
   611     mEventQ->Enqueue(new FTPDeleteSelfEvent(this));
   612   } else {
   613     DoDeleteSelf();
   614   }
   615   return true;
   616 }
   618 void
   619 FTPChannelChild::DoDeleteSelf()
   620 {
   621   if (mIPCOpen)
   622     Send__delete__(this);
   623 }
   625 NS_IMETHODIMP
   626 FTPChannelChild::Cancel(nsresult status)
   627 {
   628   if (mCanceled)
   629     return NS_OK;
   631   mCanceled = true;
   632   mStatus = status;
   633   if (mIPCOpen)
   634     SendCancel(status);
   635   return NS_OK;
   636 }
   638 NS_IMETHODIMP
   639 FTPChannelChild::Suspend()
   640 {
   641   NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
   643   // SendSuspend only once, when suspend goes from 0 to 1.
   644   // Don't SendSuspend at all if we're diverting callbacks to the parent;
   645   // suspend will be called at the correct time in the parent itself.
   646   if (!mSuspendCount++ && !mDivertingToParent) {
   647     SendSuspend();
   648     mSuspendSent = true;
   649   }
   650   mEventQ->Suspend();
   652   return NS_OK;
   653 }
   655 NS_IMETHODIMP
   656 FTPChannelChild::Resume()
   657 {
   658   NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
   660   // SendResume only once, when suspend count drops to 0.
   661   // Don't SendResume at all if we're diverting callbacks to the parent (unless
   662   // suspend was sent earlier); otherwise, resume will be called at the correct
   663   // time in the parent itself.
   664   if (!--mSuspendCount && (!mDivertingToParent || mSuspendSent)) {
   665     SendResume();
   666   }
   667   mEventQ->Resume();
   669   return NS_OK;
   670 }
   672 //-----------------------------------------------------------------------------
   673 // FTPChannelChild::nsIChildChannel
   674 //-----------------------------------------------------------------------------
   676 NS_IMETHODIMP
   677 FTPChannelChild::ConnectParent(uint32_t id)
   678 {
   679   mozilla::dom::TabChild* tabChild = nullptr;
   680   nsCOMPtr<nsITabChild> iTabChild;
   681   NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
   682                                 NS_GET_IID(nsITabChild),
   683                                 getter_AddRefs(iTabChild));
   684   GetCallback(iTabChild);
   685   if (iTabChild) {
   686     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
   687   }
   689   // The socket transport in the chrome process now holds a logical ref to us
   690   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
   691   AddIPDLReference();
   693   FTPChannelConnectArgs connectArgs(id);
   695   if (!gNeckoChild->SendPFTPChannelConstructor(this, tabChild,
   696                                                IPC::SerializedLoadContext(this),
   697                                                connectArgs)) {
   698     return NS_ERROR_FAILURE;
   699   }
   701   return NS_OK;
   702 }
   704 NS_IMETHODIMP
   705 FTPChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
   706                                        nsISupports *aContext)
   707 {
   708   LOG(("FTPChannelChild::CompleteRedirectSetup [this=%p]\n", this));
   710   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   711   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
   713   mIsPending = true;
   714   mWasOpened = true;
   715   mListener = listener;
   716   mListenerContext = aContext;
   718   // add ourselves to the load group.
   719   if (mLoadGroup)
   720     mLoadGroup->AddRequest(this, nullptr);
   722   // We already have an open IPDL connection to the parent. If on-modify-request
   723   // listeners or load group observers canceled us, let the parent handle it
   724   // and send it back to us naturally.
   725   return NS_OK;
   726 }
   728 //-----------------------------------------------------------------------------
   729 // FTPChannelChild::nsIDivertableChannel
   730 //-----------------------------------------------------------------------------
   731 NS_IMETHODIMP
   732 FTPChannelChild::DivertToParent(ChannelDiverterChild **aChild)
   733 {
   734   MOZ_RELEASE_ASSERT(aChild);
   735   MOZ_RELEASE_ASSERT(gNeckoChild);
   736   MOZ_RELEASE_ASSERT(!mDivertingToParent);
   738   // We must fail DivertToParent() if there's no parent end of the channel (and
   739   // won't be!) due to early failure.
   740   if (NS_FAILED(mStatus) && !mIPCOpen) {
   741     return mStatus;
   742   }
   744   nsresult rv = Suspend();
   745   if (NS_WARN_IF(NS_FAILED(rv))) {
   746     return rv;
   747   }
   749   // Once this is set, it should not be unset before the child is taken down.
   750   mDivertingToParent = true;
   752   PChannelDiverterChild* diverter =
   753     gNeckoChild->SendPChannelDiverterConstructor(this);
   754   MOZ_RELEASE_ASSERT(diverter);
   756   *aChild = static_cast<ChannelDiverterChild*>(diverter);
   758   return NS_OK;
   759 }
   761 } // namespace net
   762 } // namespace mozilla

mercurial