From 6d69b6f3dae742258a2d7caacbf41ecf5b2e7ab5 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Wed, 6 Jul 2011 22:56:32 -0700 Subject: [PATCH] Bug 669105 - Leak-until-shutdown with deviceorientation and unload listeners. r=smaug --- dom/base/nsGlobalWindow.cpp | 2 + dom/system/nsDeviceMotion.cpp | 16 ++---- dom/system/nsDeviceMotion.h | 3 +- dom/tests/mochitest/Makefile.in | 1 + dom/tests/mochitest/orientation/Makefile.in | 53 +++++++++++++++++++ .../mochitest/orientation/test_bug507902.html | 39 ++++++++++++++ xpcom/system/nsIDeviceMotion.idl | 8 +-- 7 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 dom/tests/mochitest/orientation/Makefile.in create mode 100644 dom/tests/mochitest/orientation/test_bug507902.html diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 347afe26b284..b29bd0bf1a09 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1026,6 +1026,8 @@ nsGlobalWindow::~nsGlobalWindow() CleanUp(PR_TRUE); + NS_ASSERTION(!mHasDeviceMotion, "Window still registered with device motion."); + #ifdef DEBUG nsCycleCollector_DEBUG_wasFreed(static_cast(this)); #endif diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 19246fc3f77b..414cfa9cd747 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -163,7 +163,7 @@ nsDeviceMotion::TimeoutHandler(nsITimer *aTimer, void *aClosure) } // what about listeners that don't clean up properly? they will leak - if (self->mListeners.Count() == 0 && self->mWindowListeners.Count() == 0) { + if (self->mListeners.Count() == 0 && self->mWindowListeners.Length() == 0) { self->Shutdown(); self->mStarted = PR_FALSE; } @@ -195,26 +195,18 @@ NS_IMETHODIMP nsDeviceMotion::RemoveListener(nsIDeviceMotionListener *aListener) NS_IMETHODIMP nsDeviceMotion::AddWindowListener(nsIDOMWindow *aWindow) { - if (mWindowListeners.IndexOf(aWindow) >= 0) - return NS_OK; // already exists - if (mStarted == PR_FALSE) { mStarted = PR_TRUE; Startup(); } - - mWindowListeners.AppendObject(aWindow); + mWindowListeners.AppendElement(aWindow); return NS_OK; } NS_IMETHODIMP nsDeviceMotion::RemoveWindowListener(nsIDOMWindow *aWindow) { - if (mWindowListeners.IndexOf(aWindow) < 0) - return NS_OK; // doesn't exist - - mWindowListeners.RemoveObject(aWindow); + mWindowListeners.RemoveElement(aWindow); StartDisconnectTimer(); - return NS_OK; } @@ -230,7 +222,7 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) mListeners[i]->OnMotionChange(a); } - for (PRUint32 i = mWindowListeners.Count(); i > 0 ; ) { + for (PRUint32 i = mWindowListeners.Length(); i > 0 ; ) { --i; nsCOMPtr domdoc; diff --git a/dom/system/nsDeviceMotion.h b/dom/system/nsDeviceMotion.h index 6ff77ede89b7..3d4ac3ad5b22 100644 --- a/dom/system/nsDeviceMotion.h +++ b/dom/system/nsDeviceMotion.h @@ -40,6 +40,7 @@ #include "nsIDeviceMotion.h" #include "nsIDOMDeviceMotionEvent.h" #include "nsCOMArray.h" +#include "nsTPtrArray.h" #include "nsCOMPtr.h" #include "nsITimer.h" @@ -64,7 +65,7 @@ public: private: nsCOMArray mListeners; - nsCOMArray mWindowListeners; + nsTPtrArray mWindowListeners; void StartDisconnectTimer(); diff --git a/dom/tests/mochitest/Makefile.in b/dom/tests/mochitest/Makefile.in index 64a343eb641a..5dcf7c3f84ee 100644 --- a/dom/tests/mochitest/Makefile.in +++ b/dom/tests/mochitest/Makefile.in @@ -55,6 +55,7 @@ DIRS += \ geolocation \ globalstorage \ localstorage \ + orientation \ sessionstorage \ storageevent \ $(NULL) diff --git a/dom/tests/mochitest/orientation/Makefile.in b/dom/tests/mochitest/orientation/Makefile.in new file mode 100644 index 000000000000..26f070525b4f --- /dev/null +++ b/dom/tests/mochitest/orientation/Makefile.in @@ -0,0 +1,53 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org build system. +# +# The Initial Developer of the Original Code is Mozilla Foundation +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Doug Turner +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = dom/tests/mochitest/orientation + +include $(DEPTH)/config/autoconf.mk + +include $(topsrcdir)/config/rules.mk + +_TEST_FILES = \ + test_bug507902.html \ + $(NULL) + +libs:: $(_TEST_FILES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) + diff --git a/dom/tests/mochitest/orientation/test_bug507902.html b/dom/tests/mochitest/orientation/test_bug507902.html new file mode 100644 index 000000000000..088e936af392 --- /dev/null +++ b/dom/tests/mochitest/orientation/test_bug507902.html @@ -0,0 +1,39 @@ + + + + + Test for watchPosition + + + + + +Mozilla Bug 507902 +

+ +
+
+
+ + + diff --git a/xpcom/system/nsIDeviceMotion.idl b/xpcom/system/nsIDeviceMotion.idl index e20bfbaf7699..f24144f6a3e6 100644 --- a/xpcom/system/nsIDeviceMotion.idl +++ b/xpcom/system/nsIDeviceMotion.idl @@ -57,14 +57,16 @@ interface nsIDeviceMotionListener : nsISupports void onMotionChange(in nsIDeviceMotionData aMotionData); }; -[scriptable, uuid(4B04E228-0B33-43FC-971F-AF60CEDB1C21)] +[scriptable, uuid(B6E5C463-AAA6-44E2-BD07-7A7DC6192E68)] interface nsIDeviceMotion : nsISupports { void addListener(in nsIDeviceMotionListener aListener); void removeListener(in nsIDeviceMotionListener aListener); - void addWindowListener(in nsIDOMWindow aWindow); - void removeWindowListener(in nsIDOMWindow aWindow); + // Holds pointers, not AddRef objects -- it is up to the caller + // to call RemoveWindowListener before the window is deleted. + [noscript] void addWindowListener(in nsIDOMWindow aWindow); + [noscript] void removeWindowListener(in nsIDOMWindow aWindow); };