diff options
Diffstat (limited to 'netwerk/dns/TRRServiceParent.cpp')
-rw-r--r-- | netwerk/dns/TRRServiceParent.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/netwerk/dns/TRRServiceParent.cpp b/netwerk/dns/TRRServiceParent.cpp new file mode 100644 index 0000000000..9002f239fe --- /dev/null +++ b/netwerk/dns/TRRServiceParent.cpp @@ -0,0 +1,155 @@ +/* -*- 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 "nsICaptivePortalService.h" +#include "nsIParentalControlsService.h" +#include "nsINetworkLinkService.h" +#include "nsIObserverService.h" +#include "nsIOService.h" +#include "nsNetCID.h" +#include "TRRService.h" + +namespace mozilla { +namespace net { + +static const char kRolloutURIPref[] = "doh-rollout.uri"; +static const char kRolloutModePref[] = "doh-rollout.mode"; + +static const char* gTRRUriCallbackPrefs[] = { + "network.trr.uri", "network.trr.mode", kRolloutURIPref, kRolloutModePref, + nullptr, +}; + +NS_IMPL_ISUPPORTS(TRRServiceParent, nsIObserver, nsISupportsWeakReference) + +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); + + Unused << socketParent->SendPTRRServiceConstructor( + this, captiveIsPassed, parentalControlEnabled, suffixList); +} + +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; +} + +bool TRRServiceParent::MaybeSetPrivateURI(const nsACString& aURI) { + nsAutoCString newURI(aURI); + ProcessURITemplate(newURI); + + if (mPrivateURI.Equals(newURI)) { + return false; + } + + mPrivateURI = newURI; + + 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 (mURIPrefHasUserValue) { + return; + } + + mURISetByDetection = MaybeSetPrivateURI(aURI); + RefPtr<TRRServiceParent> self = this; + nsCString uri(aURI); + gIOService->CallOrWaitForSocketProcess( + [self, uri]() { Unused << self->SendSetDetectedTrrURI(uri); }); +} + +void TRRServiceParent::GetTrrURI(nsACString& aURI) { 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, kRolloutURIPref)) { + OnTRRURIChange(); + } + + if (!aName || !strcmp(aName, "network.trr.mode") || + !strcmp(aName, kRolloutModePref)) { + OnTRRModeChange(); + } +} + +void TRRServiceParent::ActorDestroy(ActorDestroyReason why) { + Preferences::UnregisterPrefixCallbacks(TRRServiceParent::PrefsChanged, + gTRRUriCallbackPrefs, this); +} + +} // namespace net +} // namespace mozilla |