Bug 488862 - crash while geolocation is retrieving data [@ nsGeolocation::RemoveRequest]. r=dbaron, sr=smaug, r=ctalbert on tests, a=beltzner
authorDoug Turner <dougt@meer.net>
Thu, 11 Jun 2009 17:46:46 -0700
changeset 25959 7a5bf953ed9e47337d16572960216c4d59cca023
parent 25958 7272620d19cc3ff93499e1df3eb374d69859f077
child 25960 33bf9fe2f725b9da56d4b0e9351360535781f7aa
child 25963 096e514f6e77f5da2371c98855148208d25fe2bd
push id1695
push userreed@reedloden.com
push dateFri, 12 Jun 2009 08:15:20 +0000
reviewersdbaron, smaug, ctalbert, beltzner
bugs488862
milestone1.9.1pre
Bug 488862 - crash while geolocation is retrieving data [@ nsGeolocation::RemoveRequest]. r=dbaron, sr=smaug, r=ctalbert on tests, a=beltzner
dom/src/geolocation/nsGeolocation.cpp
dom/src/geolocation/nsGeolocation.h
dom/tests/mochitest/geolocation/geolocation.html
dom/tests/mochitest/geolocation/test_manyWindows.html
xpcom/glue/nsCycleCollectionParticipant.h
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -174,17 +174,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGeolocationRequest)
   NS_INTERFACE_MAP_ENTRY(nsIGeolocationRequest)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeolocationRequest)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest)
 
-NS_IMPL_CYCLE_COLLECTION_3(nsGeolocationRequest, mCallback, mErrorCallback, mOptions)
+NS_IMPL_CYCLE_COLLECTION_4(nsGeolocationRequest, mCallback, mErrorCallback, mOptions, mLocator)
 
 
 void
 nsGeolocationRequest::NotifyError(PRInt16 errorCode)
 {
   nsRefPtr<nsDOMGeoPositionError> positionError = new nsDOMGeoPositionError(errorCode);
   if (!positionError)
     return;
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -89,17 +89,17 @@ class nsGeolocationRequest : public nsIG
   PRPackedBool mCleared;
   PRPackedBool mHasSentData;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   nsCOMPtr<nsIDOMGeoPositionCallback> mCallback;
   nsCOMPtr<nsIDOMGeoPositionErrorCallback> mErrorCallback;
   nsCOMPtr<nsIDOMGeoPositionOptions> mOptions;
 
-  nsGeolocation* mLocator; // The locator exists longer than this object.
+  nsRefPtr<nsGeolocation> mLocator;
 };
 
 /**
  * Singleton that manages the geolocation provider
  */
 class nsGeolocationService : public nsIGeolocationUpdate, public nsIObserver
 {
 public:
--- a/dom/tests/mochitest/geolocation/geolocation.html
+++ b/dom/tests/mochitest/geolocation/geolocation.html
@@ -1,12 +1,73 @@
 <html> <head>
 <title>Simple access of geolocation</title>
+<head>
 <script>
 
-document.writeln(navigator.geolocation);
+// This is copied from geolocation-common.js.  We do this so
+// that we do not document write ANYTHING to this page.
+
+function getNotificationBox()
+{
+  const Ci = Components.interfaces;
+  
+  function getChromeWindow(aWindow) {
+      var chromeWin = aWindow 
+          .QueryInterface(Ci.nsIInterfaceRequestor)
+          .getInterface(Ci.nsIWebNavigation)
+          .QueryInterface(Ci.nsIDocShellTreeItem)
+          .rootTreeItem
+          .QueryInterface(Ci.nsIInterfaceRequestor)
+          .getInterface(Ci.nsIDOMWindow)
+          .QueryInterface(Ci.nsIDOMChromeWindow);
+      return chromeWin;
+  }
+
+  var notifyWindow = window.top;
+
+  var chromeWin = getChromeWindow(notifyWindow);
+
+  var notifyBox = chromeWin.getNotificationBox(notifyWindow);
+
+  return notifyBox;
+}
+
+
+function clickNotificationButton(aButtonIndex) {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+  // This is a bit of a hack. The notification doesn't have an API to
+  // trigger buttons, so we dive down into the implementation and twiddle
+  // the buttons directly.
+  var box = getNotificationBox();
+  var bar = box.getNotificationWithValue("geolocation");
+  var button = bar.getElementsByTagName("button").item(aButtonIndex);
+  button.doCommand();
+}
+
+const kAcceptButton = 0;
+const kDenyButton = 1;
+
+gotPosition = function(location){
+  document.location.href="http://www.mozilla.org";
+};
+
+failPosition = function(error){
+  document.location.href="http://www.mozilla.org";
+};
+
+function accept() {
+  clickNotificationButton(kAcceptButton);
+}
+
+navigator.geolocation.getCurrentPosition(gotPosition,
+                                         failPosition,
+                                         {timeout:30000});
+
+setTimeout(accept, 1000);
 
 </script>
 </head>
 <body>
 <p>
 </body>
 </html>
--- a/dom/tests/mochitest/geolocation/test_manyWindows.html
+++ b/dom/tests/mochitest/geolocation/test_manyWindows.html
@@ -18,40 +18,45 @@ href="https://bugzilla.mozilla.org/show_
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug  **/
 
-var numberOfWindows = 2;  // 20 seems to be the default max popups during the mochitest run
+var numberOfWindows = 5;  // 20 seems to be the default max popups during the mochitest run
 var totalWindows = numberOfWindows;
 
 var windows = new Array(numberOfWindows);
 
 for(var i = 0; i < numberOfWindows; i++) {
   windows[i] = window.open("geolocation.html", "_blank", "width=700,height=400");
 }
 
-for(var i = 0; i < numberOfWindows; i++) {
-  windows[i].close();
-  totalWindows --;
+function closeWindows()
+{
+  for(var i = 0; i < numberOfWindows; i++) {
+    windows[i].close();
+    totalWindows --;
+  }
 }
 
 SimpleTest.waitForExplicitFinish();
 
 function checkDone()
 {
     if (totalWindows == 0)
     {
         ok(navigator.geolocation, "Opened a bunch of windows and didn't crash.");
         clearInterval(timer);
         SimpleTest.finish();
     }
 }
 
 var timer = setInterval(checkDone, 1000);
 
+setTimeout(closeWindows, 5000);
+
 </script>
 </pre>
 </body>
 </html>
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -679,9 +679,24 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f3)                                 \
  NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f1)                               \
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f2)                               \
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f3)                               \
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
+#define NS_IMPL_CYCLE_COLLECTION_4(_class, _f1, _f2, _f3, _f4)                 \
+ NS_IMPL_CYCLE_COLLECTION_CLASS(_class)                                        \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f1)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f2)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f3)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_f4)                                 \
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_END                                           \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f1)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f2)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f3)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_f4)                               \
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 #endif // nsCycleCollectionParticipant_h__