Bug 1058043 - ServiceWorkerRegistration should not keep a reference to the window, r=nsm

This commit is contained in:
Andrea Marchesini 2014-08-26 09:17:36 +01:00
parent 51c5e60fe1
commit 77c2d8452a
2 changed files with 16 additions and 80 deletions

View File

@ -13,7 +13,6 @@
#include "nsServiceManagerUtils.h"
#include "ServiceWorker.h"
#include "nsIObserverService.h"
#include "nsIServiceWorkerManager.h"
#include "nsISupportsPrimitives.h"
#include "nsPIDOMWindow.h"
@ -24,7 +23,6 @@ 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)
@ -32,35 +30,30 @@ NS_IMPL_RELEASE_INHERITED(ServiceWorkerRegistration, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistration,
DOMEventTargetHelper,
mWindow,
mInstallingWorker,
mWaitingWorker,
mActiveWorker)
ServiceWorkerRegistration::ServiceWorkerRegistration(nsPIDOMWindow* aWindow,
const nsAString& aScope)
: mWindow(aWindow)
: DOMEventTargetHelper(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()
{
}
void
ServiceWorkerRegistration::DisconnectFromOwner()
{
StopListeningForEvents();
DOMEventTargetHelper::DisconnectFromOwner();
}
JSObject*
@ -138,13 +131,13 @@ ServiceWorkerRegistration::GetWorkerReference(WhichServiceWorker aWhichOne)
nsCOMPtr<nsISupports> serviceWorker;
switch(aWhichOne) {
case WhichServiceWorker::INSTALLING_WORKER:
rv = swm->GetInstalling(mWindow, getter_AddRefs(serviceWorker));
rv = swm->GetInstalling(GetOwner(), getter_AddRefs(serviceWorker));
break;
case WhichServiceWorker::WAITING_WORKER:
rv = swm->GetWaiting(mWindow, getter_AddRefs(serviceWorker));
rv = swm->GetWaiting(GetOwner(), getter_AddRefs(serviceWorker));
break;
case WhichServiceWorker::ACTIVE_WORKER:
rv = swm->GetActive(mWindow, getter_AddRefs(serviceWorker));
rv = swm->GetActive(GetOwner(), getter_AddRefs(serviceWorker));
break;
default:
MOZ_CRASH("Invalid enum value");
@ -180,74 +173,27 @@ 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
// SnowWhite had already set to null mWindow.
if (swm && mWindow) {
if (swm) {
swm->RemoveRegistrationEventListener(GetDocumentURI(), this);
}
mIsListeningForEvents = false;
}
nsIURI*
ServiceWorkerRegistration::GetDocumentURI() const
{
MOZ_ASSERT(mWindow);
return mWindow->GetDocumentURI();
MOZ_ASSERT(GetOwner());
return GetOwner()->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,11 +22,9 @@ 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)
@ -35,12 +33,6 @@ public:
ServiceWorkerRegistration(nsPIDOMWindow* aWindow,
const nsAString& aScope);
nsPIDOMWindow*
GetParentObject() const
{
return mWindow;
}
JSObject*
WrapObject(JSContext* aCx);
@ -70,6 +62,9 @@ public:
void
InvalidateWorkerReference(WhichServiceWorker aWhichOnes);
// DOMEventTargethelper
virtual void DisconnectFromOwner() MOZ_OVERRIDE;
private:
~ServiceWorkerRegistration();
@ -82,8 +77,6 @@ private:
void
StopListeningForEvents();
nsCOMPtr<nsPIDOMWindow> mWindow;
// The following properties are cached here to ensure JS equality is satisfied
// instead of acquiring a new worker instance from the ServiceWorkerManager
// for every access. A null value is considered a cache miss.
@ -93,9 +86,6 @@ private:
nsRefPtr<workers::ServiceWorker> mActiveWorker;
const nsString mScope;
uint64_t mInnerID;
bool mIsListeningForEvents;
};
} // namespace dom