Bug 759989 - Add test to ensure device sensors are shutdown when listeners are removed. r=smaug
authorDoug Turner <dougt@dougt.org>
Thu, 07 Jun 2012 10:58:33 -0700
changeset 96092 a9024396eeb7012bc024992791de734adfa13414
parent 96091 e11cfc5084eaf6f55386afdb1d668f874c595d0c
child 96093 a9455a51d5436b6c4e98b82a87c1c58643360b8a
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerssmaug
bugs759989
milestone16.0a1
Bug 759989 - Add test to ensure device sensors are shutdown when listeners are removed. r=smaug
content/events/test/Makefile.in
content/events/test/test_bug742376.html
dom/base/nsGlobalWindow.cpp
dom/system/nsDeviceSensors.cpp
xpcom/system/nsIDeviceSensors.idl
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -80,16 +80,17 @@ include $(topsrcdir)/config/rules.mk
 		empty.js \
 		test_bug689564.html \
 		test_bug698929.html \
 		test_eventctors.html \
 		test_bug635465.html \
 		test_bug741666.html \
 		test_dom_keyboard_event.html \
 		test_dom_mouse_event.html \
+		test_bug742376.html \
 		$(NULL)
 
 #bug 585630
 ifneq (mobile,$(MOZ_BUILD_APP))
 _TEST_FILES += \
 		test_dragstart.html \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug742376.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=402089
+-->
+<head>
+  <title>Test for Bug 742376</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=742376">Mozilla Bug 742376</a>
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 742376 **/
+
+function getListenerCount() {
+
+  var Cc = SpecialPowers.wrap(Components).classes;
+  var Ci = SpecialPowers.wrap(Components).interfaces;
+  var dss = Cc["@mozilla.org/devicesensors;1"].getService(Ci.nsIDeviceSensors);
+
+  return dss.listenerCount(Ci.nsIDeviceSensorData.TYPE_ORIENTATION);
+}
+
+var startListenerCount = getListenerCount();
+
+function dumbListener(event) {}
+function dumbListener2(event) {}
+
+window.addEventListener("deviceorientation", dumbListener, false);
+window.addEventListener("deviceorientation", dumbListener2, false);
+
+window.setTimeout(function() {
+
+  window.removeEventListener("deviceorientation", dumbListener, false);
+  window.setTimeout(function() {
+
+    window.removeEventListener("deviceorientation", dumbListener2, false);
+    window.setTimeout(function() {
+      is (getListenerCount(), startListenerCount, "Must have the same listeners at this point");
+      SimpleTest.finish();
+    }, 0);
+  }, 0);
+}, 0);
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10071,45 +10071,54 @@ nsGlobalWindow::EnableDeviceSensor(PRUin
   bool alreadyEnabled = false;
   for (PRUint32 i = 0; i < mEnabledSensors.Length(); i++) {
     if (mEnabledSensors[i] == aType) {
       alreadyEnabled = true;
       break;
     }
   }
 
-  if (alreadyEnabled)
+  mEnabledSensors.AppendElement(aType);
+
+  if (alreadyEnabled) {
     return;
-
-  mEnabledSensors.AppendElement(aType);
+  }
 
   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
-  if (ac)
+  if (ac) {
     ac->AddWindowListener(aType, this);
+  }
 }
 
 void
 nsGlobalWindow::DisableDeviceSensor(PRUint32 aType)
 {
   PRInt32 doomedElement = -1;
+  PRInt32 listenerCount = 0;
   for (PRUint32 i = 0; i < mEnabledSensors.Length(); i++) {
     if (mEnabledSensors[i] == aType) {
       doomedElement = i;
-      break;
-    }
-  }
-
-  if (doomedElement == -1)
+      listenerCount++;
+    }
+  }
+
+  if (doomedElement == -1) {
     return;
+  }
 
   mEnabledSensors.RemoveElementAt(doomedElement);
 
+  if (listenerCount > 1) {
+    return;
+  }
+
   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
-  if (ac)
+  if (ac) {
     ac->RemoveWindowListener(aType, this);
+  }
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL)
 {
   FORWARD_TO_INNER(GetURL, (aURL), NS_ERROR_UNEXPECTED);
 
   if (!mURLProperty) {
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -113,16 +113,27 @@ nsDeviceSensors::~nsDeviceSensors()
       UnregisterSensorObserver((SensorType)i, this);
   }
 
   for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
     delete mWindowListeners[i];
   }
 }
 
+NS_IMETHODIMP nsDeviceSensors::ListenerCount(PRUint32 aType, PRInt32 *aRetVal)
+{
+  if (!mEnabled) {
+    *aRetVal = 0;
+    return NS_OK;
+  }
+
+  *aRetVal = mWindowListeners[aType]->Length();
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsDeviceSensors::AddWindowListener(PRUint32 aType, nsIDOMWindow *aWindow)
 {
   if (!mEnabled)
     return NS_OK;
 
   if (mWindowListeners[aType]->IndexOf(aWindow) != NoIndex)
     return NS_OK;
 
--- a/xpcom/system/nsIDeviceSensors.idl
+++ b/xpcom/system/nsIDeviceSensors.idl
@@ -19,17 +19,20 @@ interface nsIDeviceSensorData : nsISuppo
 
   readonly attribute unsigned long type;
 
   readonly attribute double x;
   readonly attribute double y;
   readonly attribute double z;
 };
 
-[scriptable, uuid(b672bfe0-4479-4094-a9ef-1b6847720d07)]
+[scriptable, uuid(83306c9f-1c8f-43c4-900a-245d7f219511)]
 interface nsIDeviceSensors : nsISupports
 {
+  long listenerCount(in unsigned long aType);
+
   // Holds pointers, not AddRef objects -- it is up to the caller
   // to call RemoveWindowListener before the window is deleted.
+
   [noscript] void addWindowListener(in unsigned long aType, in nsIDOMWindow aWindow);
   [noscript] void removeWindowListener(in unsigned long aType, in nsIDOMWindow aWindow);
   [noscript] void removeWindowAsListener(in nsIDOMWindow aWindow);
 };