Bug 517916, crash if the capturing element has no view, r=roc
authorNeil Deakin <neil@mozilla.com>
Mon, 05 Oct 2009 10:00:05 -0400
changeset 33464 18d78af4be01695b024b4359dd3ef38694626287
parent 33463 fe44a4b6eee06c4540c443adcbbc6304acc7fb99
child 33465 b8aa319fa2dd989699eab60340bd98fcb160c110
push id9524
push userneil@mozilla.com
push dateMon, 05 Oct 2009 14:01:00 +0000
treeherdermozilla-central@b8aa319fa2dd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs517916
milestone1.9.3a1pre
Bug 517916, crash if the capturing element has no view, r=roc
layout/base/nsPresShell.cpp
toolkit/content/tests/widgets/test_mousecapture.xul
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4456,35 +4456,43 @@ PresShell::ClearMouseCapture(nsIView* aV
       // if a view was specified, ensure that the captured content is within
       // this view. Get the frame for the captured content from the right
       // presshell first.
       nsIFrame* frame = nsnull;
       nsIDocument* doc = gCaptureInfo.mContent->GetCurrentDoc();
       if (doc) {
         nsIPresShell *shell = doc->GetPrimaryShell();
         if (shell) {
+          // not much can happen if frames are being destroyed so just return.
+          if (shell->FrameManager()->IsDestroyingFrames())
+            return;
+
           frame = shell->GetPrimaryFrameFor(gCaptureInfo.mContent);
         }
       }
 
       if (frame) {
         nsIView* view = frame->GetClosestView();
-        while (view) {
-          if (view == aView) {
-            NS_RELEASE(gCaptureInfo.mContent);
-            // the view containing the captured content likely disappeared so
-            // disable capture for now.
-            gCaptureInfo.mAllowed = PR_FALSE;
-            break;
-          }
-
-          view = view->GetParent();
+        // if there is no view, capturing won't be handled any more, so
+        // just release the capture.
+        if (view) {
+          do {
+            if (view == aView) {
+              NS_RELEASE(gCaptureInfo.mContent);
+              // the view containing the captured content likely disappeared so
+              // disable capture for now.
+              gCaptureInfo.mAllowed = PR_FALSE;
+              break;
+            }
+
+            view = view->GetParent();
+          } while (view);
+          // return if the view wasn't found
+          return;
         }
-        // return if the view wasn't found
-        return;
       }
     }
 
     NS_RELEASE(gCaptureInfo.mContent);
   }
 
   // disable mouse capture until the next mousedown as a dialog has opened
   // or a drag has started. Otherwise, someone could start capture during
--- a/toolkit/content/tests/widgets/test_mousecapture.xul
+++ b/toolkit/content/tests/widgets/test_mousecapture.xul
@@ -144,16 +144,20 @@ function runTests()
   synthesizeMouseExpectEvent(fixed, 2, 2, { type: "mousemove" },
                              fixed, "mousemove", "setCapture on body retargets to root node", frames[0]);
   synthesizeMouse(body, 8, 8, { type: "mouseup" }, frames[0]);
 
   previousWidth = frames[1].frames[0].document.documentElement.clientWidth;
   originalWidth = previousWidth;
   runCaptureTest(frames[1].document.documentElement.lastChild, framesetCallback);
 
+  // ensure that clicking on an element where the frame disappears doesn't crash
+  synthesizeMouse(frames[2].document.getElementById("input"), 8, 8, { type: "mousedown" }, frames[2]);
+  synthesizeMouse(frames[2].document.getElementById("input"), 8, 8, { type: "mouseup" }, frames[2]);
+
   // check to ensure that selection dragging scrolls the right scrollable area
   otherWindow = window.open("data:text/html,<html><p style='margin-top: 4000px'>This is some text</p></html>", "_blank");
   SimpleTest.waitForFocus(selectionScrollCheck, otherWindow);
 }
 
 function runCaptureTest(element, callback)
 {
   var expectedTarget = null;
@@ -242,15 +246,18 @@ SimpleTest.waitForFocus(runTests);
       onmousedown="document.createElement('hbox').setCapture();"/>
 
 <hbox>
   <iframe width="100" height="100"
           src="data:text/html,%3Cbody style%3D'font-size%3A 40pt%3B'%3E.%3Cb id%3D'b'%3EThis%3C/b%3E is some text%3Cdiv id='fixed' style='position: fixed; left: 55px; top: 5px; width: 10px; height: 10px'%3E.%3C/div%3E%3C/body%3E"/>
 
   <iframe width="100" height="100"
           src="data:text/html,%3Cframeset cols='50%, 50%'%3E%3Cframe src='about:blank'%3E%3Cframe src='about:blank'%3E%3C/frameset%3E"/>
+
+  <iframe width="100" height="100"
+          src="data:text/html,%3Cinput id='input' onfocus='this.style.display = &quot;none&quot;' style='float: left;'"/>
 </hbox>
 
 <body id="body" xmlns="http://www.w3.org/1999/xhtml">
   <p id="display"/><div id="content" style="display: none"/><pre id="test"/>
 </body>
 
 </window>