TRRServiceParent.cpp (7216B)
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/. */ 6 7 #include "mozilla/net/TRRServiceParent.h" 8 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 "nsHttpConnectionInfo.h" 14 #include "nsICaptivePortalService.h" 15 #include "nsIParentalControlsService.h" 16 #include "nsINetworkLinkService.h" 17 #include "nsIObserverService.h" 18 #include "nsIOService.h" 19 #include "nsNetCID.h" 20 #include "TRRService.h" 21 22 #include "DNSLogging.h" 23 24 namespace mozilla { 25 namespace net { 26 27 static Atomic<TRRServiceParent*> sTRRServiceParentPtr; 28 29 static const char* gTRRUriCallbackPrefs[] = { 30 "network.trr.uri", "network.trr.default_provider_uri", 31 "network.trr.mode", kRolloutURIPref, 32 kRolloutModePref, nullptr, 33 }; 34 35 NS_IMPL_ISUPPORTS_INHERITED(TRRServiceParent, TRRServiceBase, nsIObserver, 36 nsISupportsWeakReference) 37 38 TRRServiceParent::~TRRServiceParent() = default; 39 40 void TRRServiceParent::Init() { 41 MOZ_ASSERT(gIOService); 42 43 if (!gIOService->SocketProcessReady()) { 44 RefPtr<TRRServiceParent> self = this; 45 gIOService->CallOrWaitForSocketProcess([self]() { self->Init(); }); 46 return; 47 } 48 49 RefPtr<SocketProcessParent> socketParent = 50 SocketProcessParent::GetSingleton(); 51 if (!socketParent) { 52 return; 53 } 54 55 nsCOMPtr<nsIObserverService> obs = 56 static_cast<nsIObserverService*>(gIOService); 57 TRRService::AddObserver(this, obs); 58 59 bool captiveIsPassed = TRRService::CheckCaptivePortalIsPassed(); 60 bool parentalControlEnabled = 61 TRRService::GetParentalControlsEnabledInternal(); 62 63 nsCOMPtr<nsINetworkLinkService> nls = 64 do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID); 65 nsTArray<nsCString> suffixList; 66 if (nls) { 67 nls->GetDnsSuffixList(suffixList); 68 } 69 70 Preferences::RegisterPrefixCallbacks(TRRServiceParent::PrefsChanged, 71 gTRRUriCallbackPrefs, this); 72 prefsChanged(nullptr); 73 74 if (socketParent->SendPTRRServiceConstructor( 75 this, captiveIsPassed, parentalControlEnabled, suffixList)) { 76 sTRRServiceParentPtr = this; 77 } 78 } 79 80 NS_IMETHODIMP 81 TRRServiceParent::Observe(nsISupports* aSubject, const char* aTopic, 82 const char16_t* aData) { 83 if (!strcmp(aTopic, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC) || 84 !strcmp(aTopic, NS_NETWORK_LINK_TOPIC)) { 85 nsCOMPtr<nsINetworkLinkService> link = do_QueryInterface(aSubject); 86 // The network link service notification normally passes itself as the 87 // subject, but some unit tests will sometimes pass a null subject. 88 if (link) { 89 nsTArray<nsCString> suffixList; 90 link->GetDnsSuffixList(suffixList); 91 (void)SendUpdatePlatformDNSInformation(suffixList); 92 } 93 94 if (!strcmp(aTopic, NS_NETWORK_LINK_TOPIC) && mURISetByDetection) { 95 CheckURIPrefs(); 96 } 97 } 98 99 return NS_OK; 100 } 101 102 mozilla::ipc::IPCResult 103 TRRServiceParent::RecvNotifyNetworkConnectivityServiceObservers( 104 const nsCString& aTopic) { 105 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 106 if (obs) { 107 obs->NotifyObservers(nullptr, aTopic.get(), nullptr); 108 } 109 return IPC_OK(); 110 } 111 112 bool TRRServiceParent::MaybeSetPrivateURI(const nsACString& aURI) { 113 nsAutoCString newURI(aURI); 114 ProcessURITemplate(newURI); 115 116 if (mPrivateURI.Equals(newURI)) { 117 return false; 118 } 119 120 mPrivateURI = newURI; 121 AsyncCreateTRRConnectionInfo(mPrivateURI); 122 123 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); 124 if (obs) { 125 obs->NotifyObservers(nullptr, NS_NETWORK_TRR_URI_CHANGED_TOPIC, nullptr); 126 } 127 return true; 128 } 129 130 void TRRServiceParent::SetDetectedTrrURI(const nsACString& aURI) { 131 if (!mURIPref.IsEmpty()) { 132 return; 133 } 134 135 mURISetByDetection = MaybeSetPrivateURI(aURI); 136 gIOService->CallOrWaitForSocketProcess( 137 [self = RefPtr{this}, uri = nsAutoCString(aURI)]() { 138 (void)self->SendSetDetectedTrrURI(uri); 139 }); 140 } 141 142 void TRRServiceParent::GetURI(nsACString& aURI) { 143 // We don't need a lock here, since mPrivateURI is only touched on main 144 // thread. 145 MOZ_ASSERT(NS_IsMainThread()); 146 aURI = mPrivateURI; 147 } 148 149 void TRRServiceParent::ReloadParentalControlsEnabled() { 150 bool enabled = TRRService::ReloadParentalControlsEnabled(); 151 RefPtr<TRRServiceParent> self = this; 152 gIOService->CallOrWaitForSocketProcess([self, enabled]() { 153 (void)self->SendUpdateParentalControlEnabled(enabled); 154 }); 155 } 156 157 // static 158 void TRRServiceParent::PrefsChanged(const char* aName, void* aSelf) { 159 static_cast<TRRServiceParent*>(aSelf)->prefsChanged(aName); 160 } 161 162 void TRRServiceParent::prefsChanged(const char* aName) { 163 if (!aName || !strcmp(aName, "network.trr.uri") || 164 !strcmp(aName, "network.trr.default_provider_uri") || 165 !strcmp(aName, kRolloutURIPref) || 166 !strcmp(aName, "network.trr.ohttp.uri")) { 167 OnTRRURIChange(); 168 } 169 170 if (!aName || !strcmp(aName, "network.trr.mode") || 171 !strcmp(aName, kRolloutModePref)) { 172 OnTRRModeChange(); 173 } 174 } 175 176 void TRRServiceParent::ActorDestroy(ActorDestroyReason why) { 177 sTRRServiceParentPtr = nullptr; 178 Preferences::UnregisterPrefixCallbacks(TRRServiceParent::PrefsChanged, 179 gTRRUriCallbackPrefs, this); 180 } 181 182 NS_IMETHODIMP TRRServiceParent::OnProxyConfigChanged() { 183 LOG(("TRRServiceParent::OnProxyConfigChanged")); 184 185 AsyncCreateTRRConnectionInfo(mPrivateURI); 186 return NS_OK; 187 } 188 189 void TRRServiceParent::SetDefaultTRRConnectionInfo( 190 nsHttpConnectionInfo* aConnInfo) { 191 TRRServiceBase::SetDefaultTRRConnectionInfo(aConnInfo); 192 193 if (!CanSend()) { 194 return; 195 } 196 197 if (!aConnInfo) { 198 (void)SendSetDefaultTRRConnectionInfo(Nothing()); 199 return; 200 } 201 202 HttpConnectionInfoCloneArgs infoArgs; 203 nsHttpConnectionInfo::SerializeHttpConnectionInfo(aConnInfo, infoArgs); 204 (void)SendSetDefaultTRRConnectionInfo(Some(infoArgs)); 205 } 206 207 mozilla::ipc::IPCResult TRRServiceParent::RecvInitTRRConnectionInfo( 208 bool aForceReinit) { 209 InitTRRConnectionInfo(aForceReinit); 210 return IPC_OK(); 211 } 212 213 mozilla::ipc::IPCResult TRRServiceParent::RecvSetConfirmationState( 214 uint32_t aNewState) { 215 mConfirmationState = aNewState; 216 return IPC_OK(); 217 } 218 219 void TRRServiceParent::ReadEtcHostsFile() { 220 if (!sTRRServiceParentPtr) { 221 return; 222 } 223 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( 229 NS_NewRunnableFunction("TRRServiceParent::ReadEtcHostsFile", 230 [service, hosts = std::move(hosts)]() mutable { 231 if (service->CanSend()) { 232 (void)service->SendUpdateEtcHosts(hosts); 233 } 234 })); 235 } 236 return !!service; 237 }); 238 } 239 240 } // namespace net 241 } // namespace mozilla