Blame netwerk/protocol/ftp/FTPChannelChild.cpp

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