tor-browser

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

NeckoParent.cpp (35751B)


      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 "nsBaseParentChannel.h"
      9 #include "nsHttp.h"
     10 #include "mozilla/BasePrincipal.h"
     11 #include "mozilla/Components.h"
     12 #include "mozilla/ContentPrincipal.h"
     13 #include "mozilla/NullPrincipal.h"
     14 #include "mozilla/ipc/IPCStreamUtils.h"
     15 #include "mozilla/net/ExtensionProtocolHandler.h"
     16 #include "mozilla/net/PageThumbProtocolHandler.h"
     17 #include "mozilla/net/MozNewTabWallpaperProtocolHandler.h"
     18 #include "mozilla/net/NeckoParent.h"
     19 #include "mozilla/net/HttpChannelParent.h"
     20 #include "mozilla/net/CookieServiceParent.h"
     21 #include "mozilla/net/WebSocketChannelParent.h"
     22 #include "mozilla/net/WebSocketEventListenerParent.h"
     23 #ifdef MOZ_WIDGET_GTK
     24 #  include "mozilla/net/GIOChannelParent.h"
     25 #endif
     26 #ifdef MOZ_WIDGET_ANDROID
     27 #  include "mozilla/net/GeckoViewContentChannelParent.h"
     28 #endif
     29 #include "mozilla/net/DocumentChannelParent.h"
     30 #include "mozilla/net/CacheEntryWriteHandleParent.h"
     31 #include "mozilla/net/AltDataOutputStreamParent.h"
     32 #include "mozilla/net/DNSRequestParent.h"
     33 #include "mozilla/net/IPCTransportProvider.h"
     34 #include "mozilla/net/RemoteStreamGetter.h"
     35 #include "mozilla/net/RequestContextService.h"
     36 #include "mozilla/net/SocketProcessParent.h"
     37 #include "mozilla/net/PSocketProcessBridgeParent.h"
     38 #ifdef MOZ_WEBRTC
     39 #  include "mozilla/net/StunAddrsRequestParent.h"
     40 #  include "mozilla/net/WebrtcTCPSocketParent.h"
     41 #endif
     42 #include "mozilla/dom/ContentParent.h"
     43 #include "mozilla/dom/BrowserParent.h"
     44 #include "mozilla/dom/MaybeDiscarded.h"
     45 #include "mozilla/dom/network/TCPSocketParent.h"
     46 #include "mozilla/dom/network/TCPServerSocketParent.h"
     47 #include "mozilla/dom/network/UDPSocketParent.h"
     48 #ifdef MOZ_PLACES
     49 #  include "mozilla/places/PageIconProtocolHandler.h"
     50 #endif
     51 #include "mozilla/LoadContext.h"
     52 #include "mozilla/MozPromise.h"
     53 #include "nsPrintfCString.h"
     54 #include "mozilla/dom/HTMLDNSPrefetch.h"
     55 #include "nsEscape.h"
     56 #include "SerializedLoadContext.h"
     57 #include "nsAuthInformationHolder.h"
     58 #include "nsISpeculativeConnect.h"
     59 #include "nsFileChannel.h"
     60 #include "nsHttpHandler.h"
     61 #include "nsIMIMEService.h"
     62 #include "nsNetUtil.h"
     63 #include "nsIOService.h"
     64 
     65 using IPC::SerializedLoadContext;
     66 using mozilla::dom::BrowserParent;
     67 using mozilla::dom::ContentParent;
     68 using mozilla::dom::TCPServerSocketParent;
     69 using mozilla::dom::TCPSocketParent;
     70 using mozilla::dom::UDPSocketParent;
     71 using mozilla::ipc::LoadInfoArgsToLoadInfo;
     72 using mozilla::ipc::PrincipalInfo;
     73 #ifdef MOZ_PLACES
     74 using mozilla::places::PageIconProtocolHandler;
     75 #endif
     76 
     77 namespace mozilla {
     78 namespace net {
     79 
     80 // C++ file contents
     81 NeckoParent::NeckoParent() : mSocketProcessBridgeInited(false) {
     82  // Init HTTP protocol handler now since we need atomTable up and running very
     83  // early (IPDL argument handling for PHttpChannel constructor needs it) so
     84  // normal init (during 1st Http channel request) isn't early enough.
     85  nsCOMPtr<nsIProtocolHandler> proto =
     86      do_GetService("@mozilla.org/network/protocol;1?name=http");
     87 }
     88 
     89 static PBOverrideStatus PBOverrideStatusFromLoadContext(
     90    const SerializedLoadContext& aSerialized) {
     91  if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) {
     92    return aSerialized.mOriginAttributes.IsPrivateBrowsing()
     93               ? kPBOverride_Private
     94               : kPBOverride_NotPrivate;
     95  }
     96  return kPBOverride_Unset;
     97 }
     98 
     99 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
    100    const LoadInfoArgs& aLoadInfoArgs) {
    101  const Maybe<PrincipalInfo>& optionalPrincipalInfo =
    102      aLoadInfoArgs.requestingPrincipalInfo();
    103 
    104  if (optionalPrincipalInfo.isNothing()) {
    105    return nullptr;
    106  }
    107 
    108  const PrincipalInfo& principalInfo = optionalPrincipalInfo.ref();
    109 
    110  auto principalOrErr = PrincipalInfoToPrincipal(principalInfo);
    111  return principalOrErr.isOk() ? principalOrErr.unwrap().forget() : nullptr;
    112 }
    113 
    114 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
    115    const HttpChannelCreationArgs& aArgs) {
    116  if (aArgs.type() != HttpChannelCreationArgs::THttpChannelOpenArgs) {
    117    return nullptr;
    118  }
    119 
    120  const HttpChannelOpenArgs& args = aArgs.get_HttpChannelOpenArgs();
    121  return GetRequestingPrincipal(args.loadInfo());
    122 }
    123 
    124 void NeckoParent::GetValidatedOriginAttributes(
    125    const SerializedLoadContext& aSerialized, PContentParent* aContent,
    126    nsIPrincipal* aRequestingPrincipal, OriginAttributes& aAttrs) {
    127  if (!aSerialized.IsNotNull()) {
    128    // If serialized is null, we cannot validate anything. We have to assume
    129    // that this requests comes from a SystemPrincipal.
    130    aAttrs = OriginAttributes();
    131  } else {
    132    aAttrs = aSerialized.mOriginAttributes;
    133  }
    134 }
    135 
    136 void NeckoParent::CreateChannelLoadContext(
    137    PBrowserParent* aBrowser, PContentParent* aContent,
    138    const SerializedLoadContext& aSerialized,
    139    nsIPrincipal* aRequestingPrincipal, nsCOMPtr<nsILoadContext>& aResult) {
    140  OriginAttributes attrs;
    141  GetValidatedOriginAttributes(aSerialized, aContent, aRequestingPrincipal,
    142                               attrs);
    143 
    144  if (aSerialized.IsNotNull()) {
    145    attrs.SyncAttributesWithPrivateBrowsing(
    146        aSerialized.mOriginAttributes.IsPrivateBrowsing());
    147 
    148    RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(aBrowser);
    149    dom::Element* topFrameElement = nullptr;
    150    if (browserParent) {
    151      topFrameElement = browserParent->GetOwnerElement();
    152    }
    153    aResult = new LoadContext(aSerialized, topFrameElement, attrs);
    154  }
    155 }
    156 
    157 void NeckoParent::ActorDestroy(ActorDestroyReason aWhy) {
    158  // Nothing needed here. Called right before destructor since this is a
    159  // non-refcounted class.
    160 }
    161 
    162 already_AddRefed<PHttpChannelParent> NeckoParent::AllocPHttpChannelParent(
    163    PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
    164    const HttpChannelCreationArgs& aOpenArgs) {
    165  nsCOMPtr<nsIPrincipal> requestingPrincipal =
    166      GetRequestingPrincipal(aOpenArgs);
    167 
    168  nsCOMPtr<nsILoadContext> loadContext;
    169  CreateChannelLoadContext(aBrowser, Manager(), aSerialized,
    170                           requestingPrincipal, loadContext);
    171  PBOverrideStatus overrideStatus =
    172      PBOverrideStatusFromLoadContext(aSerialized);
    173  RefPtr<HttpChannelParent> p = new HttpChannelParent(
    174      BrowserParent::GetFrom(aBrowser), loadContext, overrideStatus);
    175  return p.forget();
    176 }
    177 
    178 mozilla::ipc::IPCResult NeckoParent::RecvPHttpChannelConstructor(
    179    PHttpChannelParent* aActor, PBrowserParent* aBrowser,
    180    const SerializedLoadContext& aSerialized,
    181    const HttpChannelCreationArgs& aOpenArgs) {
    182  HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor);
    183  if (!p->Init(aOpenArgs)) {
    184    return IPC_FAIL_NO_REASON(this);
    185  }
    186  return IPC_OK();
    187 }
    188 
    189 PStunAddrsRequestParent* NeckoParent::AllocPStunAddrsRequestParent() {
    190 #ifdef MOZ_WEBRTC
    191  StunAddrsRequestParent* p = new StunAddrsRequestParent();
    192  p->AddRef();
    193  return p;
    194 #else
    195  return nullptr;
    196 #endif
    197 }
    198 
    199 bool NeckoParent::DeallocPStunAddrsRequestParent(
    200    PStunAddrsRequestParent* aActor) {
    201 #ifdef MOZ_WEBRTC
    202  StunAddrsRequestParent* p = static_cast<StunAddrsRequestParent*>(aActor);
    203  p->Release();
    204 #endif
    205  return true;
    206 }
    207 
    208 PWebrtcTCPSocketParent* NeckoParent::AllocPWebrtcTCPSocketParent(
    209    const Maybe<TabId>& aTabId) {
    210 #ifdef MOZ_WEBRTC
    211  WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId);
    212  parent->AddRef();
    213  return parent;
    214 #else
    215  return nullptr;
    216 #endif
    217 }
    218 
    219 bool NeckoParent::DeallocPWebrtcTCPSocketParent(
    220    PWebrtcTCPSocketParent* aActor) {
    221 #ifdef MOZ_WEBRTC
    222  WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor);
    223  parent->Release();
    224 #endif
    225  return true;
    226 }
    227 
    228 PCacheEntryWriteHandleParent* NeckoParent::AllocPCacheEntryWriteHandleParent(
    229    PHttpChannelParent* channel) {
    230  HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel);
    231  CacheEntryWriteHandleParent* parent = chan->AllocCacheEntryWriteHandle();
    232  parent->AddRef();
    233  return parent;
    234 }
    235 
    236 bool NeckoParent::DeallocPCacheEntryWriteHandleParent(
    237    PCacheEntryWriteHandleParent* aActor) {
    238  CacheEntryWriteHandleParent* parent =
    239      static_cast<CacheEntryWriteHandleParent*>(aActor);
    240  parent->Release();
    241  return true;
    242 }
    243 
    244 PAltDataOutputStreamParent* NeckoParent::AllocPAltDataOutputStreamParent(
    245    const nsACString& type, const int64_t& predictedSize,
    246    mozilla::Maybe<mozilla::NotNull<mozilla::net::PHttpChannelParent*>>&
    247        channel,
    248    mozilla::Maybe<mozilla::NotNull<PCacheEntryWriteHandleParent*>>& handle) {
    249  MOZ_ASSERT(channel || handle);
    250 
    251  nsresult rv;
    252  nsCOMPtr<nsIAsyncOutputStream> stream;
    253  if (channel) {
    254    HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel->get());
    255    rv = chan->OpenAlternativeOutputStream(type, predictedSize,
    256                                           getter_AddRefs(stream));
    257  } else {
    258    CacheEntryWriteHandleParent* h =
    259        static_cast<CacheEntryWriteHandleParent*>(handle->get());
    260    rv = h->OpenAlternativeOutputStream(type, predictedSize,
    261                                        getter_AddRefs(stream));
    262  }
    263  AltDataOutputStreamParent* parent = new AltDataOutputStreamParent(stream);
    264  parent->AddRef();
    265  // If the return value was not NS_OK, the error code will be sent
    266  // asynchronously to the child, after receiving the first message.
    267  parent->SetError(rv);
    268  return parent;
    269 }
    270 
    271 bool NeckoParent::DeallocPAltDataOutputStreamParent(
    272    PAltDataOutputStreamParent* aActor) {
    273  AltDataOutputStreamParent* parent =
    274      static_cast<AltDataOutputStreamParent*>(aActor);
    275  parent->Release();
    276  return true;
    277 }
    278 
    279 already_AddRefed<PDocumentChannelParent>
    280 NeckoParent::AllocPDocumentChannelParent(
    281    const dom::MaybeDiscarded<dom::BrowsingContext>& aContext,
    282    const DocumentChannelCreationArgs& args) {
    283  RefPtr<DocumentChannelParent> p = new DocumentChannelParent();
    284  return p.forget();
    285 }
    286 
    287 mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor(
    288    PDocumentChannelParent* aActor,
    289    const dom::MaybeDiscarded<dom::BrowsingContext>& aContext,
    290    const DocumentChannelCreationArgs& aArgs) {
    291  DocumentChannelParent* p = static_cast<DocumentChannelParent*>(aActor);
    292 
    293  if (aContext.IsNullOrDiscarded()) {
    294    (void)p->SendFailedAsyncOpen(NS_ERROR_FAILURE);
    295    return IPC_OK();
    296  }
    297 
    298  if (!p->Init(aContext.get_canonical(), aArgs)) {
    299    return IPC_FAIL(this, "Couldn't initialize DocumentChannel");
    300  }
    301 
    302  return IPC_OK();
    303 }
    304 
    305 PCookieServiceParent* NeckoParent::AllocPCookieServiceParent() {
    306  return new CookieServiceParent(static_cast<ContentParent*>(Manager()));
    307 }
    308 
    309 bool NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) {
    310  delete cs;
    311  return true;
    312 }
    313 
    314 PWebSocketParent* NeckoParent::AllocPWebSocketParent(
    315    PBrowserParent* browser, const SerializedLoadContext& serialized,
    316    const uint32_t& aSerial) {
    317  nsCOMPtr<nsILoadContext> loadContext;
    318  CreateChannelLoadContext(browser, Manager(), serialized, nullptr,
    319                           loadContext);
    320 
    321  RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(browser);
    322  PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized);
    323  WebSocketChannelParent* p = new WebSocketChannelParent(
    324      browserParent, loadContext, overrideStatus, aSerial);
    325  p->AddRef();
    326  return p;
    327 }
    328 
    329 bool NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) {
    330  WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
    331  p->Release();
    332  return true;
    333 }
    334 
    335 PWebSocketEventListenerParent* NeckoParent::AllocPWebSocketEventListenerParent(
    336    const uint64_t& aInnerWindowID) {
    337  RefPtr<WebSocketEventListenerParent> c =
    338      new WebSocketEventListenerParent(aInnerWindowID);
    339  return c.forget().take();
    340 }
    341 
    342 bool NeckoParent::DeallocPWebSocketEventListenerParent(
    343    PWebSocketEventListenerParent* aActor) {
    344  RefPtr<WebSocketEventListenerParent> c =
    345      dont_AddRef(static_cast<WebSocketEventListenerParent*>(aActor));
    346  MOZ_ASSERT(c);
    347  return true;
    348 }
    349 
    350 mozilla::ipc::IPCResult NeckoParent::RecvConnectBaseChannel(
    351    const uint32_t& channelId) {
    352  RefPtr<nsBaseParentChannel> parentChannel =
    353      new nsBaseParentChannel(ContentParent::Cast(Manager())->GetRemoteType());
    354 
    355  nsCOMPtr<nsIChannel> channel;
    356  NS_LinkRedirectChannels(channelId, parentChannel, getter_AddRefs(channel));
    357  return IPC_OK();
    358 }
    359 
    360 #ifdef MOZ_WIDGET_GTK
    361 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
    362    const GIOChannelCreationArgs& aArgs) {
    363  if (aArgs.type() != GIOChannelCreationArgs::TGIOChannelOpenArgs) {
    364    return nullptr;
    365  }
    366 
    367  const GIOChannelOpenArgs& args = aArgs.get_GIOChannelOpenArgs();
    368  return GetRequestingPrincipal(args.loadInfo());
    369 }
    370 
    371 PGIOChannelParent* NeckoParent::AllocPGIOChannelParent(
    372    PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
    373    const GIOChannelCreationArgs& aOpenArgs) {
    374  nsCOMPtr<nsIPrincipal> requestingPrincipal =
    375      GetRequestingPrincipal(aOpenArgs);
    376 
    377  nsCOMPtr<nsILoadContext> loadContext;
    378  CreateChannelLoadContext(aBrowser, Manager(), aSerialized,
    379                           requestingPrincipal, loadContext);
    380  PBOverrideStatus overrideStatus =
    381      PBOverrideStatusFromLoadContext(aSerialized);
    382  GIOChannelParent* p = new GIOChannelParent(BrowserParent::GetFrom(aBrowser),
    383                                             loadContext, overrideStatus);
    384  p->AddRef();
    385  return p;
    386 }
    387 
    388 bool NeckoParent::DeallocPGIOChannelParent(PGIOChannelParent* channel) {
    389  GIOChannelParent* p = static_cast<GIOChannelParent*>(channel);
    390  p->Release();
    391  return true;
    392 }
    393 
    394 mozilla::ipc::IPCResult NeckoParent::RecvPGIOChannelConstructor(
    395    PGIOChannelParent* actor, PBrowserParent* aBrowser,
    396    const SerializedLoadContext& aSerialized,
    397    const GIOChannelCreationArgs& aOpenArgs) {
    398  GIOChannelParent* p = static_cast<GIOChannelParent*>(actor);
    399  DebugOnly<bool> rv = p->Init(aOpenArgs);
    400  MOZ_ASSERT(rv);
    401  return IPC_OK();
    402 }
    403 #endif
    404 
    405 #ifdef MOZ_WIDGET_ANDROID
    406 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
    407    const GeckoViewContentChannelArgs& aArgs) {
    408  if (aArgs.type() !=
    409      GeckoViewContentChannelArgs::TGeckoViewContentChannelOpenArgs) {
    410    return nullptr;
    411  }
    412 
    413  const GeckoViewContentChannelOpenArgs& args =
    414      aArgs.get_GeckoViewContentChannelOpenArgs();
    415  return GetRequestingPrincipal(args.loadInfo());
    416 }
    417 
    418 already_AddRefed<PGeckoViewContentChannelParent>
    419 NeckoParent::AllocPGeckoViewContentChannelParent(
    420    PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
    421    const GeckoViewContentChannelArgs& aOpenArgs) {
    422  nsCOMPtr<nsIPrincipal> requestingPrincipal =
    423      GetRequestingPrincipal(aOpenArgs);
    424 
    425  nsCOMPtr<nsILoadContext> loadContext;
    426  CreateChannelLoadContext(aBrowser, Manager(), aSerialized,
    427                           requestingPrincipal, loadContext);
    428  return MakeAndAddRef<GeckoViewContentChannelParent>(
    429      BrowserParent::GetFrom(aBrowser), loadContext);
    430 }
    431 
    432 mozilla::ipc::IPCResult NeckoParent::RecvPGeckoViewContentChannelConstructor(
    433    PGeckoViewContentChannelParent* actor, PBrowserParent* aBrowser,
    434    const SerializedLoadContext& aSerialized,
    435    const GeckoViewContentChannelArgs& aArgs) {
    436  GeckoViewContentChannelParent* p =
    437      static_cast<GeckoViewContentChannelParent*>(actor);
    438  if (!p->Init(aArgs)) {
    439    return IPC_FAIL(this, "Init is failed");
    440  }
    441  return IPC_OK();
    442 }
    443 #endif
    444 
    445 mozilla::ipc::IPCResult NeckoParent::RecvNotifyFileChannelOpened(
    446    const FileChannelInfo& aInfo) {
    447  nsFileChannel::DoNotifyFileChannelOpened(
    448      ContentParent::Cast(Manager())->GetRemoteType(), aInfo);
    449  return IPC_OK();
    450 }
    451 
    452 PTCPSocketParent* NeckoParent::AllocPTCPSocketParent(
    453    const nsAString& /* host */, const uint16_t& /* port */) {
    454  // We actually don't need host/port to construct a TCPSocketParent since
    455  // TCPSocketParent will maintain an internal nsIDOMTCPSocket instance which
    456  // can be delegated to get the host/port.
    457  TCPSocketParent* p = new TCPSocketParent();
    458  p->AddIPDLReference();
    459  return p;
    460 }
    461 
    462 bool NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor) {
    463  TCPSocketParent* p = static_cast<TCPSocketParent*>(actor);
    464  p->ReleaseIPDLReference();
    465  return true;
    466 }
    467 
    468 PTCPServerSocketParent* NeckoParent::AllocPTCPServerSocketParent(
    469    const uint16_t& aLocalPort, const uint16_t& aBacklog,
    470    const bool& aUseArrayBuffers) {
    471  TCPServerSocketParent* p =
    472      new TCPServerSocketParent(this, aLocalPort, aBacklog, aUseArrayBuffers);
    473  p->AddIPDLReference();
    474  return p;
    475 }
    476 
    477 mozilla::ipc::IPCResult NeckoParent::RecvPTCPServerSocketConstructor(
    478    PTCPServerSocketParent* aActor, const uint16_t& aLocalPort,
    479    const uint16_t& aBacklog, const bool& aUseArrayBuffers) {
    480  static_cast<TCPServerSocketParent*>(aActor)->Init();
    481  return IPC_OK();
    482 }
    483 
    484 bool NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor) {
    485  TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
    486  p->ReleaseIPDLReference();
    487  return true;
    488 }
    489 
    490 PUDPSocketParent* NeckoParent::AllocPUDPSocketParent(
    491    nsIPrincipal* /* unused */, const nsACString& /* unused */) {
    492  RefPtr<UDPSocketParent> p = new UDPSocketParent(this);
    493 
    494  return p.forget().take();
    495 }
    496 
    497 mozilla::ipc::IPCResult NeckoParent::RecvPUDPSocketConstructor(
    498    PUDPSocketParent* aActor, nsIPrincipal* aPrincipal,
    499    const nsACString& aFilter) {
    500  if (!static_cast<UDPSocketParent*>(aActor)->Init(aPrincipal, aFilter)) {
    501    return IPC_FAIL_NO_REASON(this);
    502  }
    503  return IPC_OK();
    504 }
    505 
    506 bool NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) {
    507  UDPSocketParent* p = static_cast<UDPSocketParent*>(actor);
    508  p->Release();
    509  return true;
    510 }
    511 
    512 already_AddRefed<PDNSRequestParent> NeckoParent::AllocPDNSRequestParent(
    513    const nsACString& aHost, const nsACString& aTrrServer, const int32_t& aPort,
    514    const uint16_t& aType, const OriginAttributes& aOriginAttributes,
    515    const nsIDNSService::DNSFlags& aFlags) {
    516  RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
    517  RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
    518  return actor.forget();
    519 }
    520 
    521 mozilla::ipc::IPCResult NeckoParent::RecvPDNSRequestConstructor(
    522    PDNSRequestParent* aActor, const nsACString& aHost,
    523    const nsACString& aTrrServer, const int32_t& aPort, const uint16_t& aType,
    524    const OriginAttributes& aOriginAttributes,
    525    const nsIDNSService::DNSFlags& aFlags) {
    526  RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
    527  RefPtr<DNSRequestHandler> handler =
    528      actor->GetDNSRequest()->AsDNSRequestHandler();
    529  handler->DoAsyncResolve(aHost, aTrrServer, aPort, aType, aOriginAttributes,
    530                          aFlags);
    531  return IPC_OK();
    532 }
    533 
    534 mozilla::ipc::IPCResult NeckoParent::RecvSpeculativeConnect(
    535    nsIURI* aURI, nsIPrincipal* aPrincipal,
    536    Maybe<OriginAttributes>&& aOriginAttributes, const bool& aAnonymous) {
    537  nsCOMPtr<nsISpeculativeConnect> speculator(gIOService);
    538  nsCOMPtr<nsIPrincipal> principal(aPrincipal);
    539  if (!aURI) {
    540    return IPC_FAIL(this, "aURI must not be null");
    541  }
    542  if (aURI && speculator) {
    543    if (aOriginAttributes) {
    544      speculator->SpeculativeConnectWithOriginAttributesNative(
    545          aURI, std::move(aOriginAttributes.ref()), nullptr, aAnonymous);
    546    } else {
    547      speculator->SpeculativeConnect(aURI, principal, nullptr, aAnonymous);
    548    }
    549  }
    550  return IPC_OK();
    551 }
    552 
    553 mozilla::ipc::IPCResult NeckoParent::RecvHTMLDNSPrefetch(
    554    const nsAString& hostname, const bool& isHttps,
    555    const OriginAttributes& aOriginAttributes,
    556    const nsIDNSService::DNSFlags& flags) {
    557  dom::HTMLDNSPrefetch::Prefetch(hostname, isHttps, aOriginAttributes, flags);
    558  return IPC_OK();
    559 }
    560 
    561 mozilla::ipc::IPCResult NeckoParent::RecvCancelHTMLDNSPrefetch(
    562    const nsAString& hostname, const bool& isHttps,
    563    const OriginAttributes& aOriginAttributes,
    564    const nsIDNSService::DNSFlags& flags, const nsresult& reason) {
    565  dom::HTMLDNSPrefetch::CancelPrefetch(hostname, isHttps, aOriginAttributes,
    566                                       flags, reason);
    567  return IPC_OK();
    568 }
    569 
    570 PTransportProviderParent* NeckoParent::AllocPTransportProviderParent() {
    571  RefPtr<TransportProviderParent> res = new TransportProviderParent();
    572  return res.forget().take();
    573 }
    574 
    575 bool NeckoParent::DeallocPTransportProviderParent(
    576    PTransportProviderParent* aActor) {
    577  RefPtr<TransportProviderParent> provider =
    578      dont_AddRef(static_cast<TransportProviderParent*>(aActor));
    579  return true;
    580 }
    581 
    582 mozilla::ipc::IPCResult NeckoParent::RecvRequestContextLoadBegin(
    583    const uint64_t& rcid) {
    584  nsCOMPtr<nsIRequestContextService> rcsvc =
    585      RequestContextService::GetOrCreate();
    586  if (!rcsvc) {
    587    return IPC_OK();
    588  }
    589  nsCOMPtr<nsIRequestContext> rc;
    590  rcsvc->GetRequestContext(rcid, getter_AddRefs(rc));
    591  if (rc) {
    592    rc->BeginLoad();
    593  }
    594 
    595  return IPC_OK();
    596 }
    597 
    598 mozilla::ipc::IPCResult NeckoParent::RecvRequestContextAfterDOMContentLoaded(
    599    const uint64_t& rcid) {
    600  nsCOMPtr<nsIRequestContextService> rcsvc =
    601      RequestContextService::GetOrCreate();
    602  if (!rcsvc) {
    603    return IPC_OK();
    604  }
    605  nsCOMPtr<nsIRequestContext> rc;
    606  rcsvc->GetRequestContext(rcid, getter_AddRefs(rc));
    607  if (rc) {
    608    rc->DOMContentLoaded();
    609  }
    610 
    611  return IPC_OK();
    612 }
    613 
    614 mozilla::ipc::IPCResult NeckoParent::RecvRemoveRequestContext(
    615    const uint64_t& rcid) {
    616  nsCOMPtr<nsIRequestContextService> rcsvc =
    617      RequestContextService::GetOrCreate();
    618  if (!rcsvc) {
    619    return IPC_OK();
    620  }
    621 
    622  rcsvc->RemoveRequestContext(rcid);
    623 
    624  return IPC_OK();
    625 }
    626 
    627 mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionStream(
    628    nsIURI* aURI, GetExtensionStreamResolver&& aResolve) {
    629  if (!aURI) {
    630    return IPC_FAIL(this, "aURI must not be null");
    631  }
    632 
    633  RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton());
    634  MOZ_ASSERT(ph);
    635 
    636  // Ask the ExtensionProtocolHandler to give us a new input stream for
    637  // this URI. The request comes from an ExtensionProtocolHandler in the
    638  // child process, but is not guaranteed to be a valid moz-extension URI,
    639  // and not guaranteed to represent a resource that the child should be
    640  // allowed to access. The ExtensionProtocolHandler is responsible for
    641  // validating the request. Specifically, only URI's for local files that
    642  // an extension is allowed to access via moz-extension URI's should be
    643  // accepted.
    644  nsCOMPtr<nsIInputStream> inputStream;
    645  bool terminateSender = true;
    646  auto inputStreamOrReason = ph->NewStream(aURI, &terminateSender);
    647  if (inputStreamOrReason.isOk()) {
    648    inputStream = inputStreamOrReason.unwrap();
    649  }
    650 
    651  // If NewStream failed, we send back an invalid stream to the child so
    652  // it can handle the error. MozPromise rejection is reserved for channel
    653  // errors/disconnects.
    654  aResolve(inputStream);
    655 
    656  if (terminateSender) {
    657    return IPC_FAIL_NO_REASON(this);
    658  }
    659  return IPC_OK();
    660 }
    661 
    662 mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionFD(
    663    nsIURI* aURI, GetExtensionFDResolver&& aResolve) {
    664  if (!aURI) {
    665    return IPC_FAIL(this, "aURI must not be null");
    666  }
    667 
    668  RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton());
    669  MOZ_ASSERT(ph);
    670 
    671  // Ask the ExtensionProtocolHandler to give us a new input stream for
    672  // this URI. The request comes from an ExtensionProtocolHandler in the
    673  // child process, but is not guaranteed to be a valid moz-extension URI,
    674  // and not guaranteed to represent a resource that the child should be
    675  // allowed to access. The ExtensionProtocolHandler is responsible for
    676  // validating the request. Specifically, only URI's for local files that
    677  // an extension is allowed to access via moz-extension URI's should be
    678  // accepted.
    679  bool terminateSender = true;
    680  auto result = ph->NewFD(aURI, &terminateSender, aResolve);
    681 
    682  if (result.isErr() && terminateSender) {
    683    return IPC_FAIL_NO_REASON(this);
    684  }
    685 
    686  if (result.isErr()) {
    687    FileDescriptor invalidFD;
    688    aResolve(invalidFD);
    689  }
    690 
    691  return IPC_OK();
    692 }
    693 
    694 mozilla::ipc::IPCResult NeckoParent::RecvInitSocketProcessBridge(
    695    InitSocketProcessBridgeResolver&& aResolver) {
    696  MOZ_ASSERT(NS_IsMainThread());
    697 
    698  // Initing the socket process bridge must be async here in order to
    699  // wait for the socket process launch before executing.
    700  auto task = [self = RefPtr{this}, resolver = std::move(aResolver)]() {
    701    // The content process might be already destroyed.
    702    if (!self->CanSend()) {
    703      return;
    704    }
    705 
    706    Endpoint<PSocketProcessBridgeChild> invalidEndpoint;
    707    if (NS_WARN_IF(self->mSocketProcessBridgeInited)) {
    708      resolver(std::move(invalidEndpoint));
    709      return;
    710    }
    711 
    712    RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton();
    713    if (NS_WARN_IF(!parent)) {
    714      resolver(std::move(invalidEndpoint));
    715      return;
    716    }
    717 
    718    Endpoint<PSocketProcessBridgeParent> parentEndpoint;
    719    Endpoint<PSocketProcessBridgeChild> childEndpoint;
    720    if (NS_WARN_IF(NS_FAILED(PSocketProcessBridge::CreateEndpoints(
    721            parent->OtherEndpointProcInfo(),
    722            self->Manager()->OtherEndpointProcInfo(), &parentEndpoint,
    723            &childEndpoint)))) {
    724      resolver(std::move(invalidEndpoint));
    725      return;
    726    }
    727 
    728    if (NS_WARN_IF(!parent->SendInitSocketProcessBridgeParent(
    729            self->Manager()->OtherPid(), std::move(parentEndpoint)))) {
    730      resolver(std::move(invalidEndpoint));
    731      return;
    732    }
    733 
    734    resolver(std::move(childEndpoint));
    735    self->mSocketProcessBridgeInited = true;
    736  };
    737  gIOService->CallOrWaitForSocketProcess(std::move(task));
    738 
    739  return IPC_OK();
    740 }
    741 
    742 mozilla::ipc::IPCResult NeckoParent::RecvResetSocketProcessBridge() {
    743  // SendResetSocketProcessBridge is called from
    744  // SocketProcessBridgeChild::ActorDestroy if the socket process
    745  // crashes.  This is necessary in order to properly initialize the
    746  // restarted socket process.
    747  mSocketProcessBridgeInited = false;
    748  return IPC_OK();
    749 }
    750 
    751 mozilla::ipc::IPCResult NeckoParent::RecvEnsureHSTSData(
    752    EnsureHSTSDataResolver&& aResolver) {
    753  auto callback = [aResolver{std::move(aResolver)}](bool aResult) {
    754    aResolver(aResult);
    755  };
    756  RefPtr<HSTSDataCallbackWrapper> wrapper =
    757      new HSTSDataCallbackWrapper(std::move(callback));
    758  gHttpHandler->EnsureHSTSDataReadyNative(wrapper);
    759  return IPC_OK();
    760 }
    761 
    762 mozilla::ipc::IPCResult NeckoParent::RecvGetPageThumbStream(
    763    nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs,
    764    GetPageThumbStreamResolver&& aResolver) {
    765  // Only the privileged about content process is allowed to access
    766  // things over the moz-page-thumb protocol. Any other content process
    767  // that tries to send this should have been blocked via the
    768  // ScriptSecurityManager, but if somehow the process has been tricked into
    769  // sending this message, we send IPC_FAIL in order to crash that
    770  // likely-compromised content process.
    771  if (static_cast<ContentParent*>(Manager())->GetRemoteType() !=
    772      PRIVILEGEDABOUT_REMOTE_TYPE) {
    773    return IPC_FAIL(this, "Wrong process type");
    774  }
    775 
    776  RefPtr<PageThumbProtocolHandler> ph(PageThumbProtocolHandler::GetSingleton());
    777  MOZ_ASSERT(ph);
    778 
    779  // Ask the PageThumbProtocolHandler to give us a new input stream for
    780  // this URI. The request comes from a PageThumbProtocolHandler in the
    781  // child process, but is not guaranteed to be a valid moz-page-thumb URI,
    782  // and not guaranteed to represent a resource that the child should be
    783  // allowed to access. The PageThumbProtocolHandler is responsible for
    784  // validating the request.
    785  nsCOMPtr<nsIInputStream> inputStream;
    786  bool terminateSender = true;
    787  auto inputStreamPromise = ph->NewStream(aURI, &terminateSender);
    788 
    789  if (terminateSender) {
    790    return IPC_FAIL(this, "Malformed moz-page-thumb request");
    791  }
    792 
    793  inputStreamPromise->Then(
    794      GetMainThreadSerialEventTarget(), __func__,
    795      [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); },
    796      [aResolver](nsresult aRv) {
    797        // If NewStream failed, we send back an invalid stream to the child so
    798        // it can handle the error. MozPromise rejection is reserved for channel
    799        // errors/disconnects.
    800        (void)NS_WARN_IF(NS_FAILED(aRv));
    801        aResolver(Nothing());
    802      });
    803 
    804  return IPC_OK();
    805 }
    806 
    807 mozilla::ipc::IPCResult NeckoParent::RecvGetMozNewTabWallpaperStream(
    808    nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs,
    809    GetMozNewTabWallpaperStreamResolver&& aResolver) {
    810  // Only the privileged about content process is allowed to access
    811  // things over the moz-newtab-wallpaper protocol. Any other content process
    812  // that tries to send this should have been blocked via the
    813  // ScriptSecurityManager, but if somehow the process has been tricked into
    814  // sending this message, we send IPC_FAIL in order to crash that
    815  // likely-compromised content process.
    816  if (static_cast<ContentParent*>(Manager())->GetRemoteType() !=
    817      PRIVILEGEDABOUT_REMOTE_TYPE) {
    818    return IPC_FAIL(this, "Wrong process type");
    819  }
    820 
    821  RefPtr<net::MozNewTabWallpaperProtocolHandler> ph(
    822      net::MozNewTabWallpaperProtocolHandler::GetSingleton());
    823  MOZ_ASSERT(ph);
    824 
    825  // Ask the MozNewTabWallpaperProtocolHandler to give us a new input stream for
    826  // this URI. The request comes from a MozNewTabWallpaperProtocolHandler in the
    827  // child process, but is not guaranteed to be a valid moz-newtab-wallpaper
    828  // URI, and not guaranteed to represent a resource that the child should be
    829  // allowed to access. The MozNewTabWallpaperProtocolHandler is responsible for
    830  // validating the request.
    831  nsCOMPtr<nsIInputStream> inputStream;
    832  bool terminateSender = true;
    833  auto inputStreamPromise = ph->NewStream(aURI, &terminateSender);
    834 
    835  if (terminateSender) {
    836    return IPC_FAIL(this, "Malformed moz-newtab-wallpaper request");
    837  }
    838 
    839  inputStreamPromise->Then(
    840      GetMainThreadSerialEventTarget(), __func__,
    841      [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); },
    842      [aResolver](nsresult aRv) {
    843        // If NewStream failed, we send back an invalid stream to the child so
    844        // it can handle the error. MozPromise rejection is reserved for channel
    845        // errors/disconnects.
    846        (void)NS_WARN_IF(NS_FAILED(aRv));
    847        aResolver(Nothing());
    848      });
    849 
    850  return IPC_OK();
    851 }
    852 
    853 mozilla::ipc::IPCResult NeckoParent::RecvGetPageIconStream(
    854    nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs,
    855    GetPageIconStreamResolver&& aResolver) {
    856 #ifdef MOZ_PLACES
    857  const nsACString& remoteType =
    858      ContentParent::Cast(Manager())->GetRemoteType();
    859 
    860  // Only the privileged about content process is allowed to access
    861  // things over the page-icon protocol. Any other content process
    862  // that tries to send this should have been blocked via the
    863  // ScriptSecurityManager, but if somehow the process has been tricked into
    864  // sending this message, we send IPC_FAIL in order to crash that
    865  // likely-compromised content process.
    866  if (remoteType != PRIVILEGEDABOUT_REMOTE_TYPE) {
    867    return IPC_FAIL(this, "Wrong process type");
    868  }
    869 
    870  nsCOMPtr<nsILoadInfo> loadInfo;
    871  nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs, remoteType,
    872                                                     getter_AddRefs(loadInfo));
    873  if (NS_FAILED(rv)) {
    874    return IPC_FAIL(this, "Page-icon request must include loadInfo");
    875  }
    876 
    877  RefPtr<PageIconProtocolHandler> ph(PageIconProtocolHandler::GetSingleton());
    878  MOZ_ASSERT(ph);
    879 
    880  nsCOMPtr<nsIInputStream> inputStream;
    881  bool terminateSender = true;
    882  auto inputStreamPromise = ph->NewStream(aURI, loadInfo, &terminateSender);
    883 
    884  if (terminateSender) {
    885    return IPC_FAIL(this, "Malformed page-icon request");
    886  }
    887 
    888  inputStreamPromise->Then(
    889      GetMainThreadSerialEventTarget(), __func__,
    890      [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); },
    891      [aResolver](nsresult aRv) {
    892        // If NewStream failed, we send back an invalid stream to the child so
    893        // it can handle the error. MozPromise rejection is reserved for channel
    894        // errors/disconnects.
    895        (void)NS_WARN_IF(NS_FAILED(aRv));
    896        aResolver(Nothing());
    897      });
    898 
    899  return IPC_OK();
    900 #else
    901  return IPC_FAIL(this, "page-icon: protocol unavailable");
    902 #endif
    903 }
    904 
    905 /* static */
    906 RefPtr<RemoteStreamPromise> NeckoParent::CreateRemoteStreamForResolvedURI(
    907    nsIURI* aChildURI, const nsACString& aResolvedSpec,
    908    const nsACString& aDefaultMimeType) {
    909  MOZ_ASSERT(NS_IsMainThread());
    910  MOZ_ASSERT(XRE_IsParentProcess());
    911 
    912  nsresult rv;
    913 
    914  nsAutoCString resolvedScheme;
    915  rv = net_ExtractURLScheme(aResolvedSpec, resolvedScheme);
    916  if (NS_FAILED(rv) || !resolvedScheme.EqualsLiteral("file")) {
    917    return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNEXPECTED, __func__);
    918  }
    919 
    920  MOZ_ASSERT(resolvedScheme.EqualsLiteral("file"),
    921             "CreateRemoteStreamForResolvedURI requires file:// URI");
    922 
    923  nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
    924  if (NS_FAILED(rv)) {
    925    return RemoteStreamPromise::CreateAndReject(rv, __func__);
    926  }
    927 
    928  nsCOMPtr<nsIURI> resolvedURI;
    929  rv = ioService->NewURI(aResolvedSpec, nullptr, nullptr,
    930                         getter_AddRefs(resolvedURI));
    931  if (NS_FAILED(rv)) {
    932    return RemoteStreamPromise::CreateAndReject(rv, __func__);
    933  }
    934 
    935  // Load local file resources for internal protocol handlers (moz-page-thumb,
    936  // moz-newtab-wallpaper). resolvedURI must be file:// scheme pointing to the
    937  // profile directory. Callers validate the original URI scheme/host and use
    938  // internal path resolution (PageThumbsStorageService, profile/wallpaper/)
    939  // before calling this method.
    940  nsCOMPtr<nsIChannel> channel;
    941  nsCOMPtr<nsIPrincipal> nullPrincipal =
    942      NullPrincipal::CreateWithoutOriginAttributes();
    943  rv = NS_NewChannel(getter_AddRefs(channel), resolvedURI, nullPrincipal,
    944                     nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    945                     nsIContentPolicy::TYPE_IMAGE);
    946  if (NS_FAILED(rv)) {
    947    return RemoteStreamPromise::CreateAndReject(rv, __func__);
    948  }
    949 
    950  auto promiseHolder = MakeUnique<MozPromiseHolder<RemoteStreamPromise>>();
    951  RefPtr<RemoteStreamPromise> promise = promiseHolder->Ensure(__func__);
    952 
    953  nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv);
    954  if (NS_FAILED(rv)) {
    955    return RemoteStreamPromise::CreateAndReject(rv, __func__);
    956  }
    957 
    958  nsAutoCString contentType;
    959  rv = mime->GetTypeFromURI(aChildURI, contentType);
    960  if (NS_FAILED(rv)) {
    961    if (!aDefaultMimeType.IsEmpty()) {
    962      contentType = aDefaultMimeType;
    963    } else {
    964      return RemoteStreamPromise::CreateAndReject(rv, __func__);
    965    }
    966  }
    967 
    968  rv = NS_DispatchBackgroundTask(
    969      NS_NewRunnableFunction(
    970          "NeckoParent::CreateRemoteStreamForResolvedURI",
    971          [contentType, channel, holder = std::move(promiseHolder)]() {
    972            nsresult rv;
    973 
    974            nsCOMPtr<nsIFileChannel> fileChannel =
    975                do_QueryInterface(channel, &rv);
    976            if (NS_FAILED(rv)) {
    977              holder->Reject(rv, __func__);
    978              return;
    979            }
    980 
    981            nsCOMPtr<nsIFile> requestedFile;
    982            rv = fileChannel->GetFile(getter_AddRefs(requestedFile));
    983            if (NS_FAILED(rv)) {
    984              holder->Reject(rv, __func__);
    985              return;
    986            }
    987 
    988            nsCOMPtr<nsIInputStream> inputStream;
    989            rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream),
    990                                            requestedFile, PR_RDONLY, -1);
    991            if (NS_FAILED(rv)) {
    992              holder->Reject(rv, __func__);
    993              return;
    994            }
    995 
    996            RemoteStreamInfo info(inputStream, contentType, -1);
    997 
    998            holder->Resolve(std::move(info), __func__);
    999          }),
   1000      NS_DISPATCH_EVENT_MAY_BLOCK);
   1001 
   1002  if (NS_FAILED(rv)) {
   1003    return RemoteStreamPromise::CreateAndReject(rv, __func__);
   1004  }
   1005 
   1006  return promise;
   1007 }
   1008 
   1009 }  // namespace net
   1010 }  // namespace mozilla