Bug 669105 - Leak-until-shutdown with deviceorientation and unload listeners. r=smaug

This commit is contained in:
Doug Turner 2011-07-06 22:56:32 -07:00
parent ec813f7f4b
commit 6d69b6f3da
7 changed files with 106 additions and 16 deletions

View File

@ -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<nsIScriptGlobalObject*>(this));
#endif

View File

@ -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<nsIDOMDocument> domdoc;

View File

@ -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<nsIDeviceMotionListener> mListeners;
nsCOMArray<nsIDOMWindow> mWindowListeners;
nsTPtrArray<nsIDOMWindow> mWindowListeners;
void StartDisconnectTimer();

View File

@ -55,6 +55,7 @@ DIRS += \
geolocation \
globalstorage \
localstorage \
orientation \
sessionstorage \
storageevent \
$(NULL)

View File

@ -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 <dougt@dougt.org>
#
# 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)

View File

@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=507902
-->
<head>
<title>Test for watchPosition </title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507902">Mozilla Bug 507902</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
function boom()
{
window.addEventListener("unload", function(){}, false);
window.addEventListener("devicemotion", function(){}, false);
location = "data:text/html,2";
ok(1, "leak will be at the end of mochitests. so pass.");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", function() { setTimeout(boom, 0); }, false);
</script>
</pre>
</body>
</html>

View File

@ -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);
};