summaryrefslogtreecommitdiffstats
path: root/netwerk/ipc/NeckoParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/ipc/NeckoParent.cpp922
1 files changed, 922 insertions, 0 deletions
diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp
new file mode 100644
index 0000000000..f0ee16d855
--- /dev/null
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -0,0 +1,922 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHttp.h"
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/ContentPrincipal.h"
+#include "mozilla/ipc/IPCStreamUtils.h"
+#include "mozilla/net/ExtensionProtocolHandler.h"
+#include "mozilla/net/PageThumbProtocolHandler.h"
+#include "mozilla/net/NeckoParent.h"
+#include "mozilla/net/HttpChannelParent.h"
+#include "mozilla/net/CookieServiceParent.h"
+#include "mozilla/net/FTPChannelParent.h"
+#include "mozilla/net/WebSocketChannelParent.h"
+#include "mozilla/net/WebSocketEventListenerParent.h"
+#include "mozilla/net/DataChannelParent.h"
+#include "mozilla/net/DocumentChannelParent.h"
+#include "mozilla/net/SimpleChannelParent.h"
+#include "mozilla/net/AltDataOutputStreamParent.h"
+#include "mozilla/Unused.h"
+#include "mozilla/net/FileChannelParent.h"
+#include "mozilla/net/DNSRequestParent.h"
+#include "mozilla/net/ClassifierDummyChannelParent.h"
+#include "mozilla/net/IPCTransportProvider.h"
+#include "mozilla/net/RequestContextService.h"
+#include "mozilla/net/SocketProcessParent.h"
+#include "mozilla/net/PSocketProcessBridgeParent.h"
+#ifdef MOZ_WEBRTC
+# include "mozilla/net/StunAddrsRequestParent.h"
+# include "mozilla/net/WebrtcTCPSocketParent.h"
+#endif
+#include "mozilla/dom/ChromeUtils.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/TabContext.h"
+#include "mozilla/dom/BrowserParent.h"
+#include "mozilla/dom/network/TCPSocketParent.h"
+#include "mozilla/dom/network/TCPServerSocketParent.h"
+#include "mozilla/dom/network/UDPSocketParent.h"
+#include "mozilla/dom/ServiceWorkerManager.h"
+#include "mozilla/LoadContext.h"
+#include "mozilla/MozPromise.h"
+#include "nsPrintfCString.h"
+#include "nsHTMLDNSPrefetch.h"
+#include "nsEscape.h"
+#include "SerializedLoadContext.h"
+#include "nsAuthInformationHolder.h"
+#include "nsIAuthPromptCallback.h"
+#include "nsINetworkPredictor.h"
+#include "nsINetworkPredictorVerifier.h"
+#include "nsISpeculativeConnect.h"
+#include "nsHttpHandler.h"
+#include "nsNetUtil.h"
+
+using IPC::SerializedLoadContext;
+using mozilla::OriginAttributes;
+using mozilla::dom::BrowserParent;
+using mozilla::dom::ChromeUtils;
+using mozilla::dom::ContentParent;
+using mozilla::dom::ServiceWorkerManager;
+using mozilla::dom::TabContext;
+using mozilla::dom::TCPServerSocketParent;
+using mozilla::dom::TCPSocketParent;
+using mozilla::dom::UDPSocketParent;
+using mozilla::ipc::LoadInfoArgsToLoadInfo;
+using mozilla::ipc::PrincipalInfo;
+using mozilla::net::PTCPServerSocketParent;
+using mozilla::net::PTCPSocketParent;
+using mozilla::net::PUDPSocketParent;
+
+namespace mozilla {
+namespace net {
+
+// C++ file contents
+NeckoParent::NeckoParent() : mSocketProcessBridgeInited(false) {
+ // Init HTTP protocol handler now since we need atomTable up and running very
+ // early (IPDL argument handling for PHttpChannel constructor needs it) so
+ // normal init (during 1st Http channel request) isn't early enough.
+ nsCOMPtr<nsIProtocolHandler> proto =
+ do_GetService("@mozilla.org/network/protocol;1?name=http");
+}
+
+static PBOverrideStatus PBOverrideStatusFromLoadContext(
+ const SerializedLoadContext& aSerialized) {
+ if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) {
+ return (aSerialized.mOriginAttributes.mPrivateBrowsingId > 0)
+ ? kPBOverride_Private
+ : kPBOverride_NotPrivate;
+ }
+ return kPBOverride_Unset;
+}
+
+static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
+ const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs) {
+ if (aOptionalLoadInfoArgs.isNothing()) {
+ return nullptr;
+ }
+
+ const LoadInfoArgs& loadInfoArgs = aOptionalLoadInfoArgs.ref();
+ const Maybe<PrincipalInfo>& optionalPrincipalInfo =
+ loadInfoArgs.requestingPrincipalInfo();
+
+ if (optionalPrincipalInfo.isNothing()) {
+ return nullptr;
+ }
+
+ const PrincipalInfo& principalInfo = optionalPrincipalInfo.ref();
+
+ auto principalOrErr = PrincipalInfoToPrincipal(principalInfo);
+ return principalOrErr.isOk() ? principalOrErr.unwrap().forget() : nullptr;
+}
+
+static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
+ const HttpChannelCreationArgs& aArgs) {
+ if (aArgs.type() != HttpChannelCreationArgs::THttpChannelOpenArgs) {
+ return nullptr;
+ }
+
+ const HttpChannelOpenArgs& args = aArgs.get_HttpChannelOpenArgs();
+ return GetRequestingPrincipal(args.loadInfo());
+}
+
+static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
+ const FTPChannelCreationArgs& aArgs) {
+ if (aArgs.type() != FTPChannelCreationArgs::TFTPChannelOpenArgs) {
+ return nullptr;
+ }
+
+ const FTPChannelOpenArgs& args = aArgs.get_FTPChannelOpenArgs();
+ return GetRequestingPrincipal(args.loadInfo());
+}
+
+const char* NeckoParent::GetValidatedOriginAttributes(
+ const SerializedLoadContext& aSerialized, PContentParent* aContent,
+ nsIPrincipal* aRequestingPrincipal, OriginAttributes& aAttrs) {
+ if (!aSerialized.IsNotNull()) {
+ // If serialized is null, we cannot validate anything. We have to assume
+ // that this requests comes from a SystemPrincipal.
+ aAttrs = OriginAttributes(false);
+ } else {
+ aAttrs = aSerialized.mOriginAttributes;
+ }
+ return nullptr;
+}
+
+const char* NeckoParent::CreateChannelLoadContext(
+ PBrowserParent* aBrowser, PContentParent* aContent,
+ const SerializedLoadContext& aSerialized,
+ nsIPrincipal* aRequestingPrincipal, nsCOMPtr<nsILoadContext>& aResult) {
+ OriginAttributes attrs;
+ const char* error = GetValidatedOriginAttributes(aSerialized, aContent,
+ aRequestingPrincipal, attrs);
+ if (error) {
+ return error;
+ }
+
+ // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is
+ // the common case for most xpcshell tests.
+ if (aSerialized.IsNotNull()) {
+ attrs.SyncAttributesWithPrivateBrowsing(
+ aSerialized.mOriginAttributes.mPrivateBrowsingId > 0);
+
+ RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(aBrowser);
+ dom::Element* topFrameElement = nullptr;
+ if (browserParent) {
+ topFrameElement = browserParent->GetOwnerElement();
+ }
+ aResult = new LoadContext(aSerialized, topFrameElement, attrs);
+ }
+
+ return nullptr;
+}
+
+void NeckoParent::ActorDestroy(ActorDestroyReason aWhy) {
+ // Nothing needed here. Called right before destructor since this is a
+ // non-refcounted class.
+}
+
+already_AddRefed<PHttpChannelParent> NeckoParent::AllocPHttpChannelParent(
+ PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
+ const HttpChannelCreationArgs& aOpenArgs) {
+ nsCOMPtr<nsIPrincipal> requestingPrincipal =
+ GetRequestingPrincipal(aOpenArgs);
+
+ nsCOMPtr<nsILoadContext> loadContext;
+ const char* error = CreateChannelLoadContext(
+ aBrowser, Manager(), aSerialized, requestingPrincipal, loadContext);
+ if (error) {
+ printf_stderr(
+ "NeckoParent::AllocPHttpChannelParent: "
+ "FATAL error: %s: KILLING CHILD PROCESS\n",
+ error);
+ return nullptr;
+ }
+ PBOverrideStatus overrideStatus =
+ PBOverrideStatusFromLoadContext(aSerialized);
+ RefPtr<HttpChannelParent> p = new HttpChannelParent(
+ BrowserParent::GetFrom(aBrowser), loadContext, overrideStatus);
+ return p.forget();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPHttpChannelConstructor(
+ PHttpChannelParent* aActor, PBrowserParent* aBrowser,
+ const SerializedLoadContext& aSerialized,
+ const HttpChannelCreationArgs& aOpenArgs) {
+ HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor);
+ if (!p->Init(aOpenArgs)) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ return IPC_OK();
+}
+
+PStunAddrsRequestParent* NeckoParent::AllocPStunAddrsRequestParent() {
+#ifdef MOZ_WEBRTC
+ StunAddrsRequestParent* p = new StunAddrsRequestParent();
+ p->AddRef();
+ return p;
+#else
+ return nullptr;
+#endif
+}
+
+bool NeckoParent::DeallocPStunAddrsRequestParent(
+ PStunAddrsRequestParent* aActor) {
+#ifdef MOZ_WEBRTC
+ StunAddrsRequestParent* p = static_cast<StunAddrsRequestParent*>(aActor);
+ p->Release();
+#endif
+ return true;
+}
+
+PWebrtcTCPSocketParent* NeckoParent::AllocPWebrtcTCPSocketParent(
+ const Maybe<TabId>& aTabId) {
+#ifdef MOZ_WEBRTC
+ WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId);
+ parent->AddRef();
+ return parent;
+#else
+ return nullptr;
+#endif
+}
+
+bool NeckoParent::DeallocPWebrtcTCPSocketParent(
+ PWebrtcTCPSocketParent* aActor) {
+#ifdef MOZ_WEBRTC
+ WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor);
+ parent->Release();
+#endif
+ return true;
+}
+
+PAltDataOutputStreamParent* NeckoParent::AllocPAltDataOutputStreamParent(
+ const nsCString& type, const int64_t& predictedSize,
+ PHttpChannelParent* channel) {
+ HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel);
+ nsCOMPtr<nsIAsyncOutputStream> stream;
+ nsresult rv = chan->OpenAlternativeOutputStream(type, predictedSize,
+ getter_AddRefs(stream));
+ AltDataOutputStreamParent* parent = new AltDataOutputStreamParent(stream);
+ parent->AddRef();
+ // If the return value was not NS_OK, the error code will be sent
+ // asynchronously to the child, after receiving the first message.
+ parent->SetError(rv);
+ return parent;
+}
+
+bool NeckoParent::DeallocPAltDataOutputStreamParent(
+ PAltDataOutputStreamParent* aActor) {
+ AltDataOutputStreamParent* parent =
+ static_cast<AltDataOutputStreamParent*>(aActor);
+ parent->Release();
+ return true;
+}
+
+PFTPChannelParent* NeckoParent::AllocPFTPChannelParent(
+ PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
+ const FTPChannelCreationArgs& aOpenArgs) {
+ nsCOMPtr<nsIPrincipal> requestingPrincipal =
+ GetRequestingPrincipal(aOpenArgs);
+
+ nsCOMPtr<nsILoadContext> loadContext;
+ const char* error = CreateChannelLoadContext(
+ aBrowser, Manager(), aSerialized, requestingPrincipal, loadContext);
+ if (error) {
+ printf_stderr(
+ "NeckoParent::AllocPFTPChannelParent: "
+ "FATAL error: %s: KILLING CHILD PROCESS\n",
+ error);
+ return nullptr;
+ }
+ PBOverrideStatus overrideStatus =
+ PBOverrideStatusFromLoadContext(aSerialized);
+ FTPChannelParent* p = new FTPChannelParent(BrowserParent::GetFrom(aBrowser),
+ loadContext, overrideStatus);
+ p->AddRef();
+ return p;
+}
+
+bool NeckoParent::DeallocPFTPChannelParent(PFTPChannelParent* channel) {
+ FTPChannelParent* p = static_cast<FTPChannelParent*>(channel);
+ p->Release();
+ return true;
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPFTPChannelConstructor(
+ PFTPChannelParent* aActor, PBrowserParent* aBrowser,
+ const SerializedLoadContext& aSerialized,
+ const FTPChannelCreationArgs& aOpenArgs) {
+ FTPChannelParent* p = static_cast<FTPChannelParent*>(aActor);
+ if (!p->Init(aOpenArgs)) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ return IPC_OK();
+}
+
+already_AddRefed<PDocumentChannelParent>
+NeckoParent::AllocPDocumentChannelParent(
+ const MaybeDiscarded<BrowsingContext>& aContext,
+ const DocumentChannelCreationArgs& args) {
+ RefPtr<DocumentChannelParent> p = new DocumentChannelParent();
+ return p.forget();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor(
+ PDocumentChannelParent* aActor,
+ const MaybeDiscarded<BrowsingContext>& aContext,
+ const DocumentChannelCreationArgs& aArgs) {
+ DocumentChannelParent* p = static_cast<DocumentChannelParent*>(aActor);
+
+ if (aContext.IsNullOrDiscarded()) {
+ Unused << p->SendFailedAsyncOpen(NS_ERROR_FAILURE);
+ return IPC_OK();
+ }
+
+ if (!p->Init(aContext.get_canonical(), aArgs)) {
+ return IPC_FAIL(this, "Couldn't initialize DocumentChannel");
+ }
+
+ return IPC_OK();
+}
+
+PCookieServiceParent* NeckoParent::AllocPCookieServiceParent() {
+ return new CookieServiceParent();
+}
+
+bool NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) {
+ delete cs;
+ return true;
+}
+
+PWebSocketParent* NeckoParent::AllocPWebSocketParent(
+ PBrowserParent* browser, const SerializedLoadContext& serialized,
+ const uint32_t& aSerial) {
+ nsCOMPtr<nsILoadContext> loadContext;
+ const char* error = CreateChannelLoadContext(browser, Manager(), serialized,
+ nullptr, loadContext);
+ if (error) {
+ printf_stderr(
+ "NeckoParent::AllocPWebSocketParent: "
+ "FATAL error: %s: KILLING CHILD PROCESS\n",
+ error);
+ return nullptr;
+ }
+
+ RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(browser);
+ PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized);
+ WebSocketChannelParent* p = new WebSocketChannelParent(
+ browserParent, loadContext, overrideStatus, aSerial);
+ p->AddRef();
+ return p;
+}
+
+bool NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) {
+ WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
+ p->Release();
+ return true;
+}
+
+PWebSocketEventListenerParent* NeckoParent::AllocPWebSocketEventListenerParent(
+ const uint64_t& aInnerWindowID) {
+ RefPtr<WebSocketEventListenerParent> c =
+ new WebSocketEventListenerParent(aInnerWindowID);
+ return c.forget().take();
+}
+
+bool NeckoParent::DeallocPWebSocketEventListenerParent(
+ PWebSocketEventListenerParent* aActor) {
+ RefPtr<WebSocketEventListenerParent> c =
+ dont_AddRef(static_cast<WebSocketEventListenerParent*>(aActor));
+ MOZ_ASSERT(c);
+ return true;
+}
+
+already_AddRefed<PDataChannelParent> NeckoParent::AllocPDataChannelParent(
+ const uint32_t& channelId) {
+ RefPtr<DataChannelParent> p = new DataChannelParent();
+ return p.forget();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPDataChannelConstructor(
+ PDataChannelParent* actor, const uint32_t& channelId) {
+ DataChannelParent* p = static_cast<DataChannelParent*>(actor);
+ DebugOnly<bool> rv = p->Init(channelId);
+ MOZ_ASSERT(rv);
+ return IPC_OK();
+}
+
+PSimpleChannelParent* NeckoParent::AllocPSimpleChannelParent(
+ const uint32_t& channelId) {
+ RefPtr<SimpleChannelParent> p = new SimpleChannelParent();
+ return p.forget().take();
+}
+
+bool NeckoParent::DeallocPSimpleChannelParent(PSimpleChannelParent* actor) {
+ RefPtr<SimpleChannelParent> p =
+ dont_AddRef(actor).downcast<SimpleChannelParent>();
+ return true;
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPSimpleChannelConstructor(
+ PSimpleChannelParent* actor, const uint32_t& channelId) {
+ SimpleChannelParent* p = static_cast<SimpleChannelParent*>(actor);
+ MOZ_ALWAYS_TRUE(p->Init(channelId));
+ return IPC_OK();
+}
+
+already_AddRefed<PFileChannelParent> NeckoParent::AllocPFileChannelParent(
+ const uint32_t& channelId) {
+ RefPtr<FileChannelParent> p = new FileChannelParent();
+ return p.forget();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPFileChannelConstructor(
+ PFileChannelParent* actor, const uint32_t& channelId) {
+ FileChannelParent* p = static_cast<FileChannelParent*>(actor);
+ DebugOnly<bool> rv = p->Init(channelId);
+ MOZ_ASSERT(rv);
+ return IPC_OK();
+}
+
+PTCPSocketParent* NeckoParent::AllocPTCPSocketParent(
+ const nsString& /* host */, const uint16_t& /* port */) {
+ // We actually don't need host/port to construct a TCPSocketParent since
+ // TCPSocketParent will maintain an internal nsIDOMTCPSocket instance which
+ // can be delegated to get the host/port.
+ TCPSocketParent* p = new TCPSocketParent();
+ p->AddIPDLReference();
+ return p;
+}
+
+bool NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor) {
+ TCPSocketParent* p = static_cast<TCPSocketParent*>(actor);
+ p->ReleaseIPDLReference();
+ return true;
+}
+
+PTCPServerSocketParent* NeckoParent::AllocPTCPServerSocketParent(
+ const uint16_t& aLocalPort, const uint16_t& aBacklog,
+ const bool& aUseArrayBuffers) {
+ TCPServerSocketParent* p =
+ new TCPServerSocketParent(this, aLocalPort, aBacklog, aUseArrayBuffers);
+ p->AddIPDLReference();
+ return p;
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPTCPServerSocketConstructor(
+ PTCPServerSocketParent* aActor, const uint16_t& aLocalPort,
+ const uint16_t& aBacklog, const bool& aUseArrayBuffers) {
+ static_cast<TCPServerSocketParent*>(aActor)->Init();
+ return IPC_OK();
+}
+
+bool NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor) {
+ TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
+ p->ReleaseIPDLReference();
+ return true;
+}
+
+PUDPSocketParent* NeckoParent::AllocPUDPSocketParent(
+ nsIPrincipal* /* unused */, const nsCString& /* unused */) {
+ RefPtr<UDPSocketParent> p = new UDPSocketParent(this);
+
+ return p.forget().take();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPUDPSocketConstructor(
+ PUDPSocketParent* aActor, nsIPrincipal* aPrincipal,
+ const nsCString& aFilter) {
+ if (!static_cast<UDPSocketParent*>(aActor)->Init(aPrincipal, aFilter)) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ return IPC_OK();
+}
+
+bool NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) {
+ UDPSocketParent* p = static_cast<UDPSocketParent*>(actor);
+ p->Release();
+ return true;
+}
+
+already_AddRefed<PDNSRequestParent> NeckoParent::AllocPDNSRequestParent(
+ const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
+ const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
+ RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
+ RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
+ return actor.forget();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPDNSRequestConstructor(
+ PDNSRequestParent* aActor, const nsCString& aHost,
+ const nsCString& aTrrServer, const uint16_t& aType,
+ const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
+ RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
+ RefPtr<DNSRequestHandler> handler =
+ actor->GetDNSRequest()->AsDNSRequestHandler();
+ handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvSpeculativeConnect(
+ nsIURI* aURI, nsIPrincipal* aPrincipal, const bool& aAnonymous) {
+ nsCOMPtr<nsISpeculativeConnect> speculator(gIOService);
+ nsCOMPtr<nsIPrincipal> principal(aPrincipal);
+ if (!aURI) {
+ return IPC_FAIL(this, "aURI must not be null");
+ }
+ if (aURI && speculator) {
+ if (aAnonymous) {
+ speculator->SpeculativeAnonymousConnect(aURI, principal, nullptr);
+ } else {
+ speculator->SpeculativeConnect(aURI, principal, nullptr);
+ }
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvHTMLDNSPrefetch(
+ const nsString& hostname, const bool& isHttps,
+ const OriginAttributes& aOriginAttributes, const uint32_t& flags) {
+ nsHTMLDNSPrefetch::Prefetch(hostname, isHttps, aOriginAttributes, flags);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvCancelHTMLDNSPrefetch(
+ const nsString& hostname, const bool& isHttps,
+ const OriginAttributes& aOriginAttributes, const uint32_t& flags,
+ const nsresult& reason) {
+ nsHTMLDNSPrefetch::CancelPrefetch(hostname, isHttps, aOriginAttributes, flags,
+ reason);
+ return IPC_OK();
+}
+
+PTransportProviderParent* NeckoParent::AllocPTransportProviderParent() {
+ RefPtr<TransportProviderParent> res = new TransportProviderParent();
+ return res.forget().take();
+}
+
+bool NeckoParent::DeallocPTransportProviderParent(
+ PTransportProviderParent* aActor) {
+ RefPtr<TransportProviderParent> provider =
+ dont_AddRef(static_cast<TransportProviderParent*>(aActor));
+ return true;
+}
+
+namespace {
+std::map<uint64_t, nsCOMPtr<nsIAuthPromptCallback> >& CallbackMap() {
+ MOZ_ASSERT(NS_IsMainThread());
+ static std::map<uint64_t, nsCOMPtr<nsIAuthPromptCallback> > sCallbackMap;
+ return sCallbackMap;
+}
+} // namespace
+
+NS_IMPL_ISUPPORTS(NeckoParent::NestedFrameAuthPrompt, nsIAuthPrompt2)
+
+NeckoParent::NestedFrameAuthPrompt::NestedFrameAuthPrompt(PNeckoParent* aParent,
+ TabId aNestedFrameId)
+ : mNeckoParent(aParent), mNestedFrameId(aNestedFrameId) {}
+
+NS_IMETHODIMP
+NeckoParent::NestedFrameAuthPrompt::AsyncPromptAuth(
+ nsIChannel* aChannel, nsIAuthPromptCallback* callback, nsISupports*,
+ uint32_t, nsIAuthInformation* aInfo, nsICancelable**) {
+ static uint64_t callbackId = 0;
+ MOZ_ASSERT(XRE_IsParentProcess());
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsAutoCString spec;
+ if (uri) {
+ rv = uri->GetSpec(spec);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ nsString realm;
+ rv = aInfo->GetRealm(realm);
+ NS_ENSURE_SUCCESS(rv, rv);
+ callbackId++;
+ if (mNeckoParent->SendAsyncAuthPromptForNestedFrame(mNestedFrameId, spec,
+ realm, callbackId)) {
+ CallbackMap()[callbackId] = callback;
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvOnAuthAvailable(
+ const uint64_t& aCallbackId, const nsString& aUser,
+ const nsString& aPassword, const nsString& aDomain) {
+ nsCOMPtr<nsIAuthPromptCallback> callback = CallbackMap()[aCallbackId];
+ if (!callback) {
+ return IPC_OK();
+ }
+ CallbackMap().erase(aCallbackId);
+
+ RefPtr<nsAuthInformationHolder> holder =
+ new nsAuthInformationHolder(0, u""_ns, ""_ns);
+ holder->SetUsername(aUser);
+ holder->SetPassword(aPassword);
+ holder->SetDomain(aDomain);
+
+ callback->OnAuthAvailable(nullptr, holder);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvOnAuthCancelled(
+ const uint64_t& aCallbackId, const bool& aUserCancel) {
+ nsCOMPtr<nsIAuthPromptCallback> callback = CallbackMap()[aCallbackId];
+ if (!callback) {
+ return IPC_OK();
+ }
+ CallbackMap().erase(aCallbackId);
+ callback->OnAuthCancelled(nullptr, aUserCancel);
+ return IPC_OK();
+}
+
+/* Predictor Messages */
+mozilla::ipc::IPCResult NeckoParent::RecvPredPredict(
+ nsIURI* aTargetURI, nsIURI* aSourceURI, const uint32_t& aReason,
+ const OriginAttributes& aOriginAttributes, const bool& hasVerifier) {
+ // Get the current predictor
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsINetworkPredictor> predictor =
+ do_GetService("@mozilla.org/network/predictor;1", &rv);
+ NS_ENSURE_SUCCESS(rv, IPC_OK());
+
+ nsCOMPtr<nsINetworkPredictorVerifier> verifier;
+ if (hasVerifier) {
+ verifier = do_QueryInterface(predictor);
+ }
+ predictor->PredictNative(aTargetURI, aSourceURI, aReason, aOriginAttributes,
+ verifier);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPredLearn(
+ nsIURI* aTargetURI, nsIURI* aSourceURI, const uint32_t& aReason,
+ const OriginAttributes& aOriginAttributes) {
+ // Get the current predictor
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsINetworkPredictor> predictor =
+ do_GetService("@mozilla.org/network/predictor;1", &rv);
+ NS_ENSURE_SUCCESS(rv, IPC_OK());
+
+ predictor->LearnNative(aTargetURI, aSourceURI, aReason, aOriginAttributes);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPredReset() {
+ // Get the current predictor
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsINetworkPredictor> predictor =
+ do_GetService("@mozilla.org/network/predictor;1", &rv);
+ NS_ENSURE_SUCCESS(rv, IPC_OK());
+
+ predictor->Reset();
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvRequestContextLoadBegin(
+ const uint64_t& rcid) {
+ nsCOMPtr<nsIRequestContextService> rcsvc =
+ RequestContextService::GetOrCreate();
+ if (!rcsvc) {
+ return IPC_OK();
+ }
+ nsCOMPtr<nsIRequestContext> rc;
+ rcsvc->GetRequestContext(rcid, getter_AddRefs(rc));
+ if (rc) {
+ rc->BeginLoad();
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvRequestContextAfterDOMContentLoaded(
+ const uint64_t& rcid) {
+ nsCOMPtr<nsIRequestContextService> rcsvc =
+ RequestContextService::GetOrCreate();
+ if (!rcsvc) {
+ return IPC_OK();
+ }
+ nsCOMPtr<nsIRequestContext> rc;
+ rcsvc->GetRequestContext(rcid, getter_AddRefs(rc));
+ if (rc) {
+ rc->DOMContentLoaded();
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvRemoveRequestContext(
+ const uint64_t& rcid) {
+ nsCOMPtr<nsIRequestContextService> rcsvc =
+ RequestContextService::GetOrCreate();
+ if (!rcsvc) {
+ return IPC_OK();
+ }
+
+ rcsvc->RemoveRequestContext(rcid);
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionStream(
+ nsIURI* aURI, GetExtensionStreamResolver&& aResolve) {
+ if (!aURI) {
+ return IPC_FAIL(this, "aURI must not be null");
+ }
+
+ RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton());
+ MOZ_ASSERT(ph);
+
+ // Ask the ExtensionProtocolHandler to give us a new input stream for
+ // this URI. The request comes from an ExtensionProtocolHandler in the
+ // child process, but is not guaranteed to be a valid moz-extension URI,
+ // and not guaranteed to represent a resource that the child should be
+ // allowed to access. The ExtensionProtocolHandler is responsible for
+ // validating the request. Specifically, only URI's for local files that
+ // an extension is allowed to access via moz-extension URI's should be
+ // accepted.
+ nsCOMPtr<nsIInputStream> inputStream;
+ bool terminateSender = true;
+ auto inputStreamOrReason = ph->NewStream(aURI, &terminateSender);
+ if (inputStreamOrReason.isOk()) {
+ inputStream = inputStreamOrReason.unwrap();
+ }
+
+ // If NewStream failed, we send back an invalid stream to the child so
+ // it can handle the error. MozPromise rejection is reserved for channel
+ // errors/disconnects.
+ aResolve(inputStream);
+
+ if (terminateSender) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionFD(
+ nsIURI* aURI, GetExtensionFDResolver&& aResolve) {
+ if (!aURI) {
+ return IPC_FAIL(this, "aURI must not be null");
+ }
+
+ RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton());
+ MOZ_ASSERT(ph);
+
+ // Ask the ExtensionProtocolHandler to give us a new input stream for
+ // this URI. The request comes from an ExtensionProtocolHandler in the
+ // child process, but is not guaranteed to be a valid moz-extension URI,
+ // and not guaranteed to represent a resource that the child should be
+ // allowed to access. The ExtensionProtocolHandler is responsible for
+ // validating the request. Specifically, only URI's for local files that
+ // an extension is allowed to access via moz-extension URI's should be
+ // accepted.
+ bool terminateSender = true;
+ auto result = ph->NewFD(aURI, &terminateSender, aResolve);
+
+ if (result.isErr() && terminateSender) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ if (result.isErr()) {
+ FileDescriptor invalidFD;
+ aResolve(invalidFD);
+ }
+
+ return IPC_OK();
+}
+
+PClassifierDummyChannelParent* NeckoParent::AllocPClassifierDummyChannelParent(
+ nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult,
+ const Maybe<LoadInfoArgs>& aLoadInfo) {
+ RefPtr<ClassifierDummyChannelParent> c = new ClassifierDummyChannelParent();
+ return c.forget().take();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvPClassifierDummyChannelConstructor(
+ PClassifierDummyChannelParent* aActor, nsIURI* aURI, nsIURI* aTopWindowURI,
+ const nsresult& aTopWindowURIResult, const Maybe<LoadInfoArgs>& aLoadInfo) {
+ ClassifierDummyChannelParent* p =
+ static_cast<ClassifierDummyChannelParent*>(aActor);
+
+ if (NS_WARN_IF(!aURI)) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ nsCOMPtr<nsILoadInfo> loadInfo;
+ nsresult rv = LoadInfoArgsToLoadInfo(aLoadInfo, getter_AddRefs(loadInfo));
+ if (NS_WARN_IF(NS_FAILED(rv)) || !loadInfo) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ p->Init(aURI, aTopWindowURI, aTopWindowURIResult, loadInfo);
+ return IPC_OK();
+}
+
+bool NeckoParent::DeallocPClassifierDummyChannelParent(
+ PClassifierDummyChannelParent* aActor) {
+ RefPtr<ClassifierDummyChannelParent> c =
+ dont_AddRef(static_cast<ClassifierDummyChannelParent*>(aActor));
+ MOZ_ASSERT(c);
+ return true;
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvInitSocketProcessBridge(
+ InitSocketProcessBridgeResolver&& aResolver) {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ Endpoint<PSocketProcessBridgeChild> invalidEndpoint;
+ if (NS_WARN_IF(mSocketProcessBridgeInited)) {
+ aResolver(std::move(invalidEndpoint));
+ return IPC_OK();
+ }
+
+ SocketProcessParent* parent = SocketProcessParent::GetSingleton();
+ if (NS_WARN_IF(!parent)) {
+ aResolver(std::move(invalidEndpoint));
+ return IPC_OK();
+ }
+
+ Endpoint<PSocketProcessBridgeParent> parentEndpoint;
+ Endpoint<PSocketProcessBridgeChild> childEndpoint;
+ if (NS_WARN_IF(NS_FAILED(PSocketProcessBridge::CreateEndpoints(
+ parent->OtherPid(), Manager()->OtherPid(), &parentEndpoint,
+ &childEndpoint)))) {
+ aResolver(std::move(invalidEndpoint));
+ return IPC_OK();
+ }
+
+ if (NS_WARN_IF(!parent->SendInitSocketProcessBridgeParent(
+ Manager()->OtherPid(), std::move(parentEndpoint)))) {
+ aResolver(std::move(invalidEndpoint));
+ return IPC_OK();
+ }
+
+ aResolver(std::move(childEndpoint));
+ mSocketProcessBridgeInited = true;
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvEnsureHSTSData(
+ EnsureHSTSDataResolver&& aResolver) {
+ auto callback = [aResolver{std::move(aResolver)}](bool aResult) {
+ aResolver(aResult);
+ };
+ RefPtr<HSTSDataCallbackWrapper> wrapper =
+ new HSTSDataCallbackWrapper(std::move(callback));
+ gHttpHandler->EnsureHSTSDataReadyNative(wrapper);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult NeckoParent::RecvGetPageThumbStream(
+ nsIURI* aURI, GetPageThumbStreamResolver&& aResolver) {
+ // Only the privileged about content process is allowed to access
+ // things over the moz-page-thumb protocol. Any other content process
+ // that tries to send this should have been blocked via the
+ // ScriptSecurityManager, but if somehow the process has been tricked into
+ // sending this message, we send IPC_FAIL in order to crash that
+ // likely-compromised content process.
+ if (static_cast<ContentParent*>(Manager())->GetRemoteType() !=
+ PRIVILEGEDABOUT_REMOTE_TYPE) {
+ return IPC_FAIL(this, "Wrong process type");
+ }
+
+ RefPtr<PageThumbProtocolHandler> ph(PageThumbProtocolHandler::GetSingleton());
+ MOZ_ASSERT(ph);
+
+ // Ask the PageThumbProtocolHandler to give us a new input stream for
+ // this URI. The request comes from a PageThumbProtocolHandler in the
+ // child process, but is not guaranteed to be a valid moz-page-thumb URI,
+ // and not guaranteed to represent a resource that the child should be
+ // allowed to access. The PageThumbProtocolHandler is responsible for
+ // validating the request.
+ nsCOMPtr<nsIInputStream> inputStream;
+ bool terminateSender = true;
+ auto inputStreamPromise = ph->NewStream(aURI, &terminateSender);
+
+ if (terminateSender) {
+ return IPC_FAIL(this, "Malformed moz-page-thumb request");
+ }
+
+ inputStreamPromise->Then(
+ GetMainThreadSerialEventTarget(), __func__,
+ [aResolver](const nsCOMPtr<nsIInputStream>& aStream) {
+ aResolver(aStream);
+ },
+ [aResolver](nsresult aRv) {
+ // If NewStream failed, we send back an invalid stream to the child so
+ // it can handle the error. MozPromise rejection is reserved for channel
+ // errors/disconnects.
+ Unused << NS_WARN_IF(NS_FAILED(aRv));
+ aResolver(nullptr);
+ });
+
+ return IPC_OK();
+}
+
+} // namespace net
+} // namespace mozilla