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 RefPtr
<SocketProcessParent
> socketParent
=
51 SocketProcessParent::GetSingleton();
56 nsCOMPtr
<nsIObserverService
> obs
=
57 static_cast<nsIObserverService
*>(gIOService
);
58 TRRService::AddObserver(this, obs
);
60 bool captiveIsPassed
= TRRService::CheckCaptivePortalIsPassed();
61 bool parentalControlEnabled
=
62 TRRService::GetParentalControlsEnabledInternal();
64 nsCOMPtr
<nsINetworkLinkService
> nls
=
65 do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID
);
66 nsTArray
<nsCString
> suffixList
;
68 nls
->GetDnsSuffixList(suffixList
);
71 Preferences::RegisterPrefixCallbacks(TRRServiceParent::PrefsChanged
,
72 gTRRUriCallbackPrefs
, this);
73 prefsChanged(nullptr);
75 if (socketParent
->SendPTRRServiceConstructor(
76 this, captiveIsPassed
, parentalControlEnabled
, suffixList
)) {
77 sTRRServiceParentPtr
= this;
82 TRRServiceParent::Observe(nsISupports
* aSubject
, const char* aTopic
,
83 const char16_t
* aData
) {
84 if (!strcmp(aTopic
, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC
) ||
85 !strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
)) {
86 nsCOMPtr
<nsINetworkLinkService
> link
= do_QueryInterface(aSubject
);
87 // The network link service notification normally passes itself as the
88 // subject, but some unit tests will sometimes pass a null subject.
90 nsTArray
<nsCString
> suffixList
;
91 link
->GetDnsSuffixList(suffixList
);
92 Unused
<< SendUpdatePlatformDNSInformation(suffixList
);
95 if (!strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
) && mURISetByDetection
) {
103 mozilla::ipc::IPCResult
104 TRRServiceParent::RecvNotifyNetworkConnectivityServiceObservers(
105 const nsCString
& aTopic
) {
106 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
108 obs
->NotifyObservers(nullptr, aTopic
.get(), nullptr);
113 bool TRRServiceParent::MaybeSetPrivateURI(const nsACString
& aURI
) {
114 nsAutoCString
newURI(aURI
);
115 ProcessURITemplate(newURI
);
117 if (mPrivateURI
.Equals(newURI
)) {
121 mPrivateURI
= newURI
;
122 AsyncCreateTRRConnectionInfo(mPrivateURI
);
124 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
126 obs
->NotifyObservers(nullptr, NS_NETWORK_TRR_URI_CHANGED_TOPIC
, nullptr);
131 void TRRServiceParent::SetDetectedTrrURI(const nsACString
& aURI
) {
132 if (!mURIPref
.IsEmpty()) {
136 mURISetByDetection
= MaybeSetPrivateURI(aURI
);
137 gIOService
->CallOrWaitForSocketProcess(
138 [self
= RefPtr
{this}, uri
= nsAutoCString(aURI
)]() {
139 Unused
<< self
->SendSetDetectedTrrURI(uri
);
143 void TRRServiceParent::GetURI(nsACString
& aURI
) {
144 // We don't need a lock here, since mPrivateURI is only touched on main
146 MOZ_ASSERT(NS_IsMainThread());
150 void TRRServiceParent::ReloadParentalControlsEnabled() {
151 bool enabled
= TRRService::ReloadParentalControlsEnabled();
152 RefPtr
<TRRServiceParent
> self
= this;
153 gIOService
->CallOrWaitForSocketProcess([self
, enabled
]() {
154 Unused
<< self
->SendUpdateParentalControlEnabled(enabled
);
159 void TRRServiceParent::PrefsChanged(const char* aName
, void* aSelf
) {
160 static_cast<TRRServiceParent
*>(aSelf
)->prefsChanged(aName
);
163 void TRRServiceParent::prefsChanged(const char* aName
) {
164 if (!aName
|| !strcmp(aName
, "network.trr.uri") ||
165 !strcmp(aName
, "network.trr.default_provider_uri") ||
166 !strcmp(aName
, kRolloutURIPref
) ||
167 !strcmp(aName
, "network.trr.ohttp.uri")) {
171 if (!aName
|| !strcmp(aName
, "network.trr.mode") ||
172 !strcmp(aName
, kRolloutModePref
)) {
177 void TRRServiceParent::ActorDestroy(ActorDestroyReason why
) {
178 sTRRServiceParentPtr
= nullptr;
179 Preferences::UnregisterPrefixCallbacks(TRRServiceParent::PrefsChanged
,
180 gTRRUriCallbackPrefs
, this);
183 NS_IMETHODIMP
TRRServiceParent::OnProxyConfigChanged() {
184 LOG(("TRRServiceParent::OnProxyConfigChanged"));
186 AsyncCreateTRRConnectionInfo(mPrivateURI
);
190 void TRRServiceParent::SetDefaultTRRConnectionInfo(
191 nsHttpConnectionInfo
* aConnInfo
) {
192 TRRServiceBase::SetDefaultTRRConnectionInfo(aConnInfo
);
199 Unused
<< SendSetDefaultTRRConnectionInfo(Nothing());
203 HttpConnectionInfoCloneArgs infoArgs
;
204 nsHttpConnectionInfo::SerializeHttpConnectionInfo(aConnInfo
, infoArgs
);
205 Unused
<< SendSetDefaultTRRConnectionInfo(Some(infoArgs
));
208 mozilla::ipc::IPCResult
TRRServiceParent::RecvInitTRRConnectionInfo() {
209 InitTRRConnectionInfo();
213 mozilla::ipc::IPCResult
TRRServiceParent::RecvSetConfirmationState(
214 uint32_t aNewState
) {
215 mConfirmationState
= aNewState
;
219 void TRRServiceParent::ReadEtcHostsFile() {
220 if (!sTRRServiceParentPtr
) {
224 DoReadEtcHostsFile([](const nsTArray
<nsCString
>* aArray
) -> bool {
225 RefPtr
<TRRServiceParent
> service(sTRRServiceParentPtr
);
226 if (service
&& aArray
) {
227 nsTArray
<nsCString
> hosts(aArray
->Clone());
228 NS_DispatchToMainThread(NS_NewRunnableFunction(
229 "TRRServiceParent::ReadEtcHostsFile",
230 [service
, hosts
= std::move(hosts
)]() mutable {
231 if (service
->CanSend()) {
232 Unused
<< service
->SendUpdateEtcHosts(hosts
);
241 } // namespace mozilla