Bug 1056259 - ServiceWorkerRegistration should unregister itself when the window is destroyed. r=nsm

This commit is contained in:
Andrea Marchesini 2014-08-20 13:30:00 -04:00
parent 3b63cf597b
commit c36595a55e
3 changed files with 63 additions and 0 deletions

View File

@ -1629,6 +1629,7 @@ ServiceWorkerManager::AddRegistrationEventListener(nsIURI* aDocumentURI, nsIDOME
// TODO: this is very very bad:
ServiceWorkerRegistration* registration = static_cast<ServiceWorkerRegistration*>(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<ServiceWorkerRegistration*>(aListener);
MOZ_ASSERT(domainInfo->mServiceWorkerRegistrations.Contains(registration));
domainInfo->mServiceWorkerRegistrations.RemoveElement(registration);
return NS_OK;
}

View File

@ -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<nsIObserverService> 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<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
MOZ_ASSERT(mWindow);
if (swm) {
swm->AddRegistrationEventListener(GetDocumentURI(), this);
}
mIsListeningForEvents = true;
}
void
ServiceWorkerRegistration::StopListeningForEvents()
{
if (!mIsListeningForEvents) {
return;
}
nsCOMPtr<nsIServiceWorkerManager> 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<nsISupportsPRUint64> 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<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "inner-window-destroyed");
}
StopListeningForEvents();
}
return NS_OK;
}
} // dom namespace
} // mozilla namespace

View File

@ -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<workers::ServiceWorker> mActiveWorker;
const nsString mScope;
uint64_t mInnerID;
bool mIsListeningForEvents;
};
} // namespace dom