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