tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DNSRequestChild.cpp (18800B)


      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 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/ContentChild.h"
      8 #include "mozilla/net/ChildDNSService.h"
      9 #include "mozilla/net/DNSByTypeRecord.h"
     10 #include "mozilla/net/DNSRequestChild.h"
     11 #include "mozilla/net/DNSRequestParent.h"
     12 #include "mozilla/net/NeckoChild.h"
     13 #include "mozilla/net/SocketProcessChild.h"
     14 #include "mozilla/SchedulerGroup.h"
     15 #include "mozilla/net/SocketProcessParent.h"
     16 #include "nsIDNSRecord.h"
     17 #include "nsIDNSByTypeRecord.h"
     18 #include "nsHostResolver.h"
     19 #include "nsIOService.h"
     20 #include "nsTArray.h"
     21 #include "nsNetAddr.h"
     22 #include "nsThreadUtils.h"
     23 
     24 using namespace mozilla::ipc;
     25 
     26 namespace mozilla {
     27 namespace net {
     28 
     29 void DNSRequestBase::SetIPCActor(DNSRequestActor* aActor) {
     30  mIPCActor = aActor;
     31 }
     32 
     33 //-----------------------------------------------------------------------------
     34 // ChildDNSRecord:
     35 // A simple class to provide nsIDNSRecord on the child
     36 //-----------------------------------------------------------------------------
     37 
     38 class ChildDNSRecord : public nsIDNSAddrRecord {
     39 public:
     40  NS_DECL_THREADSAFE_ISUPPORTS
     41  NS_DECL_NSIDNSRECORD
     42  NS_DECL_NSIDNSADDRRECORD
     43 
     44  ChildDNSRecord(const DNSRecord& reply, nsIDNSService::DNSFlags flags);
     45 
     46 private:
     47  virtual ~ChildDNSRecord() = default;
     48 
     49  nsCString mCanonicalName;
     50  nsTArray<NetAddr> mAddresses;
     51  uint32_t mCurrent = 0;  // addr iterator
     52  nsIDNSService::DNSFlags mFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
     53  double mTrrFetchDuration = 0;
     54  double mTrrFetchDurationNetworkOnly = 0;
     55  bool mIsTRR = false;
     56  bool mResolvedInSocketProcess = false;
     57  nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE;
     58  nsITRRSkipReason::value mTRRSkipReason = nsITRRSkipReason::TRR_UNSET;
     59  uint32_t mTTL = 0;
     60  TimeStamp mLastUpdate = mozilla::TimeStamp::NowLoRes();
     61 };
     62 
     63 NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord, nsIDNSAddrRecord)
     64 
     65 ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply,
     66                               nsIDNSService::DNSFlags flags)
     67    : mFlags(flags) {
     68  mCanonicalName = reply.canonicalName();
     69  mTrrFetchDuration = reply.trrFetchDuration();
     70  mTrrFetchDurationNetworkOnly = reply.trrFetchDurationNetworkOnly();
     71  mIsTRR = reply.isTRR();
     72  // When ChildDNSRecord is created in parent process, we know this is case that
     73  // DNS resolution is done in socket process.
     74  mResolvedInSocketProcess = XRE_IsParentProcess();
     75  mEffectiveTRRMode = reply.effectiveTRRMode();
     76 
     77  // A shame IPDL gives us no way to grab ownership of array: so copy it.
     78  const nsTArray<NetAddr>& addrs = reply.addrs();
     79  mAddresses = addrs.Clone();
     80  mTTL = reply.ttl();
     81  mLastUpdate = reply.lastUpdate();
     82 }
     83 
     84 //-----------------------------------------------------------------------------
     85 // ChildDNSRecord::nsIDNSAddrRecord
     86 //-----------------------------------------------------------------------------
     87 
     88 NS_IMETHODIMP
     89 ChildDNSRecord::GetCanonicalName(nsACString& result) {
     90  if (!(mFlags & nsIDNSService::RESOLVE_CANONICAL_NAME)) {
     91    return NS_ERROR_NOT_AVAILABLE;
     92  }
     93 
     94  result = mCanonicalName;
     95  return NS_OK;
     96 }
     97 
     98 NS_IMETHODIMP
     99 ChildDNSRecord::IsTRR(bool* retval) {
    100  *retval = mIsTRR;
    101  return NS_OK;
    102 }
    103 
    104 NS_IMETHODIMP
    105 ChildDNSRecord::ResolvedInSocketProcess(bool* retval) {
    106  *retval = mResolvedInSocketProcess;
    107  return NS_OK;
    108 }
    109 
    110 NS_IMETHODIMP
    111 ChildDNSRecord::GetTrrFetchDuration(double* aTime) {
    112  *aTime = mTrrFetchDuration;
    113  return NS_OK;
    114 }
    115 
    116 NS_IMETHODIMP
    117 ChildDNSRecord::GetTrrFetchDurationNetworkOnly(double* aTime) {
    118  *aTime = mTrrFetchDurationNetworkOnly;
    119  return NS_OK;
    120 }
    121 
    122 NS_IMETHODIMP
    123 ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr* addr) {
    124  if (mCurrent >= mAddresses.Length()) {
    125    return NS_ERROR_NOT_AVAILABLE;
    126  }
    127 
    128  *addr = mAddresses[mCurrent++];
    129 
    130  // both Ipv4/6 use same bits for port, so safe to just use ipv4's field
    131  addr->inet.port = htons(port);
    132 
    133  return NS_OK;
    134 }
    135 
    136 NS_IMETHODIMP
    137 ChildDNSRecord::GetAddresses(nsTArray<NetAddr>& aAddressArray) {
    138  aAddressArray = mAddresses.Clone();
    139  return NS_OK;
    140 }
    141 
    142 // shamelessly copied from nsDNSRecord
    143 NS_IMETHODIMP
    144 ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr** result) {
    145  NetAddr addr;
    146  nsresult rv = GetNextAddr(port, &addr);
    147  if (NS_FAILED(rv)) {
    148    return rv;
    149  }
    150 
    151  RefPtr<nsNetAddr> netaddr = new nsNetAddr(&addr);
    152  netaddr.forget(result);
    153 
    154  return NS_OK;
    155 }
    156 
    157 // also copied from nsDNSRecord
    158 NS_IMETHODIMP
    159 ChildDNSRecord::GetNextAddrAsString(nsACString& result) {
    160  NetAddr addr;
    161  nsresult rv = GetNextAddr(0, &addr);
    162  if (NS_FAILED(rv)) {
    163    return rv;
    164  }
    165 
    166  char buf[kIPv6CStrBufSize];
    167  if (addr.ToStringBuffer(buf, sizeof(buf))) {
    168    result.Assign(buf);
    169    return NS_OK;
    170  }
    171  NS_ERROR("NetAddrToString failed unexpectedly");
    172  return NS_ERROR_FAILURE;  // conversion failed for some reason
    173 }
    174 
    175 NS_IMETHODIMP
    176 ChildDNSRecord::HasMore(bool* result) {
    177  *result = mCurrent < mAddresses.Length();
    178  return NS_OK;
    179 }
    180 
    181 NS_IMETHODIMP
    182 ChildDNSRecord::Rewind() {
    183  mCurrent = 0;
    184  return NS_OK;
    185 }
    186 
    187 NS_IMETHODIMP
    188 ChildDNSRecord::ReportUnusable(uint16_t aPort) {
    189  // "We thank you for your feedback" == >/dev/null
    190  // TODO: we could send info back to parent.
    191  return NS_OK;
    192 }
    193 
    194 NS_IMETHODIMP
    195 ChildDNSRecord::GetEffectiveTRRMode(nsIRequest::TRRMode* aMode) {
    196  *aMode = mEffectiveTRRMode;
    197  return NS_OK;
    198 }
    199 
    200 NS_IMETHODIMP ChildDNSRecord::GetTrrSkipReason(
    201    nsITRRSkipReason::value* aTrrSkipReason) {
    202  *aTrrSkipReason = mTRRSkipReason;
    203  return NS_OK;
    204 }
    205 
    206 NS_IMETHODIMP
    207 ChildDNSRecord::GetTtl(uint32_t* aTtl) {
    208  *aTtl = mTTL;
    209  return NS_OK;
    210 }
    211 
    212 NS_IMETHODIMP
    213 ChildDNSRecord::GetLastUpdate(TimeStamp* aLastUpdate) {
    214  *aLastUpdate = mLastUpdate;
    215  return NS_OK;
    216 }
    217 
    218 class ChildDNSByTypeRecord : public nsIDNSByTypeRecord,
    219                             public nsIDNSTXTRecord,
    220                             public nsIDNSHTTPSSVCRecord,
    221                             public DNSHTTPSSVCRecordBase {
    222 public:
    223  NS_DECL_THREADSAFE_ISUPPORTS
    224  NS_DECL_NSIDNSRECORD
    225  NS_DECL_NSIDNSBYTYPERECORD
    226  NS_DECL_NSIDNSTXTRECORD
    227  NS_DECL_NSIDNSHTTPSSVCRECORD
    228 
    229  explicit ChildDNSByTypeRecord(const TypeRecordResultType& reply,
    230                                const nsACString& aHost, uint32_t aTTL,
    231                                bool aIsTRR);
    232 
    233 private:
    234  virtual ~ChildDNSByTypeRecord() = default;
    235 
    236  TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
    237  bool mAllRecordsExcluded = false;
    238  uint32_t mTTL = 0;
    239  bool mIsTRR = false;
    240 };
    241 
    242 NS_IMPL_ISUPPORTS(ChildDNSByTypeRecord, nsIDNSByTypeRecord, nsIDNSRecord,
    243                  nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
    244 
    245 ChildDNSByTypeRecord::ChildDNSByTypeRecord(const TypeRecordResultType& reply,
    246                                           const nsACString& aHost,
    247                                           uint32_t aTTL, bool aIsTRR)
    248    : DNSHTTPSSVCRecordBase(aHost) {
    249  mResults = reply;
    250  mTTL = aTTL;
    251  mIsTRR = aIsTRR;
    252 }
    253 
    254 NS_IMETHODIMP
    255 ChildDNSByTypeRecord::GetType(uint32_t* aType) {
    256  *aType = mResults.match(
    257      [](TypeRecordEmpty&) {
    258        MOZ_ASSERT(false, "This should never be the case");
    259        return nsIDNSService::RESOLVE_TYPE_DEFAULT;
    260      },
    261      [](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
    262      [](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
    263  return NS_OK;
    264 }
    265 
    266 NS_IMETHODIMP
    267 ChildDNSByTypeRecord::GetRecords(CopyableTArray<nsCString>& aRecords) {
    268  if (!mResults.is<TypeRecordTxt>()) {
    269    return NS_ERROR_NOT_AVAILABLE;
    270  }
    271  aRecords = mResults.as<CopyableTArray<nsCString>>();
    272  return NS_OK;
    273 }
    274 
    275 NS_IMETHODIMP
    276 ChildDNSByTypeRecord::GetRecordsAsOneString(nsACString& aRecords) {
    277  // deep copy
    278  if (!mResults.is<TypeRecordTxt>()) {
    279    return NS_ERROR_NOT_AVAILABLE;
    280  }
    281  auto& results = mResults.as<CopyableTArray<nsCString>>();
    282  for (uint32_t i = 0; i < results.Length(); i++) {
    283    aRecords.Append(results[i]);
    284  }
    285  return NS_OK;
    286 }
    287 
    288 NS_IMETHODIMP
    289 ChildDNSByTypeRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
    290  if (!mResults.is<TypeRecordHTTPSSVC>()) {
    291    return NS_ERROR_NOT_AVAILABLE;
    292  }
    293 
    294  auto& results = mResults.as<TypeRecordHTTPSSVC>();
    295 
    296  for (const SVCB& r : results) {
    297    RefPtr<nsISVCBRecord> rec = new SVCBRecord(r);
    298    aRecords.AppendElement(rec);
    299  }
    300  return NS_OK;
    301 }
    302 
    303 NS_IMETHODIMP
    304 ChildDNSByTypeRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3,
    305                                           nsISVCBRecord** aRecord) {
    306  return GetServiceModeRecordWithCname(aNoHttp2, aNoHttp3, ""_ns, aRecord);
    307 }
    308 
    309 NS_IMETHODIMP
    310 ChildDNSByTypeRecord::IsTRR(bool* aResult) {
    311  *aResult = mIsTRR;
    312  return NS_OK;
    313 }
    314 
    315 NS_IMETHODIMP
    316 ChildDNSByTypeRecord::GetServiceModeRecordWithCname(bool aNoHttp2,
    317                                                    bool aNoHttp3,
    318                                                    const nsACString& aCname,
    319                                                    nsISVCBRecord** aRecord) {
    320  if (!mResults.is<TypeRecordHTTPSSVC>()) {
    321    return NS_ERROR_NOT_AVAILABLE;
    322  }
    323 
    324  auto& results = mResults.as<TypeRecordHTTPSSVC>();
    325  nsCOMPtr<nsISVCBRecord> result = GetServiceModeRecordInternal(
    326      aNoHttp2, aNoHttp3, results, mAllRecordsExcluded, true, aCname);
    327  if (!result) {
    328    return NS_ERROR_NOT_AVAILABLE;
    329  }
    330 
    331  result.forget(aRecord);
    332  return NS_OK;
    333 }
    334 
    335 NS_IMETHODIMP
    336 ChildDNSByTypeRecord::GetAllRecords(bool aNoHttp2, bool aNoHttp3,
    337                                    const nsACString& aCname,
    338                                    nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
    339  if (!mResults.is<TypeRecordHTTPSSVC>()) {
    340    return NS_ERROR_NOT_AVAILABLE;
    341  }
    342 
    343  auto& records = mResults.as<TypeRecordHTTPSSVC>();
    344  bool notused;
    345  GetAllRecordsInternal(aNoHttp2, aNoHttp3, aCname, records, false, &notused,
    346                        &notused, aResult);
    347  return NS_OK;
    348 }
    349 
    350 NS_IMETHODIMP
    351 ChildDNSByTypeRecord::GetAllRecordsWithEchConfig(
    352    bool aNoHttp2, bool aNoHttp3, const nsACString& aCname,
    353    bool* aAllRecordsHaveEchConfig, bool* aAllRecordsInH3ExcludedList,
    354    nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
    355  if (!mResults.is<TypeRecordHTTPSSVC>()) {
    356    return NS_ERROR_NOT_AVAILABLE;
    357  }
    358 
    359  auto& records = mResults.as<TypeRecordHTTPSSVC>();
    360  GetAllRecordsInternal(aNoHttp2, aNoHttp3, aCname, records, true,
    361                        aAllRecordsHaveEchConfig, aAllRecordsInH3ExcludedList,
    362                        aResult);
    363  return NS_OK;
    364 }
    365 
    366 NS_IMETHODIMP
    367 ChildDNSByTypeRecord::GetHasIPAddresses(bool* aResult) {
    368  NS_ENSURE_ARG(aResult);
    369 
    370  if (!mResults.is<TypeRecordHTTPSSVC>()) {
    371    return NS_ERROR_NOT_AVAILABLE;
    372  }
    373 
    374  auto& results = mResults.as<TypeRecordHTTPSSVC>();
    375  *aResult = HasIPAddressesInternal(results);
    376  return NS_OK;
    377 }
    378 
    379 NS_IMETHODIMP
    380 ChildDNSByTypeRecord::GetAllRecordsExcluded(bool* aResult) {
    381  NS_ENSURE_ARG(aResult);
    382 
    383  if (!mResults.is<TypeRecordHTTPSSVC>()) {
    384    return NS_ERROR_NOT_AVAILABLE;
    385  }
    386 
    387  *aResult = mAllRecordsExcluded;
    388  return NS_OK;
    389 }
    390 
    391 NS_IMETHODIMP
    392 ChildDNSByTypeRecord::GetResults(mozilla::net::TypeRecordResultType* aResults) {
    393  *aResults = mResults;
    394  return NS_OK;
    395 }
    396 
    397 NS_IMETHODIMP
    398 ChildDNSByTypeRecord::GetTtl(uint32_t* aResult) {
    399  *aResult = mTTL;
    400  return NS_OK;
    401 }
    402 
    403 //-----------------------------------------------------------------------------
    404 // DNSRequestSender
    405 //-----------------------------------------------------------------------------
    406 
    407 NS_IMPL_ISUPPORTS(DNSRequestSender, nsICancelable)
    408 
    409 DNSRequestSender::DNSRequestSender(const nsACString& aHost,
    410                                   const nsACString& aTrrServer, int32_t aPort,
    411                                   const uint16_t& aType,
    412                                   const OriginAttributes& aOriginAttributes,
    413                                   const nsIDNSService::DNSFlags& aFlags,
    414                                   nsIDNSListener* aListener,
    415                                   nsIEventTarget* target)
    416    : mListener(aListener),
    417      mTarget(target),
    418      mResultStatus(NS_OK),
    419      mHost(aHost),
    420      mTrrServer(aTrrServer),
    421      mPort(aPort),
    422      mType(aType),
    423      mOriginAttributes(aOriginAttributes),
    424      mFlags(aFlags) {}
    425 
    426 void DNSRequestSender::OnRecvCancelDNSRequest(
    427    const nsCString& hostName, const nsCString& trrServer, const int32_t& port,
    428    const uint16_t& type, const OriginAttributes& originAttributes,
    429    const nsIDNSService::DNSFlags& flags, const nsresult& reason) {}
    430 
    431 NS_IMETHODIMP
    432 DNSRequestSender::Cancel(nsresult reason) {
    433  // we can only do IPC on the MainThread
    434  if (!NS_IsMainThread()) {
    435    SchedulerGroup::Dispatch(
    436        NewRunnableMethod<nsresult>("net::DNSRequestSender::Cancel", this,
    437                                    &DNSRequestSender::Cancel, reason));
    438    return NS_OK;
    439  }
    440 
    441  if (!mIPCActor || !mIPCActor->CanSend()) {
    442    // Really a failure, but we won't be able to tell anyone about it anyways
    443    return NS_OK;
    444  }
    445 
    446  if (DNSRequestChild* child = mIPCActor->AsDNSRequestChild()) {
    447    (void)child->SendCancelDNSRequest(mHost, mTrrServer, mPort, mType,
    448                                      mOriginAttributes, mFlags, reason);
    449  } else if (DNSRequestParent* parent = mIPCActor->AsDNSRequestParent()) {
    450    (void)parent->SendCancelDNSRequest(mHost, mTrrServer, mPort, mType,
    451                                       mOriginAttributes, mFlags, reason);
    452  }
    453 
    454  return NS_OK;
    455 }
    456 
    457 void DNSRequestSender::StartRequest() {
    458  // we can only do IPC on the MainThread
    459  if (!NS_IsMainThread()) {
    460    SchedulerGroup::Dispatch(
    461        NewRunnableMethod("net::DNSRequestSender::StartRequest", this,
    462                          &DNSRequestSender::StartRequest));
    463    return;
    464  }
    465 
    466  if (RefPtr<DNSRequestChild> child = mIPCActor->AsDNSRequestChild()) {
    467    if (XRE_IsContentProcess()) {
    468      mozilla::dom::ContentChild* cc =
    469          static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
    470      if (cc->IsShuttingDown()) {
    471        return;
    472      }
    473 
    474      // Send request to Parent process.
    475      gNeckoChild->SendPDNSRequestConstructor(child, mHost, mTrrServer, mPort,
    476                                              mType, mOriginAttributes, mFlags);
    477    } else if (XRE_IsSocketProcess()) {
    478      // DNS resolution is done in the parent process. Send a DNS request to
    479      // parent process.
    480      MOZ_ASSERT(!nsIOService::UseSocketProcess());
    481 
    482      SocketProcessChild* socketProcessChild =
    483          SocketProcessChild::GetSingleton();
    484      if (!socketProcessChild->CanSend()) {
    485        return;
    486      }
    487 
    488      MOZ_ALWAYS_TRUE(socketProcessChild->SendPDNSRequestConstructor(
    489          child, mHost, mTrrServer, mPort, mType, mOriginAttributes, mFlags));
    490    } else {
    491      MOZ_ASSERT(false, "Wrong process");
    492      return;
    493    }
    494  } else if (DNSRequestParent* parent = mIPCActor->AsDNSRequestParent()) {
    495    // DNS resolution is done in the socket process. Send a DNS request to
    496    // socket process.
    497    MOZ_ASSERT(nsIOService::UseSocketProcess());
    498 
    499    RefPtr<DNSRequestParent> requestParent = parent;
    500    RefPtr<DNSRequestSender> self = this;
    501    auto task = [requestParent, self]() {
    502      RefPtr<SocketProcessParent> socketParent =
    503          SocketProcessParent::GetSingleton();
    504      (void)socketParent->SendPDNSRequestConstructor(
    505          requestParent, self->mHost, self->mTrrServer, self->mPort,
    506          self->mType, self->mOriginAttributes, self->mFlags);
    507    };
    508    if (!gIOService->SocketProcessReady()) {
    509      gIOService->CallOrWaitForSocketProcess(std::move(task));
    510      return;
    511    }
    512 
    513    task();
    514  }
    515 }
    516 
    517 void DNSRequestSender::CallOnLookupComplete() {
    518  MOZ_ASSERT(mListener);
    519  mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
    520 }
    521 
    522 bool DNSRequestSender::OnRecvLookupCompleted(const DNSRequestResponse& reply) {
    523  MOZ_ASSERT(mListener);
    524 
    525  switch (reply.type()) {
    526    case DNSRequestResponse::TDNSRecord: {
    527      mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags);
    528      break;
    529    }
    530    case DNSRequestResponse::Tnsresult: {
    531      mResultStatus = reply.get_nsresult();
    532      break;
    533    }
    534    case DNSRequestResponse::TIPCTypeRecord: {
    535      MOZ_ASSERT(mType != nsIDNSService::RESOLVE_TYPE_DEFAULT);
    536      mResultRecord = new ChildDNSByTypeRecord(
    537          reply.get_IPCTypeRecord().mData, mHost,
    538          reply.get_IPCTypeRecord().mTTL, reply.get_IPCTypeRecord().mIsTRR);
    539      break;
    540    }
    541    default:
    542      MOZ_ASSERT_UNREACHABLE("unknown type");
    543      return false;
    544  }
    545 
    546  MOZ_ASSERT(NS_IsMainThread());
    547 
    548  bool targetIsMain = false;
    549  if (!mTarget) {
    550    targetIsMain = true;
    551  } else {
    552    mTarget->IsOnCurrentThread(&targetIsMain);
    553  }
    554 
    555  if (targetIsMain) {
    556    CallOnLookupComplete();
    557  } else {
    558    nsCOMPtr<nsIRunnable> event =
    559        NewRunnableMethod("net::DNSRequestSender::CallOnLookupComplete", this,
    560                          &DNSRequestSender::CallOnLookupComplete);
    561    mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
    562  }
    563 
    564  if (DNSRequestChild* child = mIPCActor->AsDNSRequestChild()) {
    565    (void)mozilla::net::DNSRequestChild::Send__delete__(child);
    566  } else if (DNSRequestParent* parent = mIPCActor->AsDNSRequestParent()) {
    567    (void)mozilla::net::DNSRequestParent::Send__delete__(parent);
    568  }
    569 
    570  return true;
    571 }
    572 
    573 void DNSRequestSender::OnIPCActorDestroy() {
    574  // Request is done or destroyed. Remove it from the hash table.
    575  RefPtr<ChildDNSService> dnsServiceChild =
    576      dont_AddRef(ChildDNSService::GetSingleton());
    577  dnsServiceChild->NotifyRequestDone(this);
    578 
    579  mIPCActor = nullptr;
    580 }
    581 
    582 //-----------------------------------------------------------------------------
    583 // DNSRequestChild
    584 //-----------------------------------------------------------------------------
    585 
    586 DNSRequestChild::DNSRequestChild(DNSRequestBase* aRequest)
    587    : DNSRequestActor(aRequest) {
    588  aRequest->SetIPCActor(this);
    589 }
    590 
    591 mozilla::ipc::IPCResult DNSRequestChild::RecvCancelDNSRequest(
    592    const nsCString& hostName, const nsCString& trrServer, const int32_t& port,
    593    const uint16_t& type, const OriginAttributes& originAttributes,
    594    const nsIDNSService::DNSFlags& flags, const nsresult& reason) {
    595  mDNSRequest->OnRecvCancelDNSRequest(hostName, trrServer, port, type,
    596                                      originAttributes, flags, reason);
    597  return IPC_OK();
    598 }
    599 
    600 mozilla::ipc::IPCResult DNSRequestChild::RecvLookupCompleted(
    601    const DNSRequestResponse& reply) {
    602  return mDNSRequest->OnRecvLookupCompleted(reply) ? IPC_OK()
    603                                                   : IPC_FAIL_NO_REASON(this);
    604 }
    605 
    606 void DNSRequestChild::ActorDestroy(ActorDestroyReason) {
    607  mDNSRequest->OnIPCActorDestroy();
    608  mDNSRequest = nullptr;
    609 }
    610 
    611 //------------------------------------------------------------------------------
    612 }  // namespace net
    613 }  // namespace mozilla