This is an automated email from the git hooks/post-receive script.
pierov pushed a commit to branch geckoview-99.0.1-11.0-1 in repository tor-browser.
commit 4387a6cb8e1dc248048b9e0f30169c9d290010e6 Author: Eden Chuang echuang@mozilla.com AuthorDate: Mon Mar 14 15:31:22 2022 +0000
Bug 1757147 - make FetchService observe the network status. r=dom-worker-reviewers,asuth,jesup, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D139953 --- dom/fetch/FetchService.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++--- dom/fetch/FetchService.h | 11 ++++- 2 files changed, 108 insertions(+), 8 deletions(-)
diff --git a/dom/fetch/FetchService.cpp b/dom/fetch/FetchService.cpp index e951d1c498036..7fb3beaa0a1b0 100644 --- a/dom/fetch/FetchService.cpp +++ b/dom/fetch/FetchService.cpp @@ -2,14 +2,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nsContentUtils.h" #include "FetchLog.h" +#include "nsContentUtils.h" +#include "nsICookieJarSettings.h" #include "nsILoadGroup.h" #include "nsILoadInfo.h" +#include "nsIIOService.h" +#include "nsIObserverService.h" #include "nsIPrincipal.h" -#include "nsICookieJarSettings.h" -#include "nsNetUtil.h" #include "nsIScriptSecurityManager.h" +#include "nsNetUtil.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" #include "mozilla/BasePrincipal.h" @@ -212,6 +214,8 @@ void FetchService::FetchInstance::FlushConsoleReport() {}
// FetchService
+NS_IMPL_ISUPPORTS(FetchService, nsIObserver) + StaticRefPtr<FetchService> gInstance;
/*static*/ @@ -221,6 +225,11 @@ already_AddRefed<FetchService> FetchService::GetInstance() {
if (!gInstance) { gInstance = MakeRefPtr<FetchService>(); + nsresult rv = gInstance->RegisterNetworkObserver(); + if (NS_WARN_IF(NS_FAILED(rv))) { + gInstance = nullptr; + return nullptr; + } ClearOnShutdown(&gInstance); } RefPtr<FetchService> service = gInstance; @@ -239,15 +248,96 @@ FetchService::FetchService() { MOZ_ASSERT(NS_IsMainThread()); }
-FetchService::~FetchService() = default; +FetchService::~FetchService() { + MOZ_ALWAYS_SUCCEEDS(UnregisterNetworkObserver()); +} + +nsresult FetchService::RegisterNetworkObserver() { + AssertIsOnMainThread(); + nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); + if (!observerService) { + return NS_ERROR_UNEXPECTED; + } + + nsCOMPtr<nsIIOService> ioService = services::GetIOService(); + if (!ioService) { + return NS_ERROR_UNEXPECTED; + } + + nsresult rv = observerService->AddObserver( + this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC, false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = observerService->AddObserver(this, "xpcom-shutdown", false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = ioService->GetOffline(&mOffline); + NS_ENSURE_SUCCESS(rv, rv); + mObservingNetwork = true; + + return NS_OK; +} + +nsresult FetchService::UnregisterNetworkObserver() { + AssertIsOnMainThread(); + nsresult rv; + if (mObservingNetwork) { + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) { + rv = observerService->RemoveObserver(this, + NS_IOSERVICE_OFFLINE_STATUS_TOPIC); + NS_ENSURE_SUCCESS(rv, rv); + rv = observerService->RemoveObserver(this, "xpcom-shutdown"); + NS_ENSURE_SUCCESS(rv, rv); + } + mObservingNetwork = false; + } + return NS_OK; +} + +NS_IMETHODIMP FetchService::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + FETCH_LOG(("FetchService::Observe topic: %s", aTopic)); + AssertIsOnMainThread(); + MOZ_ASSERT(!strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) || + !strcmp(aTopic, "xpcom-shutdown")); + + if (!strcmp(aTopic, "xpcom-shutdown")) { + // Going to shutdown, unregister the network status observer to avoid + // receiving + nsresult rv = UnregisterNetworkObserver(); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; + } + + if (nsDependentString(aData).EqualsLiteral(NS_IOSERVICE_ONLINE)) { + mOffline = false; + } else { + mOffline = true; + // Network is offline, cancel running fetchs. + for (auto it = mFetchInstanceTable.begin(), end = mFetchInstanceTable.end(); + it != end; ++it) { + it->GetData()->Cancel(); + } + mFetchInstanceTable.Clear(); + } + return NS_OK; +}
RefPtr<FetchServiceResponsePromise> FetchService::Fetch( SafeRefPtr<InternalRequest> aRequest, nsIChannel* aChannel) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread());
- FETCH_LOG(("FetchService::Fetch aRequest[%p], aChannel[%p]", - aRequest.unsafeGetRawPtr(), aChannel)); + FETCH_LOG(("FetchService::Fetch aRequest[%p], aChannel[%p], mOffline: %s", + aRequest.unsafeGetRawPtr(), aChannel, + mOffline ? "true" : "false")); + + if (mOffline) { + FETCH_LOG(("FetchService::Fetch network offline")); + return NetworkErrorResponse(NS_ERROR_OFFLINE); + }
// Create FetchInstance RefPtr<FetchInstance> fetch = MakeRefPtr<FetchInstance>(aRequest.clonePtr()); @@ -291,7 +381,10 @@ void FetchService::CancelFetch(
auto entry = mFetchInstanceTable.Lookup(aResponsePromise); if (entry) { + // Notice any modifications here before entry.Remove() probably should be + // reflected to Observe() offline case. entry.Data()->Cancel(); + entry.Remove(); FETCH_LOG(("FetchService::CancelFetch aResponsePromise[%p] is removed", aResponsePromise.get())); diff --git a/dom/fetch/FetchService.h b/dom/fetch/FetchService.h index ea83b02137f72..458ae11b7dffe 100644 --- a/dom/fetch/FetchService.h +++ b/dom/fetch/FetchService.h @@ -5,6 +5,7 @@ #define _mozilla_dom_FetchService_h
#include "nsIChannel.h" +#include "nsIObserver.h" #include "nsTHashMap.h" #include "mozilla/ErrorResult.h" #include "mozilla/MozPromise.h" @@ -41,9 +42,10 @@ using FetchServiceResponsePromise = * the FetchServiceResponsePromise would be resolved or rejected. The promise * consumers can set callbacks to handle the Fetch result. */ -class FetchService final { +class FetchService final : public nsIObserver { public: - NS_INLINE_DECL_REFCOUNTING(FetchService) + NS_DECL_ISUPPORTS; + NS_DECL_NSIOBSERVER;
static already_AddRefed<FetchService> GetInstance();
@@ -112,10 +114,15 @@ class FetchService final {
~FetchService();
+ nsresult RegisterNetworkObserver(); + nsresult UnregisterNetworkObserver(); + // This is a container to manage the generated fetches. nsTHashMap<nsRefPtrHashKey<FetchServiceResponsePromise>, RefPtr<FetchInstance> > mFetchInstanceTable; + bool mObservingNetwork{false}; + bool mOffline{false}; };
} // namespace mozilla::dom