diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 03b3f0cda2db..556fb4ff857c 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -1629,6 +1629,7 @@ ServiceWorkerManager::AddRegistrationEventListener(nsIURI* aDocumentURI, nsIDOME // TODO: this is very very bad: ServiceWorkerRegistration* registration = static_cast(aListener); + MOZ_ASSERT(!domainInfo->mServiceWorkerRegistrations.Contains(registration)); domainInfo->mServiceWorkerRegistrations.AppendElement(registration); return NS_OK; } @@ -1643,6 +1644,7 @@ ServiceWorkerManager::RemoveRegistrationEventListener(nsIURI* aDocumentURI, nsID } ServiceWorkerRegistration* registration = static_cast(aListener); + MOZ_ASSERT(domainInfo->mServiceWorkerRegistrations.Contains(registration)); domainInfo->mServiceWorkerRegistrations.RemoveElement(registration); return NS_OK; } diff --git a/dom/workers/ServiceWorkerRegistration.cpp b/dom/workers/ServiceWorkerRegistration.cpp index 14c017156a9d..98b7feef7632 100644 --- a/dom/workers/ServiceWorkerRegistration.cpp +++ b/dom/workers/ServiceWorkerRegistration.cpp @@ -8,11 +8,14 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/ServiceWorkerRegistrationBinding.h" +#include "mozilla/Services.h" #include "nsCycleCollectionParticipant.h" #include "nsServiceManagerUtils.h" #include "ServiceWorker.h" +#include "nsIObserverService.h" #include "nsIServiceWorkerManager.h" +#include "nsISupportsPrimitives.h" #include "nsPIDOMWindow.h" using namespace mozilla::dom::workers; @@ -21,6 +24,7 @@ namespace mozilla { namespace dom { NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistration) + NS_INTERFACE_MAP_ENTRY(nsIObserver) NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(ServiceWorkerRegistration, DOMEventTargetHelper) @@ -37,11 +41,21 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(nsPIDOMWindow* aWindow, const nsAString& aScope) : mWindow(aWindow) , mScope(aScope) + , mInnerID(0) + , mIsListeningForEvents(false) { MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsInnerWindow()); SetIsDOMBinding(); StartListeningForEvents(); + + mInnerID = aWindow->WindowID(); + + nsCOMPtr obs = services::GetObserverService(); + if (obs) { + obs->AddObserver(this, "inner-window-destroyed", false); + } } ServiceWorkerRegistration::~ServiceWorkerRegistration() @@ -166,17 +180,25 @@ ServiceWorkerRegistration::InvalidateWorkerReference(WhichServiceWorker aWhichOn void ServiceWorkerRegistration::StartListeningForEvents() { + MOZ_ASSERT(!mIsListeningForEvents); + nsCOMPtr swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID); MOZ_ASSERT(mWindow); if (swm) { swm->AddRegistrationEventListener(GetDocumentURI(), this); } + + mIsListeningForEvents = true; } void ServiceWorkerRegistration::StopListeningForEvents() { + if (!mIsListeningForEvents) { + return; + } + nsCOMPtr swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID); // StopListeningForEvents is called in the dtor, and it can happen that @@ -184,6 +206,8 @@ ServiceWorkerRegistration::StopListeningForEvents() if (swm && mWindow) { swm->RemoveRegistrationEventListener(GetDocumentURI(), this); } + + mIsListeningForEvents = false; } nsIURI* @@ -193,5 +217,37 @@ ServiceWorkerRegistration::GetDocumentURI() const return mWindow->GetDocumentURI(); } +NS_IMETHODIMP +ServiceWorkerRegistration::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (strcmp(aTopic, "inner-window-destroyed")) { + return NS_OK; + } + + if (!mIsListeningForEvents) { + return NS_OK; + } + + nsCOMPtr wrapper = do_QueryInterface(aSubject); + NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE); + + uint64_t innerID; + nsresult rv = wrapper->GetData(&innerID); + NS_ENSURE_SUCCESS(rv, rv); + + if (innerID == mInnerID) { + nsCOMPtr obs = services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, "inner-window-destroyed"); + } + + StopListeningForEvents(); + } + + return NS_OK; +} } // dom namespace } // mozilla namespace diff --git a/dom/workers/ServiceWorkerRegistration.h b/dom/workers/ServiceWorkerRegistration.h index 2ebfc26c0d05..906f675e0094 100644 --- a/dom/workers/ServiceWorkerRegistration.h +++ b/dom/workers/ServiceWorkerRegistration.h @@ -22,9 +22,11 @@ class ServiceWorker; } class ServiceWorkerRegistration MOZ_FINAL : public DOMEventTargetHelper + , public nsIObserver { public: NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerRegistration, DOMEventTargetHelper) @@ -91,6 +93,9 @@ private: nsRefPtr mActiveWorker; const nsString mScope; + + uint64_t mInnerID; + bool mIsListeningForEvents; }; } // namespace dom