Bug 989012 - Part 2: Don't get stuck when seeing an image without a src or alt attribute; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 15 Jan 2015 11:59:13 -0500
changeset 239559 739b6b7ed6bcab0626e0f0c42ed1d14cb0000cf6
parent 239558 39c448409484df1357a6417f38c9a6965d60b51c
child 239560 edbdf7aa292c8380667a602a20d58f77492fd75f
push id500
push userjoshua.m.grant@gmail.com
push dateThu, 29 Jan 2015 01:48:36 +0000
reviewersroc
bugs989012
milestone38.0a1
Bug 989012 - Part 2: Don't get stuck when seeing an image without a src or alt attribute; r=roc We do not want to traverse inside native anonymous elements, but we should still be able to skip over generated content, to avoid getting stuck on such images.
layout/base/tests/bug989012-3-ref.html
layout/base/tests/bug989012-3.html
layout/base/tests/mochitest.ini
layout/base/tests/test_reftests_with_caret.html
layout/generic/nsFrame.cpp
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/bug989012-3-ref.html
@@ -0,0 +1,28 @@
+<html class="reftest-wait">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <style>
+      img {
+        border: solid 1px red;
+        mid-width: 1em;
+        display: inline-block;
+      }
+    </style>
+  </head>
+  <body onload="start()">
+    <div onfocus="done()" contenteditable>foo<img>bar</div>
+    <script>
+      var div = document.querySelector("div");
+      function start() {
+        div.focus();
+      }
+      function done() {
+        var sel = getSelection();
+        // Set the caret right before "bar"
+        sel.collapse(div.lastChild, 0);
+        document.documentElement.removeAttribute("class");
+      }
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/bug989012-3.html
@@ -0,0 +1,31 @@
+<html class="reftest-wait">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <style>
+      img {
+        border: solid 1px red;
+        mid-width: 1em;
+        display: inline-block;
+      }
+    </style>
+  </head>
+  <body onload="start()">
+    <div onfocus="done()" contenteditable>foo<img>bar</div>
+    <script>
+      var div = document.querySelector("div");
+      function start() {
+        div.focus();
+      }
+      function done() {
+        var sel = getSelection();
+        sel.collapse(div, 0);
+        // Press Right four times to set the caret right before "bar"
+        for (var i = 0; i < 4; ++i) {
+          synthesizeKey("VK_RIGHT", {});
+        }
+        document.documentElement.removeAttribute("class");
+      }
+    </script>
+  </body>
+</html>
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -52,16 +52,18 @@ support-files =
   bug570378-persian-4-ref.html
   bug570378-persian-5.html
   bug570378-persian-5-ref.html
   bug644768.html
   bug989012-1.html
   bug989012-1-ref.html
   bug989012-2.html
   bug989012-2-ref.html
+  bug989012-3.html
+  bug989012-3-ref.html
   bug1061468.html
   bug1061468-ref.html
   bug1109968-1-ref.html
   bug1109968-1.html
   bug1109968-2-ref.html
   bug1109968-2.html
 
 [test_preserve3d_sorting_hit_testing.html]
--- a/layout/base/tests/test_reftests_with_caret.html
+++ b/layout/base/tests/test_reftests_with_caret.html
@@ -104,16 +104,17 @@ function endTest() {
 
 var tests = [
     [ 'bug106855-1.html' , 'bug106855-1-ref.html' ] ,
     [ 'bug106855-2.html' , 'bug106855-1-ref.html' ] ,
     [ 'bug389321-2.html' , 'bug389321-2-ref.html' ] ,
     [ 'bug613807-1.html' , 'bug613807-1-ref.html' ] ,
     [ 'bug989012-1.html' , 'bug989012-1-ref.html' ] ,
     [ 'bug989012-2.html' , 'bug989012-2-ref.html' ] ,
+    [ 'bug989012-3.html' , 'bug989012-3-ref.html' ] ,
     [ 'bug1082486-1.html', 'bug1082486-1-ref.html'] ,
     [ 'bug1082486-2.html', 'bug1082486-2-ref.html'] ,
     // The following test cases are all involving with one sending
     // synthesizeKey(), the other without. They ought to be failed
     // when touch caret preference on. Test them with preference off.
     function() {SpecialPowers.setBoolPref("touchcaret.enabled", false);} ,
     [ 'bug240933-1.html' , 'bug240933-1-ref.html' ] ,
     [ 'bug240933-2.html' , 'bug240933-1-ref.html' ] ,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -7041,20 +7041,22 @@ nsIFrame::GetFrameFromDirection(nsDirect
 
     if (aDirection == eDirNext)
       frameTraversal->Next();
     else
       frameTraversal->Prev();
 
     traversedFrame = frameTraversal->CurrentItem();
 
-    // Skip anonymous elements
+    // Skip anonymous elements, but watch out for generated content
     if (!traversedFrame ||
-        traversedFrame->GetContent()->IsRootOfNativeAnonymousSubtree())
+        (!traversedFrame->IsGeneratedContentFrame() &&
+         traversedFrame->GetContent()->IsRootOfNativeAnonymousSubtree())) {
       return NS_ERROR_FAILURE;
+    }
 
     traversedFrame->IsSelectable(&selectable, nullptr);
     if (!selectable) {
       *aOutMovedOverNonSelectableText = true;
     }
   } // while (!selectable)
 
   *aOutOffset = (aDirection == eDirNext) ? 0 : -1;