
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 -- To stop receiving notification emails like this one, please contact the administrator of this repository.