nsNetworkLinkService.cpp (6263B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set et sw=2 ts=4: */ 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 "nsIObserverService.h" 8 #include "nsNetworkLinkService.h" 9 #include "nsString.h" 10 #include "mozilla/Logging.h" 11 #include "mozilla/IntegerPrintfMacros.h" 12 #include "nsNetAddr.h" 13 14 #include "mozilla/StaticPrefs_network.h" 15 #include "mozilla/Services.h" 16 17 using namespace mozilla; 18 19 static LazyLogModule gNotifyAddrLog("nsNetworkLinkService"); 20 #define LOG(args) MOZ_LOG(gNotifyAddrLog, mozilla::LogLevel::Debug, args) 21 22 NS_IMPL_ISUPPORTS(nsNetworkLinkService, nsINetworkLinkService, nsIObserver) 23 24 nsNetworkLinkService::nsNetworkLinkService() : mStatusIsKnown(false) {} 25 26 NS_IMETHODIMP 27 nsNetworkLinkService::GetIsLinkUp(bool* aIsUp) { 28 if (!mNetlinkSvc) { 29 return NS_ERROR_NOT_AVAILABLE; 30 } 31 32 mNetlinkSvc->GetIsLinkUp(aIsUp); 33 return NS_OK; 34 } 35 36 NS_IMETHODIMP 37 nsNetworkLinkService::GetLinkStatusKnown(bool* aIsKnown) { 38 *aIsKnown = mStatusIsKnown; 39 return NS_OK; 40 } 41 42 NS_IMETHODIMP 43 nsNetworkLinkService::GetLinkType(uint32_t* aLinkType) { 44 NS_ENSURE_ARG_POINTER(aLinkType); 45 46 // XXX This function has not yet been implemented for this platform 47 *aLinkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN; 48 return NS_OK; 49 } 50 51 NS_IMETHODIMP 52 nsNetworkLinkService::GetNetworkID(nsACString& aNetworkID) { 53 #ifdef BASE_BROWSER_VERSION 54 aNetworkID.Truncate(); 55 #else 56 if (!mNetlinkSvc) { 57 return NS_ERROR_NOT_AVAILABLE; 58 } 59 60 mNetlinkSvc->GetNetworkID(aNetworkID); 61 #endif 62 return NS_OK; 63 } 64 65 NS_IMETHODIMP 66 nsNetworkLinkService::GetDnsSuffixList(nsTArray<nsCString>& aDnsSuffixList) { 67 if (!mNetlinkSvc) { 68 return NS_ERROR_NOT_AVAILABLE; 69 } 70 71 return mNetlinkSvc->GetDnsSuffixList(aDnsSuffixList); 72 } 73 74 NS_IMETHODIMP 75 nsNetworkLinkService::GetResolvers(nsTArray<RefPtr<nsINetAddr>>& aResolvers) { 76 nsTArray<mozilla::net::NetAddr> addresses; 77 nsresult rv = GetNativeResolvers(addresses); 78 if (NS_FAILED(rv)) { 79 return rv; 80 } 81 82 for (const auto& addr : addresses) { 83 aResolvers.AppendElement(MakeRefPtr<nsNetAddr>(&addr)); 84 } 85 return NS_OK; 86 } 87 88 NS_IMETHODIMP 89 nsNetworkLinkService::GetNativeResolvers( 90 nsTArray<mozilla::net::NetAddr>& aResolvers) { 91 if (!mNetlinkSvc) { 92 return NS_ERROR_NOT_AVAILABLE; 93 } 94 return mNetlinkSvc->GetResolvers(aResolvers); 95 } 96 97 NS_IMETHODIMP 98 nsNetworkLinkService::GetPlatformDNSIndications( 99 uint32_t* aPlatformDNSIndications) { 100 return NS_ERROR_NOT_IMPLEMENTED; 101 } 102 103 NS_IMETHODIMP 104 nsNetworkLinkService::Observe(nsISupports* subject, const char* topic, 105 const char16_t* data) { 106 if (!strcmp("xpcom-shutdown-threads", topic)) { 107 Shutdown(); 108 } 109 110 return NS_OK; 111 } 112 113 nsresult nsNetworkLinkService::Init() { 114 nsCOMPtr<nsIObserverService> observerService = 115 mozilla::services::GetObserverService(); 116 if (!observerService) { 117 return NS_ERROR_FAILURE; 118 } 119 120 nsresult rv; 121 rv = observerService->AddObserver(this, "xpcom-shutdown-threads", false); 122 NS_ENSURE_SUCCESS(rv, rv); 123 124 mNetlinkSvc = new mozilla::net::NetlinkService(); 125 rv = mNetlinkSvc->Init(this); 126 if (NS_FAILED(rv)) { 127 mNetlinkSvc = nullptr; 128 LOG(("Cannot initialize NetlinkService [rv=0x%08" PRIx32 "]", 129 static_cast<uint32_t>(rv))); 130 return rv; 131 } 132 NS_ENSURE_SUCCESS(rv, rv); 133 134 return NS_OK; 135 } 136 137 nsresult nsNetworkLinkService::Shutdown() { 138 // remove xpcom shutdown observer 139 nsCOMPtr<nsIObserverService> observerService = 140 mozilla::services::GetObserverService(); 141 if (observerService) { 142 observerService->RemoveObserver(this, "xpcom-shutdown-threads"); 143 } 144 145 if (mNetlinkSvc) { 146 mNetlinkSvc->Shutdown(); 147 mNetlinkSvc = nullptr; 148 } 149 150 return NS_OK; 151 } 152 153 void nsNetworkLinkService::OnNetworkChanged() { 154 if (StaticPrefs::network_notify_changed()) { 155 RefPtr<nsNetworkLinkService> self = this; 156 NS_DispatchToMainThread(NS_NewRunnableFunction( 157 "nsNetworkLinkService::OnNetworkChanged", [self]() { 158 self->NotifyObservers(NS_NETWORK_LINK_TOPIC, 159 NS_NETWORK_LINK_DATA_CHANGED); 160 })); 161 } 162 } 163 164 void nsNetworkLinkService::OnNetworkIDChanged() { 165 RefPtr<nsNetworkLinkService> self = this; 166 NS_DispatchToMainThread(NS_NewRunnableFunction( 167 "nsNetworkLinkService::OnNetworkIDChanged", [self]() { 168 self->NotifyObservers(NS_NETWORK_ID_CHANGED_TOPIC, nullptr); 169 })); 170 } 171 172 void nsNetworkLinkService::OnLinkUp() { 173 RefPtr<nsNetworkLinkService> self = this; 174 NS_DispatchToMainThread( 175 NS_NewRunnableFunction("nsNetworkLinkService::OnLinkUp", [self]() { 176 self->NotifyObservers(NS_NETWORK_LINK_TOPIC, NS_NETWORK_LINK_DATA_UP); 177 })); 178 } 179 180 void nsNetworkLinkService::OnLinkDown() { 181 RefPtr<nsNetworkLinkService> self = this; 182 NS_DispatchToMainThread( 183 NS_NewRunnableFunction("nsNetworkLinkService::OnLinkDown", [self]() { 184 self->NotifyObservers(NS_NETWORK_LINK_TOPIC, NS_NETWORK_LINK_DATA_DOWN); 185 })); 186 } 187 188 void nsNetworkLinkService::OnLinkStatusKnown() { mStatusIsKnown = true; } 189 190 void nsNetworkLinkService::OnDnsSuffixListUpdated() { 191 RefPtr<nsNetworkLinkService> self = this; 192 NS_DispatchToMainThread(NS_NewRunnableFunction( 193 "nsNetworkLinkService::OnDnsSuffixListUpdated", [self]() { 194 self->NotifyObservers(NS_DNS_SUFFIX_LIST_UPDATED_TOPIC, nullptr); 195 })); 196 } 197 198 /* Sends the given event. Assumes aTopic/aData never goes out of scope (static 199 * strings are ideal). 200 */ 201 void nsNetworkLinkService::NotifyObservers(const char* aTopic, 202 const char* aData) { 203 MOZ_ASSERT(NS_IsMainThread()); 204 205 LOG(("nsNetworkLinkService::NotifyObservers: topic:%s data:%s\n", aTopic, 206 aData ? aData : "")); 207 208 nsCOMPtr<nsIObserverService> observerService = 209 mozilla::services::GetObserverService(); 210 211 if (observerService) { 212 observerService->NotifyObservers( 213 static_cast<nsINetworkLinkService*>(this), aTopic, 214 aData ? NS_ConvertASCIItoUTF16(aData).get() : nullptr); 215 } 216 } 217 218 // static 219 bool nsINetworkLinkService::HasNonLocalIPv6Address() { 220 return mozilla::net::NetlinkService::HasNonLocalIPv6Address(); 221 }