summaryrefslogtreecommitdiffstats
path: root/netwerk/dns/TRRServiceParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/dns/TRRServiceParent.cpp')
-rw-r--r--netwerk/dns/TRRServiceParent.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/netwerk/dns/TRRServiceParent.cpp b/netwerk/dns/TRRServiceParent.cpp
new file mode 100644
index 0000000000..d5c072921b
--- /dev/null
+++ b/netwerk/dns/TRRServiceParent.cpp
@@ -0,0 +1,239 @@
+/* -*- 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 "mozilla/net/TRRServiceParent.h"
+
+#include "mozilla/ipc/FileDescriptor.h"
+#include "mozilla/net/SocketProcessParent.h"
+#include "mozilla/psm/PSMIPCTypes.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Unused.h"
+#include "nsHttpConnectionInfo.h"
+#include "nsICaptivePortalService.h"
+#include "nsIParentalControlsService.h"
+#include "nsINetworkLinkService.h"
+#include "nsIObserverService.h"
+#include "nsIOService.h"
+#include "nsNetCID.h"
+#include "TRRService.h"
+
+#include "DNSLogging.h"
+
+namespace mozilla {
+namespace net {
+
+static Atomic<TRRServiceParent*> sTRRServiceParentPtr;
+
+static const char* gTRRUriCallbackPrefs[] = {
+ "network.trr.uri", "network.trr.default_provider_uri",
+ "network.trr.mode", kRolloutURIPref,
+ kRolloutModePref, nullptr,
+};
+
+NS_IMPL_ISUPPORTS_INHERITED(TRRServiceParent, TRRServiceBase, nsIObserver,
+ nsISupportsWeakReference)
+
+TRRServiceParent::~TRRServiceParent() = default;
+
+void TRRServiceParent::Init() {
+ MOZ_ASSERT(gIOService);
+
+ if (!gIOService->SocketProcessReady()) {
+ RefPtr<TRRServiceParent> self = this;
+ gIOService->CallOrWaitForSocketProcess([self]() { self->Init(); });
+ return;
+ }
+
+ SocketProcessParent* socketParent = SocketProcessParent::GetSingleton();
+ if (!socketParent) {
+ return;
+ }
+
+ nsCOMPtr<nsIObserverService> obs =
+ static_cast<nsIObserverService*>(gIOService);
+ TRRService::AddObserver(this, obs);
+
+ bool captiveIsPassed = TRRService::CheckCaptivePortalIsPassed();
+ bool parentalControlEnabled = TRRService::GetParentalControlEnabledInternal();
+
+ nsCOMPtr<nsINetworkLinkService> nls =
+ do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID);
+ nsTArray<nsCString> suffixList;
+ if (nls) {
+ nls->GetDnsSuffixList(suffixList);
+ }
+
+ Preferences::RegisterPrefixCallbacks(TRRServiceParent::PrefsChanged,
+ gTRRUriCallbackPrefs, this);
+ prefsChanged(nullptr);
+
+ if (socketParent->SendPTRRServiceConstructor(
+ this, captiveIsPassed, parentalControlEnabled, suffixList)) {
+ sTRRServiceParentPtr = this;
+ }
+}
+
+NS_IMETHODIMP
+TRRServiceParent::Observe(nsISupports* aSubject, const char* aTopic,
+ const char16_t* aData) {
+ if (!strcmp(aTopic, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC) ||
+ !strcmp(aTopic, NS_NETWORK_LINK_TOPIC)) {
+ nsCOMPtr<nsINetworkLinkService> link = do_QueryInterface(aSubject);
+ // The network link service notification normally passes itself as the
+ // subject, but some unit tests will sometimes pass a null subject.
+ if (link) {
+ nsTArray<nsCString> suffixList;
+ link->GetDnsSuffixList(suffixList);
+ Unused << SendUpdatePlatformDNSInformation(suffixList);
+ }
+
+ if (!strcmp(aTopic, NS_NETWORK_LINK_TOPIC) && mURISetByDetection) {
+ CheckURIPrefs();
+ }
+ }
+
+ return NS_OK;
+}
+
+mozilla::ipc::IPCResult
+TRRServiceParent::RecvNotifyNetworkConnectivityServiceObservers(
+ const nsCString& aTopic) {
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->NotifyObservers(nullptr, aTopic.get(), nullptr);
+ }
+ return IPC_OK();
+}
+
+bool TRRServiceParent::MaybeSetPrivateURI(const nsACString& aURI) {
+ nsAutoCString newURI(aURI);
+ ProcessURITemplate(newURI);
+
+ if (mPrivateURI.Equals(newURI)) {
+ return false;
+ }
+
+ mPrivateURI = newURI;
+ AsyncCreateTRRConnectionInfo(mPrivateURI);
+
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->NotifyObservers(nullptr, NS_NETWORK_TRR_URI_CHANGED_TOPIC, nullptr);
+ }
+ return true;
+}
+
+void TRRServiceParent::SetDetectedTrrURI(const nsACString& aURI) {
+ if (!mURIPref.IsEmpty()) {
+ return;
+ }
+
+ mURISetByDetection = MaybeSetPrivateURI(aURI);
+ gIOService->CallOrWaitForSocketProcess(
+ [self = RefPtr{this}, uri = nsAutoCString(aURI)]() {
+ Unused << self->SendSetDetectedTrrURI(uri);
+ });
+}
+
+void TRRServiceParent::GetURI(nsACString& aURI) {
+ // We don't need a lock here, since mPrivateURI is only touched on main
+ // thread.
+ MOZ_ASSERT(NS_IsMainThread());
+ aURI = mPrivateURI;
+}
+
+void TRRServiceParent::UpdateParentalControlEnabled() {
+ bool enabled = TRRService::GetParentalControlEnabledInternal();
+ RefPtr<TRRServiceParent> self = this;
+ gIOService->CallOrWaitForSocketProcess([self, enabled]() {
+ Unused << self->SendUpdateParentalControlEnabled(enabled);
+ });
+}
+
+// static
+void TRRServiceParent::PrefsChanged(const char* aName, void* aSelf) {
+ static_cast<TRRServiceParent*>(aSelf)->prefsChanged(aName);
+}
+
+void TRRServiceParent::prefsChanged(const char* aName) {
+ if (!aName || !strcmp(aName, "network.trr.uri") ||
+ !strcmp(aName, "network.trr.default_provider_uri") ||
+ !strcmp(aName, kRolloutURIPref) ||
+ !strcmp(aName, "network.trr.ohttp.uri")) {
+ OnTRRURIChange();
+ }
+
+ if (!aName || !strcmp(aName, "network.trr.mode") ||
+ !strcmp(aName, kRolloutModePref)) {
+ OnTRRModeChange();
+ }
+}
+
+void TRRServiceParent::ActorDestroy(ActorDestroyReason why) {
+ sTRRServiceParentPtr = nullptr;
+ Preferences::UnregisterPrefixCallbacks(TRRServiceParent::PrefsChanged,
+ gTRRUriCallbackPrefs, this);
+}
+
+NS_IMETHODIMP TRRServiceParent::OnProxyConfigChanged() {
+ LOG(("TRRServiceParent::OnProxyConfigChanged"));
+
+ AsyncCreateTRRConnectionInfo(mPrivateURI);
+ return NS_OK;
+}
+
+void TRRServiceParent::SetDefaultTRRConnectionInfo(
+ nsHttpConnectionInfo* aConnInfo) {
+ TRRServiceBase::SetDefaultTRRConnectionInfo(aConnInfo);
+
+ if (!CanSend()) {
+ return;
+ }
+
+ if (!aConnInfo) {
+ Unused << SendSetDefaultTRRConnectionInfo(Nothing());
+ return;
+ }
+
+ HttpConnectionInfoCloneArgs infoArgs;
+ nsHttpConnectionInfo::SerializeHttpConnectionInfo(aConnInfo, infoArgs);
+ Unused << SendSetDefaultTRRConnectionInfo(Some(infoArgs));
+}
+
+mozilla::ipc::IPCResult TRRServiceParent::RecvInitTRRConnectionInfo() {
+ InitTRRConnectionInfo();
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult TRRServiceParent::RecvSetConfirmationState(
+ uint32_t aNewState) {
+ mConfirmationState = aNewState;
+ return IPC_OK();
+}
+
+void TRRServiceParent::ReadEtcHostsFile() {
+ if (!sTRRServiceParentPtr) {
+ return;
+ }
+
+ DoReadEtcHostsFile([](const nsTArray<nsCString>* aArray) -> bool {
+ RefPtr<TRRServiceParent> service(sTRRServiceParentPtr);
+ if (service && aArray) {
+ nsTArray<nsCString> hosts(aArray->Clone());
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "TRRServiceParent::ReadEtcHostsFile",
+ [service, hosts = std::move(hosts)]() mutable {
+ if (service->CanSend()) {
+ Unused << service->SendUpdateEtcHosts(hosts);
+ }
+ }));
+ }
+ return !!service;
+ });
+}
+
+} // namespace net
+} // namespace mozilla