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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/net/TRRServiceParent.h"
9 #include "mozilla/ipc/FileDescriptor.h"
10 #include "mozilla/net/SocketProcessParent.h"
11 #include "mozilla/psm/PSMIPCTypes.h"
12 #include "mozilla/Preferences.h"
13 #include "mozilla/Unused.h"
14 #include "nsHttpConnectionInfo.h"
15 #include "nsICaptivePortalService.h"
16 #include "nsIParentalControlsService.h"
17 #include "nsINetworkLinkService.h"
18 #include "nsIObserverService.h"
19 #include "nsIOService.h"
21 #include "TRRService.h"
23 #include "DNSLogging.h"
28 static Atomic
<TRRServiceParent
*> sTRRServiceParentPtr
;
30 static const char* gTRRUriCallbackPrefs
[] = {
31 "network.trr.uri", "network.trr.default_provider_uri",
32 "network.trr.mode", kRolloutURIPref
,
33 kRolloutModePref
, nullptr,
36 NS_IMPL_ISUPPORTS_INHERITED(TRRServiceParent
, TRRServiceBase
, nsIObserver
,
37 nsISupportsWeakReference
)
39 TRRServiceParent::~TRRServiceParent() = default;
41 void TRRServiceParent::Init() {
42 MOZ_ASSERT(gIOService
);
44 if (!gIOService
->SocketProcessReady()) {
45 RefPtr
<TRRServiceParent
> self
= this;
46 gIOService
->CallOrWaitForSocketProcess([self
]() { self
->Init(); });
50 SocketProcessParent
* socketParent
= SocketProcessParent::GetSingleton();
55 nsCOMPtr
<nsIObserverService
> obs
=
56 static_cast<nsIObserverService
*>(gIOService
);
57 TRRService::AddObserver(this, obs
);
59 bool captiveIsPassed
= TRRService::CheckCaptivePortalIsPassed();
60 bool parentalControlEnabled
= TRRService::GetParentalControlEnabledInternal();
62 nsCOMPtr
<nsINetworkLinkService
> nls
=
63 do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID
);
64 nsTArray
<nsCString
> suffixList
;
66 nls
->GetDnsSuffixList(suffixList
);
69 Preferences::RegisterPrefixCallbacks(TRRServiceParent::PrefsChanged
,
70 gTRRUriCallbackPrefs
, this);
71 prefsChanged(nullptr);
73 if (socketParent
->SendPTRRServiceConstructor(
74 this, captiveIsPassed
, parentalControlEnabled
, suffixList
)) {
75 sTRRServiceParentPtr
= this;
80 TRRServiceParent::Observe(nsISupports
* aSubject
, const char* aTopic
,
81 const char16_t
* aData
) {
82 if (!strcmp(aTopic
, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC
) ||
83 !strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
)) {
84 nsCOMPtr
<nsINetworkLinkService
> link
= do_QueryInterface(aSubject
);
85 // The network link service notification normally passes itself as the
86 // subject, but some unit tests will sometimes pass a null subject.
88 nsTArray
<nsCString
> suffixList
;
89 link
->GetDnsSuffixList(suffixList
);
90 Unused
<< SendUpdatePlatformDNSInformation(suffixList
);
93 if (!strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
) && mURISetByDetection
) {
101 mozilla::ipc::IPCResult
102 TRRServiceParent::RecvNotifyNetworkConnectivityServiceObservers(
103 const nsCString
& aTopic
) {
104 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
106 obs
->NotifyObservers(nullptr, aTopic
.get(), nullptr);
111 bool TRRServiceParent::MaybeSetPrivateURI(const nsACString
& aURI
) {
112 nsAutoCString
newURI(aURI
);
113 ProcessURITemplate(newURI
);
115 if (mPrivateURI
.Equals(newURI
)) {
119 mPrivateURI
= newURI
;
120 AsyncCreateTRRConnectionInfo(mPrivateURI
);
122 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
124 obs
->NotifyObservers(nullptr, NS_NETWORK_TRR_URI_CHANGED_TOPIC
, nullptr);
129 void TRRServiceParent::SetDetectedTrrURI(const nsACString
& aURI
) {
130 if (!mURIPref
.IsEmpty()) {
134 mURISetByDetection
= MaybeSetPrivateURI(aURI
);
135 gIOService
->CallOrWaitForSocketProcess(
136 [self
= RefPtr
{this}, uri
= nsAutoCString(aURI
)]() {
137 Unused
<< self
->SendSetDetectedTrrURI(uri
);
141 void TRRServiceParent::GetURI(nsACString
& aURI
) {
142 // We don't need a lock here, since mPrivateURI is only touched on main
144 MOZ_ASSERT(NS_IsMainThread());
148 void TRRServiceParent::UpdateParentalControlEnabled() {
149 bool enabled
= TRRService::GetParentalControlEnabledInternal();
150 RefPtr
<TRRServiceParent
> self
= this;
151 gIOService
->CallOrWaitForSocketProcess([self
, enabled
]() {
152 Unused
<< self
->SendUpdateParentalControlEnabled(enabled
);
157 void TRRServiceParent::PrefsChanged(const char* aName
, void* aSelf
) {
158 static_cast<TRRServiceParent
*>(aSelf
)->prefsChanged(aName
);
161 void TRRServiceParent::prefsChanged(const char* aName
) {
162 if (!aName
|| !strcmp(aName
, "network.trr.uri") ||
163 !strcmp(aName
, "network.trr.default_provider_uri") ||
164 !strcmp(aName
, kRolloutURIPref
) ||
165 !strcmp(aName
, "network.trr.ohttp.uri")) {
169 if (!aName
|| !strcmp(aName
, "network.trr.mode") ||
170 !strcmp(aName
, kRolloutModePref
)) {
175 void TRRServiceParent::ActorDestroy(ActorDestroyReason why
) {
176 sTRRServiceParentPtr
= nullptr;
177 Preferences::UnregisterPrefixCallbacks(TRRServiceParent::PrefsChanged
,
178 gTRRUriCallbackPrefs
, this);
181 NS_IMETHODIMP
TRRServiceParent::OnProxyConfigChanged() {
182 LOG(("TRRServiceParent::OnProxyConfigChanged"));
184 AsyncCreateTRRConnectionInfo(mPrivateURI
);
188 void TRRServiceParent::SetDefaultTRRConnectionInfo(
189 nsHttpConnectionInfo
* aConnInfo
) {
190 TRRServiceBase::SetDefaultTRRConnectionInfo(aConnInfo
);
197 Unused
<< SendSetDefaultTRRConnectionInfo(Nothing());
201 HttpConnectionInfoCloneArgs infoArgs
;
202 nsHttpConnectionInfo::SerializeHttpConnectionInfo(aConnInfo
, infoArgs
);
203 Unused
<< SendSetDefaultTRRConnectionInfo(Some(infoArgs
));
206 mozilla::ipc::IPCResult
TRRServiceParent::RecvInitTRRConnectionInfo() {
207 InitTRRConnectionInfo();
211 mozilla::ipc::IPCResult
TRRServiceParent::RecvSetConfirmationState(
212 uint32_t aNewState
) {
213 mConfirmationState
= aNewState
;
217 void TRRServiceParent::ReadEtcHostsFile() {
218 if (!sTRRServiceParentPtr
) {
222 DoReadEtcHostsFile([](const nsTArray
<nsCString
>* aArray
) -> bool {
223 RefPtr
<TRRServiceParent
> service(sTRRServiceParentPtr
);
224 if (service
&& aArray
) {
225 nsTArray
<nsCString
> hosts(aArray
->Clone());
226 NS_DispatchToMainThread(NS_NewRunnableFunction(
227 "TRRServiceParent::ReadEtcHostsFile",
228 [service
, hosts
= std::move(hosts
)]() mutable {
229 if (service
->CanSend()) {
230 Unused
<< service
->SendUpdateEtcHosts(hosts
);
239 } // namespace mozilla