Bug 1625151 - P1: Move DNS resolution to socket process r=dragana

Differential Revision: https://phabricator.services.mozilla.com/D68388

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kershaw Chang 2020-04-14 09:14:41 +00:00
Родитель 485120fd67
Коммит bf843aa911
19 изменённых файлов: 500 добавлений и 164 удалений

Просмотреть файл

@ -525,6 +525,10 @@ void nsIOService::NotifySocketProcessPrefsChanged(const char* aName) {
return;
}
if (!StaticPrefs::network_process_enabled()) {
return;
}
dom::Pref pref(nsCString(aName), /* isLocked */ false, Nothing(), Nothing());
Preferences::GetPreference(&pref);
auto sendPrefUpdate = [pref]() {
@ -562,6 +566,7 @@ void nsIOService::CallOrWaitForSocketProcess(
aFunc();
} else {
mPendingEvents.AppendElement(aFunc); // infallible
LaunchSocketProcess();
}
}

Просмотреть файл

@ -3,7 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/ChildDNSService.h"
#include "nsDNSPrefetch.h"
#include "nsIDNSListener.h"
#include "nsIOService.h"
#include "nsThreadUtils.h"
#include "nsIXPConnect.h"
#include "nsIProtocolProxyService.h"
@ -25,7 +27,10 @@ static StaticRefPtr<ChildDNSService> gChildDNSService;
static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch";
already_AddRefed<ChildDNSService> ChildDNSService::GetSingleton() {
MOZ_ASSERT(XRE_IsContentProcess() || XRE_IsSocketProcess());
MOZ_ASSERT_IF(nsIOService::UseSocketProcess(),
XRE_IsContentProcess() || XRE_IsParentProcess());
MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(),
XRE_IsContentProcess() || XRE_IsSocketProcess());
if (!gChildDNSService) {
gChildDNSService = new ChildDNSService();
@ -41,7 +46,13 @@ ChildDNSService::ChildDNSService()
: mFirstTime(true),
mDisablePrefetch(false),
mPendingRequestsLock("DNSPendingRequestsLock") {
MOZ_ASSERT(XRE_IsContentProcess() || XRE_IsSocketProcess());
MOZ_ASSERT_IF(nsIOService::UseSocketProcess(),
XRE_IsContentProcess() || XRE_IsParentProcess());
MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(),
XRE_IsContentProcess() || XRE_IsSocketProcess());
if (XRE_IsParentProcess() && nsIOService::UseSocketProcess()) {
nsDNSPrefetch::Initialize(this);
}
}
void ChildDNSService::GetDNSRecordHashKey(
@ -68,6 +79,11 @@ nsresult ChildDNSService::AsyncResolveInternal(
NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
}
bool resolveDNSInSocketProcess = false;
if (XRE_IsParentProcess() && nsIOService::UseSocketProcess()) {
resolveDNSInSocketProcess = true;
}
if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) {
return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
}
@ -87,8 +103,14 @@ nsresult ChildDNSService::AsyncResolveInternal(
listener = new DNSListenerProxy(listener, target);
}
RefPtr<DNSRequestChild> childReq = new DNSRequestChild(
RefPtr<DNSRequestSender> sender = new DNSRequestSender(
hostname, aTrrServer, type, aOriginAttributes, flags, listener, target);
RefPtr<DNSRequestActor> dnsReq;
if (resolveDNSInSocketProcess) {
dnsReq = new DNSRequestParent(sender);
} else {
dnsReq = new DNSRequestChild(sender);
}
{
MutexAutoLock lock(mPendingRequestsLock);
@ -97,19 +119,19 @@ nsresult ChildDNSService::AsyncResolveInternal(
originalListener, key);
auto entry = mPendingRequests.LookupForAdd(key);
if (entry) {
entry.Data()->AppendElement(childReq);
entry.Data()->AppendElement(sender);
} else {
entry.OrInsert([&]() {
auto* hashEntry = new nsTArray<RefPtr<DNSRequestChild>>();
hashEntry->AppendElement(childReq);
auto* hashEntry = new nsTArray<RefPtr<DNSRequestSender>>();
hashEntry->AppendElement(sender);
return hashEntry;
});
}
}
childReq->StartRequest();
sender->StartRequest();
childReq.forget(result);
sender.forget(result);
return NS_OK;
}
@ -122,7 +144,7 @@ nsresult ChildDNSService::CancelAsyncResolveInternal(
}
MutexAutoLock lock(mPendingRequestsLock);
nsTArray<RefPtr<DNSRequestChild>>* hashEntry;
nsTArray<RefPtr<DNSRequestSender>>* hashEntry;
nsCString key;
GetDNSRecordHashKey(aHostname, aTrrServer, aType, aOriginAttributes, aFlags,
aListener, key);
@ -347,7 +369,7 @@ ChildDNSService::GetMyHostName(nsACString& result) {
return NS_ERROR_NOT_AVAILABLE;
}
void ChildDNSService::NotifyRequestDone(DNSRequestChild* aDnsRequest) {
void ChildDNSService::NotifyRequestDone(DNSRequestSender* aDnsRequest) {
// We need the original flags and listener for the pending requests hash.
uint32_t originalFlags = aDnsRequest->mFlags & ~RESOLVE_OFFLINE;
nsCOMPtr<nsIDNSListener> originalListener = aDnsRequest->mListener;
@ -367,11 +389,11 @@ void ChildDNSService::NotifyRequestDone(DNSRequestChild* aDnsRequest) {
aDnsRequest->mType, aDnsRequest->mOriginAttributes,
originalFlags, originalListener, key);
nsTArray<RefPtr<DNSRequestChild>>* hashEntry;
nsTArray<RefPtr<DNSRequestSender>>* hashEntry;
if (mPendingRequests.Get(key, &hashEntry)) {
auto idx = hashEntry->IndexOf(aDnsRequest);
if (idx != nsTArray<RefPtr<DNSRequestChild>>::NoIndex) {
if (idx != nsTArray<RefPtr<DNSRequestSender>>::NoIndex) {
hashEntry->RemoveElementAt(idx);
if (hashEntry->IsEmpty()) {
mPendingRequests.Remove(key);

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "DNSRequestChild.h"
#include "DNSRequestParent.h"
#include "nsHashKeys.h"
#include "nsClassHashtable.h"
@ -30,7 +31,7 @@ class ChildDNSService final : public nsPIDNSService, public nsIObserver {
static already_AddRefed<ChildDNSService> GetSingleton();
void NotifyRequestDone(DNSRequestChild* aDnsRequest);
void NotifyRequestDone(DNSRequestSender* aDnsRequest);
private:
virtual ~ChildDNSService() = default;
@ -54,7 +55,7 @@ class ChildDNSService final : public nsPIDNSService, public nsIObserver {
bool mDisablePrefetch;
// We need to remember pending dns requests to be able to cancel them.
nsClassHashtable<nsCStringHashKey, nsTArray<RefPtr<DNSRequestChild>>>
nsClassHashtable<nsCStringHashKey, nsTArray<RefPtr<DNSRequestSender>>>
mPendingRequests;
Mutex mPendingRequestsLock;
};

Просмотреть файл

@ -0,0 +1,148 @@
/* -*- 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/. */
#ifndef mozilla_net_DNSRequestBase_h
#define mozilla_net_DNSRequestBase_h
#include "mozilla/net/PDNSRequestParent.h"
#include "nsICancelable.h"
#include "nsIDNSRecord.h"
#include "nsIDNSListener.h"
#include "nsIDNSByTypeRecord.h"
#include "nsIEventTarget.h"
namespace mozilla {
namespace net {
class DNSRequestActor;
class DNSRequestChild;
class DNSRequestHandler;
class DNSRequestParent;
class DNSRequestSender;
// A base class for DNSRequestSender and DNSRequestHandler.
// Provide interfaces for processing DNS requests.
class DNSRequestBase : public nsISupports {
public:
explicit DNSRequestBase() = default;
void SetIPCActor(DNSRequestActor* aActor);
virtual void OnRecvCancelDNSRequest(const nsCString& hostName,
const nsCString& trrServer,
const uint16_t& type,
const OriginAttributes& originAttributes,
const uint32_t& flags,
const nsresult& reason) = 0;
virtual bool OnRecvLookupCompleted(const DNSRequestResponse& reply) = 0;
virtual void OnIPCActorDestroy() = 0;
virtual DNSRequestSender* AsDNSRequestSender() = 0;
virtual DNSRequestHandler* AsDNSRequestHandler() = 0;
protected:
virtual ~DNSRequestBase() = default;
RefPtr<DNSRequestActor> mIPCActor;
};
// DNSRequestSender is used to send an IPC request to DNSRequestHandler and
// deliver the result to nsIDNSListener.
// Note this class could be used both in content process and parent process.
class DNSRequestSender final : public DNSRequestBase, public nsICancelable {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICANCELABLE
DNSRequestSender(const nsACString& aHost, const nsACString& aTrrServer,
const uint16_t& aType,
const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags, nsIDNSListener* aListener,
nsIEventTarget* target);
void OnRecvCancelDNSRequest(const nsCString& hostName,
const nsCString& trrServer, const uint16_t& type,
const OriginAttributes& originAttributes,
const uint32_t& flags,
const nsresult& reason) override;
bool OnRecvLookupCompleted(const DNSRequestResponse& reply) override;
void OnIPCActorDestroy() override;
// Sends IPDL request to DNSRequestHandler
void StartRequest();
void CallOnLookupComplete();
DNSRequestSender* AsDNSRequestSender() override { return this; }
DNSRequestHandler* AsDNSRequestHandler() override { return nullptr; }
private:
friend class ChildDNSService;
virtual ~DNSRequestSender() = default;
nsCOMPtr<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTarget;
nsCOMPtr<nsIDNSRecord> mResultRecord;
nsresult mResultStatus;
nsCString mHost;
nsCString mTrrServer;
uint16_t mType;
const OriginAttributes mOriginAttributes;
uint16_t mFlags;
};
// DNSRequestHandler handles the dns request and sends the result back via IPC.
// Note this class could be used both in parent process and socket process.
class DNSRequestHandler final : public DNSRequestBase, public nsIDNSListener {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSLISTENER
DNSRequestHandler();
void DoAsyncResolve(const nsACString& hostname, const nsACString& trrServer,
uint16_t type, const OriginAttributes& originAttributes,
uint32_t flags);
void OnRecvCancelDNSRequest(const nsCString& hostName,
const nsCString& trrServer, const uint16_t& type,
const OriginAttributes& originAttributes,
const uint32_t& flags,
const nsresult& reason) override;
bool OnRecvLookupCompleted(const DNSRequestResponse& reply) override;
void OnIPCActorDestroy() override;
DNSRequestSender* AsDNSRequestSender() override { return nullptr; }
DNSRequestHandler* AsDNSRequestHandler() override { return this; }
private:
virtual ~DNSRequestHandler() = default;
uint32_t mFlags;
};
// Provides some common methods for DNSRequestChild and DNSRequestParent.
class DNSRequestActor {
public:
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
explicit DNSRequestActor(DNSRequestBase* aRequest) : mDNSRequest(aRequest) {}
virtual bool CanSend() const = 0;
virtual DNSRequestChild* AsDNSRequestChild() = 0;
virtual DNSRequestParent* AsDNSRequestParent() = 0;
DNSRequestBase* GetDNSRequest() { return mDNSRequest.get(); };
protected:
virtual ~DNSRequestActor() = default;
RefPtr<DNSRequestBase> mDNSRequest;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_DNSRequestBase_h

Просмотреть файл

@ -7,13 +7,16 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/net/ChildDNSService.h"
#include "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/DNSRequestParent.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/SocketProcessChild.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/net/SocketProcessParent.h"
#include "mozilla/Unused.h"
#include "nsIDNSRecord.h"
#include "nsIDNSByTypeRecord.h"
#include "nsHostResolver.h"
#include "nsIOService.h"
#include "nsTArray.h"
#include "nsNetAddr.h"
#include "nsThreadUtils.h"
@ -23,6 +26,10 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace net {
void DNSRequestBase::SetIPCActor(DNSRequestActor* aActor) {
mIPCActor = aActor;
}
//-----------------------------------------------------------------------------
// ChildDNSRecord:
// A simple class to provide nsIDNSRecord on the child
@ -193,37 +200,12 @@ ChildDNSByTypeRecord::GetRecordsAsOneString(nsACString& aRecords) {
}
//-----------------------------------------------------------------------------
// CancelDNSRequestEvent
// DNSRequestSender
//-----------------------------------------------------------------------------
class CancelDNSRequestEvent : public Runnable {
public:
CancelDNSRequestEvent(DNSRequestChild* aDnsReq, nsresult aReason)
: Runnable("net::CancelDNSRequestEvent"),
mDnsRequest(aDnsReq),
mReasonForCancel(aReason) {}
NS_IMPL_ISUPPORTS(DNSRequestSender, nsICancelable)
NS_IMETHOD Run() override {
if (mDnsRequest->CanSend()) {
// Send request to Parent process.
mDnsRequest->SendCancelDNSRequest(
mDnsRequest->mHost, mDnsRequest->mTrrServer, mDnsRequest->mType,
mDnsRequest->mOriginAttributes, mDnsRequest->mFlags,
mReasonForCancel);
}
return NS_OK;
}
private:
RefPtr<DNSRequestChild> mDnsRequest;
nsresult mReasonForCancel;
};
//-----------------------------------------------------------------------------
// DNSRequestChild
//-----------------------------------------------------------------------------
DNSRequestChild::DNSRequestChild(
DNSRequestSender::DNSRequestSender(
const nsACString& aHost, const nsACString& aTrrServer,
const uint16_t& aType, const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags, nsIDNSListener* aListener, nsIEventTarget* target)
@ -236,47 +218,105 @@ DNSRequestChild::DNSRequestChild(
mOriginAttributes(aOriginAttributes),
mFlags(aFlags) {}
void DNSRequestChild::StartRequest() {
void DNSRequestSender::OnRecvCancelDNSRequest(
const nsCString& hostName, const nsCString& trrServer, const uint16_t& type,
const OriginAttributes& originAttributes, const uint32_t& flags,
const nsresult& reason) {}
NS_IMETHODIMP
DNSRequestSender::Cancel(nsresult reason) {
if (!mIPCActor) {
return NS_ERROR_NOT_AVAILABLE;
}
if (mIPCActor->CanSend()) {
// We can only do IPDL on the main thread
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
"net::CancelDNSRequestEvent",
[actor(mIPCActor), host(mHost), trrServer(mTrrServer), type(mType),
originAttributes(mOriginAttributes), flags(mFlags), reason]() {
if (!actor->CanSend()) {
return;
}
if (DNSRequestChild* child = actor->AsDNSRequestChild()) {
Unused << child->SendCancelDNSRequest(
host, trrServer, type, originAttributes, flags, reason);
} else if (DNSRequestParent* parent = actor->AsDNSRequestParent()) {
Unused << parent->SendCancelDNSRequest(
host, trrServer, type, originAttributes, flags, reason);
}
});
SchedulerGroup::Dispatch(TaskCategory::Other, runnable.forget());
}
return NS_OK;
}
void DNSRequestSender::StartRequest() {
// we can only do IPDL on the main thread
if (!NS_IsMainThread()) {
SchedulerGroup::Dispatch(
TaskCategory::Other,
NewRunnableMethod("net::DNSRequestChild::StartRequest", this,
&DNSRequestChild::StartRequest));
NewRunnableMethod("net::DNSRequestSender::StartRequest", this,
&DNSRequestSender::StartRequest));
return;
}
if (XRE_IsContentProcess()) {
mozilla::dom::ContentChild* cc =
static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
if (cc->IsShuttingDown()) {
if (DNSRequestChild* child = mIPCActor->AsDNSRequestChild()) {
if (XRE_IsContentProcess()) {
mozilla::dom::ContentChild* cc =
static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
if (cc->IsShuttingDown()) {
return;
}
// Send request to Parent process.
gNeckoChild->SendPDNSRequestConstructor(child, mHost, mTrrServer, mType,
mOriginAttributes, mFlags);
} else if (XRE_IsSocketProcess()) {
// DNS resolution is done in the parent process. Send a DNS request to
// parent process.
MOZ_ASSERT(!nsIOService::UseSocketProcess());
SocketProcessChild* socketProcessChild =
SocketProcessChild::GetSingleton();
if (!socketProcessChild->CanSend()) {
return;
}
socketProcessChild->SendPDNSRequestConstructor(
child, mHost, mTrrServer, mType, mOriginAttributes, mFlags);
} else {
MOZ_ASSERT(false, "Wrong process");
return;
}
} else if (DNSRequestParent* parent = mIPCActor->AsDNSRequestParent()) {
// DNS resolution is done in the socket process. Send a DNS request to
// socket process.
MOZ_ASSERT(nsIOService::UseSocketProcess());
RefPtr<DNSRequestParent> requestParent = parent;
RefPtr<DNSRequestSender> self = this;
auto task = [requestParent, self]() {
Unused << SocketProcessParent::GetSingleton()->SendPDNSRequestConstructor(
requestParent, self->mHost, self->mTrrServer, self->mType,
self->mOriginAttributes, self->mFlags);
};
if (!gIOService->SocketProcessReady()) {
gIOService->CallOrWaitForSocketProcess(std::move(task));
return;
}
// Send request to Parent process.
gNeckoChild->SendPDNSRequestConstructor(this, mHost, mTrrServer, mType,
mOriginAttributes, mFlags);
} else if (XRE_IsSocketProcess()) {
SocketProcessChild* child = SocketProcessChild::GetSingleton();
if (!child->CanSend()) {
return;
}
child->SendPDNSRequestConstructor(this, mHost, mTrrServer, mType,
mOriginAttributes, mFlags);
} else {
MOZ_ASSERT(false, "Wrong process");
return;
task();
}
}
void DNSRequestChild::CallOnLookupComplete() {
void DNSRequestSender::CallOnLookupComplete() {
MOZ_ASSERT(mListener);
mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
}
mozilla::ipc::IPCResult DNSRequestChild::RecvLookupCompleted(
const DNSRequestResponse& reply) {
bool DNSRequestSender::OnRecvLookupCompleted(const DNSRequestResponse& reply) {
MOZ_ASSERT(mListener);
switch (reply.type()) {
@ -295,7 +335,7 @@ mozilla::ipc::IPCResult DNSRequestChild::RecvLookupCompleted(
}
default:
MOZ_ASSERT_UNREACHABLE("unknown type");
return IPC_FAIL_NO_REASON(this);
return false;
}
MOZ_ASSERT(NS_IsMainThread());
@ -311,41 +351,56 @@ mozilla::ipc::IPCResult DNSRequestChild::RecvLookupCompleted(
CallOnLookupComplete();
} else {
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod("net::DNSRequestChild::CallOnLookupComplete", this,
&DNSRequestChild::CallOnLookupComplete);
NewRunnableMethod("net::DNSRequestSender::CallOnLookupComplete", this,
&DNSRequestSender::CallOnLookupComplete);
mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
}
Unused << Send__delete__(this);
if (DNSRequestChild* child = mIPCActor->AsDNSRequestChild()) {
Unused << child->Send__delete__(child);
} else if (DNSRequestParent* parent = mIPCActor->AsDNSRequestParent()) {
Unused << parent->Send__delete__(parent);
}
return IPC_OK();
return true;
}
void DNSRequestChild::ActorDestroy(ActorDestroyReason why) {
void DNSRequestSender::OnIPCActorDestroy() {
// Request is done or destroyed. Remove it from the hash table.
RefPtr<ChildDNSService> dnsServiceChild =
dont_AddRef(ChildDNSService::GetSingleton());
dnsServiceChild->NotifyRequestDone(this);
mIPCActor = nullptr;
}
//-----------------------------------------------------------------------------
// DNSRequestChild::nsISupports
// DNSRequestChild
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(DNSRequestChild, nsICancelable)
DNSRequestChild::DNSRequestChild(DNSRequestBase* aRequest)
: DNSRequestActor(aRequest) {
aRequest->SetIPCActor(this);
}
//-----------------------------------------------------------------------------
// DNSRequestChild::nsICancelable
//-----------------------------------------------------------------------------
mozilla::ipc::IPCResult DNSRequestChild::RecvCancelDNSRequest(
const nsCString& hostName, const nsCString& trrServer, const uint16_t& type,
const OriginAttributes& originAttributes, const uint32_t& flags,
const nsresult& reason) {
mDNSRequest->OnRecvCancelDNSRequest(hostName, trrServer, type,
originAttributes, flags, reason);
return IPC_OK();
}
NS_IMETHODIMP
DNSRequestChild::Cancel(nsresult reason) {
if (CanSend()) {
// We can only do IPDL on the main thread
nsCOMPtr<nsIRunnable> runnable = new CancelDNSRequestEvent(this, reason);
SchedulerGroup::Dispatch(TaskCategory::Other, runnable.forget());
}
return NS_OK;
mozilla::ipc::IPCResult DNSRequestChild::RecvLookupCompleted(
const DNSRequestResponse& reply) {
return mDNSRequest->OnRecvLookupCompleted(reply) ? IPC_OK()
: IPC_FAIL_NO_REASON(this);
}
void DNSRequestChild::ActorDestroy(ActorDestroyReason) {
mDNSRequest->OnIPCActorDestroy();
mDNSRequest = nullptr;
}
//------------------------------------------------------------------------------

Просмотреть файл

@ -7,50 +7,32 @@
#ifndef mozilla_net_DNSRequestChild_h
#define mozilla_net_DNSRequestChild_h
#include "mozilla/net/DNSRequestBase.h"
#include "mozilla/net/PDNSRequestChild.h"
#include "nsICancelable.h"
#include "nsIDNSRecord.h"
#include "nsIDNSListener.h"
#include "nsIDNSByTypeRecord.h"
#include "nsIEventTarget.h"
namespace mozilla {
namespace net {
class DNSRequestChild final : public PDNSRequestChild, public nsICancelable {
class DNSRequestChild final : public DNSRequestActor, public PDNSRequestChild {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DNSRequestChild, override)
friend class PDNSRequestChild;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICANCELABLE
explicit DNSRequestChild(DNSRequestBase* aRequest);
DNSRequestChild(const nsACString& aHost, const nsACString& aTrrServer,
const uint16_t& aType,
const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags, nsIDNSListener* aListener,
nsIEventTarget* target);
bool CanSend() const override { return PDNSRequestChild::CanSend(); }
DNSRequestChild* AsDNSRequestChild() override { return this; }
DNSRequestParent* AsDNSRequestParent() override { return nullptr; }
// Sends IPDL request to parent
void StartRequest();
void CallOnLookupComplete();
protected:
friend class CancelDNSRequestEvent;
friend class ChildDNSService;
private:
virtual ~DNSRequestChild() = default;
mozilla::ipc::IPCResult RecvCancelDNSRequest(
const nsCString& hostName, const nsCString& trrServer,
const uint16_t& type, const OriginAttributes& originAttributes,
const uint32_t& flags, const nsresult& reason);
mozilla::ipc::IPCResult RecvLookupCompleted(const DNSRequestResponse& reply);
virtual void ActorDestroy(ActorDestroyReason why) override;
nsCOMPtr<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTarget;
nsCOMPtr<nsIDNSRecord> mResultRecord;
nsresult mResultStatus;
nsCString mHost;
nsCString mTrrServer;
uint16_t mType;
const OriginAttributes mOriginAttributes;
uint16_t mFlags;
};
} // namespace net

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/DNSRequestParent.h"
#include "mozilla/net/DNSRequestChild.h"
#include "nsIDNSService.h"
#include "nsNetCID.h"
#include "nsThreadUtils.h"
@ -18,13 +19,28 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace net {
DNSRequestParent::DNSRequestParent() : mFlags(0) {}
DNSRequestHandler::DNSRequestHandler() : mFlags(0) {}
void DNSRequestParent::DoAsyncResolve(const nsACString& hostname,
const nsACString& trrServer,
uint16_t type,
const OriginAttributes& originAttributes,
uint32_t flags) {
//-----------------------------------------------------------------------------
// DNSRequestHandler::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(DNSRequestHandler, nsIDNSListener)
static void SendLookupCompletedHelper(DNSRequestActor* aActor,
const DNSRequestResponse& aReply) {
if (DNSRequestParent* parent = aActor->AsDNSRequestParent()) {
Unused << parent->SendLookupCompleted(aReply);
} else if (DNSRequestChild* child = aActor->AsDNSRequestChild()) {
Unused << child->SendLookupCompleted(aReply);
}
}
void DNSRequestHandler::DoAsyncResolve(const nsACString& hostname,
const nsACString& trrServer,
uint16_t type,
const OriginAttributes& originAttributes,
uint32_t flags) {
nsresult rv;
mFlags = flags;
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
@ -45,12 +61,12 @@ void DNSRequestParent::DoAsyncResolve(const nsACString& hostname,
}
}
if (NS_FAILED(rv) && CanSend()) {
Unused << SendLookupCompleted(DNSRequestResponse(rv));
if (NS_FAILED(rv) && mIPCActor->CanSend()) {
SendLookupCompletedHelper(mIPCActor, DNSRequestResponse(rv));
}
}
mozilla::ipc::IPCResult DNSRequestParent::RecvCancelDNSRequest(
void DNSRequestHandler::OnRecvCancelDNSRequest(
const nsCString& hostName, const nsCString& aTrrServer,
const uint16_t& type, const OriginAttributes& originAttributes,
const uint32_t& flags, const nsresult& reason) {
@ -68,23 +84,20 @@ mozilla::ipc::IPCResult DNSRequestParent::RecvCancelDNSRequest(
hostName, aTrrServer, flags, this, reason, originAttributes);
}
}
return IPC_OK();
}
//-----------------------------------------------------------------------------
// DNSRequestParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(DNSRequestParent, nsIDNSListener)
bool DNSRequestHandler::OnRecvLookupCompleted(const DNSRequestResponse& reply) {
return true;
}
//-----------------------------------------------------------------------------
// nsIDNSListener functions
//-----------------------------------------------------------------------------
NS_IMETHODIMP
DNSRequestParent::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
nsresult status) {
if (!CanSend()) {
DNSRequestHandler::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
nsresult status) {
if (!mIPCActor || !mIPCActor->CanSend()) {
// nothing to do: child probably crashed
return NS_OK;
}
@ -96,7 +109,7 @@ DNSRequestParent::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
if (txtRec) {
nsTArray<nsCString> rec;
txtRec->GetRecords(rec);
Unused << SendLookupCompleted(DNSRequestResponse(rec));
SendLookupCompletedHelper(mIPCActor, DNSRequestResponse(rec));
return NS_OK;
}
@ -112,13 +125,45 @@ DNSRequestParent::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
array.AppendElement(addr);
}
Unused << SendLookupCompleted(DNSRequestResponse(DNSRecord(cname, array)));
SendLookupCompletedHelper(mIPCActor,
DNSRequestResponse(DNSRecord(cname, array)));
} else {
Unused << SendLookupCompleted(DNSRequestResponse(status));
SendLookupCompletedHelper(mIPCActor, DNSRequestResponse(status));
}
return NS_OK;
}
void DNSRequestHandler::OnIPCActorDestroy() { mIPCActor = nullptr; }
//-----------------------------------------------------------------------------
// DNSRequestParent functions
//-----------------------------------------------------------------------------
DNSRequestParent::DNSRequestParent(DNSRequestBase* aRequest)
: DNSRequestActor(aRequest) {
aRequest->SetIPCActor(this);
}
mozilla::ipc::IPCResult DNSRequestParent::RecvCancelDNSRequest(
const nsCString& hostName, const nsCString& trrServer, const uint16_t& type,
const OriginAttributes& originAttributes, const uint32_t& flags,
const nsresult& reason) {
mDNSRequest->OnRecvCancelDNSRequest(hostName, trrServer, type,
originAttributes, flags, reason);
return IPC_OK();
}
mozilla::ipc::IPCResult DNSRequestParent::RecvLookupCompleted(
const DNSRequestResponse& reply) {
return mDNSRequest->OnRecvLookupCompleted(reply) ? IPC_OK()
: IPC_FAIL_NO_REASON(this);
}
void DNSRequestParent::ActorDestroy(ActorDestroyReason) {
mDNSRequest->OnIPCActorDestroy();
mDNSRequest = nullptr;
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -7,22 +7,26 @@
#ifndef mozilla_net_DNSRequestParent_h
#define mozilla_net_DNSRequestParent_h
#include "mozilla/net/DNSRequestBase.h"
#include "mozilla/net/PDNSRequestParent.h"
#include "nsIDNSListener.h"
namespace mozilla {
namespace net {
class DNSRequestParent : public PDNSRequestParent, public nsIDNSListener {
class DNSRequestParent : public DNSRequestActor, public PDNSRequestParent {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDNSLISTENER
friend class PDNSRequestParent;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DNSRequestParent, override)
DNSRequestParent();
explicit DNSRequestParent(DNSRequestBase* aRequest);
void DoAsyncResolve(const nsACString& hostname, const nsACString& trrServer,
uint16_t type, const OriginAttributes& originAttributes,
uint32_t flags);
bool CanSend() const override { return PDNSRequestParent::CanSend(); }
DNSRequestChild* AsDNSRequestChild() override { return nullptr; }
DNSRequestParent* AsDNSRequestParent() override { return this; }
private:
virtual ~DNSRequestParent() = default;
// Pass args here rather than storing them in the parent; they are only
// needed if the request is to be canceled.
@ -30,11 +34,8 @@ class DNSRequestParent : public PDNSRequestParent, public nsIDNSListener {
const nsCString& hostName, const nsCString& trrServer,
const uint16_t& type, const OriginAttributes& originAttributes,
const uint32_t& flags, const nsresult& reason);
private:
virtual ~DNSRequestParent() = default;
uint32_t mFlags;
mozilla::ipc::IPCResult RecvLookupCompleted(const DNSRequestResponse& reply);
void ActorDestroy(ActorDestroyReason) override;
};
} // namespace net

Просмотреть файл

@ -21,7 +21,7 @@ async refcounted protocol PDNSRequest
{
manager PNecko or PSocketProcess;
parent:
both:
// constructor in PNecko takes AsyncResolve args that initialize request
// Pass args here rather than storing them in the parent; they are only
@ -31,7 +31,6 @@ parent:
uint32_t flags, nsresult reason);
async __delete__();
child:
async LookupCompleted(DNSRequestResponse reply);
};

Просмотреть файл

@ -39,6 +39,7 @@ EXPORTS.mozilla.net += [
'ChildDNSService.h',
'DNS.h',
'DNSListenerProxy.h',
'DNSRequestBase.h',
'DNSRequestChild.h',
'DNSRequestParent.h',
'IDNBlocklistUtils.h',

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsIDNSByTypeRecord.h"
#include "nsICancelable.h"
#include "nsIPrefBranch.h"
#include "nsIOService.h"
#include "nsIXPConnect.h"
#include "nsProxyRelease.h"
#include "nsReadableUtils.h"
@ -39,6 +40,7 @@
#include "mozilla/net/DNSListenerProxy.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/TextUtils.h"
#include "mozilla/Utf8.h"
@ -545,6 +547,18 @@ NS_IMPL_ISUPPORTS(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
static StaticRefPtr<nsDNSService> gDNSService;
already_AddRefed<nsIDNSService> nsDNSService::GetXPCOMSingleton() {
if (nsIOService::UseSocketProcess()) {
if (XRE_IsSocketProcess()) {
return GetSingleton();
}
if (XRE_IsContentProcess() || XRE_IsParentProcess()) {
return ChildDNSService::GetSingleton();
}
return nullptr;
}
if (XRE_IsParentProcess()) {
return GetSingleton();
}
@ -557,14 +571,31 @@ already_AddRefed<nsIDNSService> nsDNSService::GetXPCOMSingleton() {
}
already_AddRefed<nsDNSService> nsDNSService::GetSingleton() {
NS_ASSERTION(XRE_IsParentProcess(), "not a parent process");
MOZ_ASSERT_IF(nsIOService::UseSocketProcess(), XRE_IsSocketProcess());
MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(), XRE_IsParentProcess());
if (!gDNSService) {
gDNSService = new nsDNSService();
if (NS_SUCCEEDED(gDNSService->Init())) {
ClearOnShutdown(&gDNSService);
auto initTask = []() {
gDNSService = new nsDNSService();
if (NS_SUCCEEDED(gDNSService->Init())) {
ClearOnShutdown(&gDNSService);
} else {
gDNSService = nullptr;
}
};
if (!NS_IsMainThread()) {
// Forward to the main thread synchronously.
RefPtr<nsIThread> mainThread = do_GetMainThread();
if (!mainThread) {
return nullptr;
}
SyncRunnable::DispatchToThread(mainThread,
new SyncRunnable(NS_NewRunnableFunction(
"nsDNSService::Init", initTask)));
} else {
gDNSService = nullptr;
initTask();
}
}

Просмотреть файл

@ -615,7 +615,8 @@ bool NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) {
already_AddRefed<PDNSRequestParent> NeckoParent::AllocPDNSRequestParent(
const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
RefPtr<DNSRequestParent> actor = new DNSRequestParent();
RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
return actor.forget();
}
@ -623,8 +624,10 @@ mozilla::ipc::IPCResult NeckoParent::RecvPDNSRequestConstructor(
PDNSRequestParent* aActor, const nsCString& aHost,
const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(
aHost, aTrrServer, aType, aOriginAttributes, aFlags);
RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
RefPtr<DNSRequestHandler> handler =
actor->GetDNSRequest()->AsDNSRequestHandler();
handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
return IPC_OK();
}

Просмотреть файл

@ -63,8 +63,6 @@ parent:
/* tabId is only required for web-proxy support, which isn't always needed */
async PWebrtcTCPSocket(TabId? tabId);
async PDNSRequest(nsCString hostName, nsCString trrServer, uint16_t type,
OriginAttributes originAttributes, uint32_t flags);
async PChildToParentStream();
async ObserveHttpActivity(HttpActivityArgs aActivityArgs,
uint32_t aActivityType,
@ -100,6 +98,8 @@ child:
both:
async PFileDescriptorSet(FileDescriptor fd);
async PDNSRequest(nsCString hostName, nsCString trrServer, uint16_t type,
OriginAttributes originAttributes, uint32_t flags);
};
} // namespace net

Просмотреть файл

@ -19,10 +19,14 @@
#include "mozilla/ipc/ProcessChild.h"
#include "mozilla/net/AltSvcTransactionChild.h"
#include "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/DNSRequestParent.h"
#include "mozilla/ipc/PChildToParentStreamChild.h"
#include "mozilla/ipc/PParentToChildStreamChild.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "nsDebugImpl.h"
#include "nsHttpConnectionInfo.h"
#include "nsHttpHandler.h"
#include "nsIDNSService.h"
#include "nsIHttpActivityObserver.h"
#include "nsThreadManager.h"
@ -352,5 +356,24 @@ SocketProcessChild::AllocPAltSvcTransactionChild(
return child.forget();
}
already_AddRefed<PDNSRequestChild> SocketProcessChild::AllocPDNSRequestChild(
const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
RefPtr<DNSRequestChild> actor = new DNSRequestChild(handler);
return actor.forget();
}
mozilla::ipc::IPCResult SocketProcessChild::RecvPDNSRequestConstructor(
PDNSRequestChild* aActor, const nsCString& aHost,
const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
RefPtr<DNSRequestChild> actor = static_cast<DNSRequestChild*>(aActor);
RefPtr<DNSRequestHandler> handler =
actor->GetDNSRequest()->AsDNSRequestHandler();
handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
return IPC_OK();
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -86,6 +86,16 @@ class SocketProcessChild final
bool IsShuttingDown() { return mShuttingDown; }
already_AddRefed<PDNSRequestChild> AllocPDNSRequestChild(
const nsCString& aHost, const nsCString& aTrrServer,
const uint16_t& aType, const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags);
mozilla::ipc::IPCResult RecvPDNSRequestConstructor(
PDNSRequestChild* aActor, const nsCString& aHost,
const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags) override;
protected:
friend class SocketProcessImpl;
~SocketProcessChild();

Просмотреть файл

@ -7,6 +7,7 @@
#include "nsAppRunner.h"
#include "nsIObserverService.h"
#include "nsIOService.h"
#include "SocketProcessParent.h"
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)

Просмотреть файл

@ -16,6 +16,10 @@
# include "mozilla/sandboxTarget.h"
#endif
#ifdef OS_POSIX
# include <unistd.h> // For sleep().
#endif
using mozilla::ipc::IOThreadChild;
namespace mozilla {

Просмотреть файл

@ -153,7 +153,8 @@ bool SocketProcessParent::DeallocPWebrtcTCPSocketParent(
already_AddRefed<PDNSRequestParent> SocketProcessParent::AllocPDNSRequestParent(
const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
RefPtr<DNSRequestParent> actor = new DNSRequestParent();
RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
return actor.forget();
}
@ -161,8 +162,10 @@ mozilla::ipc::IPCResult SocketProcessParent::RecvPDNSRequestConstructor(
PDNSRequestParent* aActor, const nsCString& aHost,
const nsCString& aTrrServer, const uint16_t& aType,
const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(
aHost, aTrrServer, aType, aOriginAttributes, aFlags);
RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
RefPtr<DNSRequestHandler> handler =
actor->GetDNSRequest()->AsDNSRequestHandler();
handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
return IPC_OK();
}

Просмотреть файл

@ -4,6 +4,8 @@
var CC = Components.Constructor;
var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
const BinaryInputStream = CC(
"@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",