Bug 974309: Fixes the IsEditable() logic for table cells. r=ehsan
authorJet Villegas <jet@mozilla.com>
Tue, 09 Feb 2016 14:06:03 -0800
changeset 283716 417d17932ff0263723ab786dc82513db8bc27b85
parent 283571 2dfb45d74f42d2a0010696f5fd47c7a7da94cedb
child 283717 71b0b49c6d47bdb2fec86bb750fad2e855fceb9a
push id17536
push usercbook@mozilla.com
push dateWed, 10 Feb 2016 13:30:18 +0000
treeherderfx-team@31150215eedf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs974309
milestone47.0a1
Bug 974309: Fixes the IsEditable() logic for table cells. r=ehsan
editor/libeditor/tests/mochitest.ini
editor/libeditor/tests/test_bug974309.html
layout/generic/moz.build
layout/generic/nsSelection.cpp
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -136,16 +136,17 @@ skip-if = toolkit == 'android'
 [test_bug787432.html]
 [test_bug790475.html]
 [test_bug795785.html]
 [test_bug796839.html]
 [test_bug832025.html]
 [test_bug857487.html]
 [test_bug858918.html]
 [test_bug915962.html]
+[test_bug974309.html]
 skip-if = toolkit == 'android'
 [test_bug966155.html]
 skip-if = os != "win"
 [test_bug966552.html]
 skip-if = os != "win"
 [test_bug998188.html]
 [test_bug1026397.html]
 [test_bug1067255.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug974309.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=974309
+-->
+<head>
+  <title>Test for Bug 974309</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=974309">Mozilla Bug 974309</a>
+<div id="edit_not_table_parent" contenteditable="true"></div>
+<div>
+  <table id="table" border="1" width="100%">
+    <tbody>
+      <tr>
+        <td>a</td>
+        <td>b</td>
+        <td>c</td>
+      </tr>
+      <tr>
+        <td>d</td>
+        <td id="cell">e</td>
+        <td>f</td>
+      </tr>
+      <tr>
+        <td>g</td>
+        <td>h</td>
+        <td>i</td>
+      </tr>
+    </tbody>
+  </table>
+</div>
+<script type="application/javascript">
+
+/**
+ * Test for Bug 974309
+ *
+ * Tests that editing a table row fails when the table or row is _not_ a child of a contenteditable node.
+ * See bug 857487 for tests that cover when the table or row _is_ a child of a contenteditable node.
+ */
+
+function getEditor() {
+  const Ci = SpecialPowers.Ci;
+  var editingSession = SpecialPowers.wrap(window)
+                                    .QueryInterface(Ci.nsIInterfaceRequestor)
+                                    .getInterface(Ci.nsIWebNavigation)
+                                    .QueryInterface(Ci.nsIInterfaceRequestor)
+                                    .getInterface(Ci.nsIEditingSession);
+  return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
+}
+
+var cell = document.getElementById("cell");
+cell.focus();
+
+// place caret at end of center cell
+var sel = getSelection();
+sel.collapse(cell, cell.childNodes.length);
+
+var table = document.getElementById("table");
+
+var tableHTML = table.innerHTML;
+
+var editor = getEditor();
+editor.deleteTableRow(1);
+
+is(table.innerHTML == tableHTML, true, "editor should not modify non-editable table" );
+
+isnot(table.innerHTML == "\n    <tbody>\n      <tr>\n        <td>a</td>\n        <td>b</td>\n        <td>c</td>\n      </tr>\n      \n      <tr>\n        <td>g</td>\n        <td>h</td>\n        <td>i</td>\n      </tr>\n    </tbody>\n  ",
+   true, "editor.deleteTableRow(1) should not delete a non-editable row containing the selection");
+
+</script>
+
+
+</body>
+</html>
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -188,16 +188,17 @@ LOCAL_INCLUDES += [
     '../forms',
     '../style',
     '../svg',
     '../tables',
     '../xul',
     '/dom/base',
     '/dom/html',
     '/dom/xul',
+    '/editor/libeditor'
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
 RESOURCE_FILES.html = [
     'folder.png',
 ]
 
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -72,16 +72,17 @@ static NS_DEFINE_CID(kFrameTraversalCID,
 #include "nsIBidiKeyboard.h"
 
 #include "nsError.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/SelectionBinding.h"
 #include "mozilla/AsyncEventDispatcher.h"
+#include "nsHTMLEditor.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //#define DEBUG_TABLE 1
 
 static bool IsValidSelectionPoint(nsFrameSelection *aFrameSel, nsINode *aNode);
 
@@ -1692,21 +1693,27 @@ nsFrameSelection::TakeFocus(nsIContent* 
     }
 
     //find out if we are inside a table. if so, find out which one and which cell
     //once we do that, the next time we get a takefocus, check the parent tree. 
     //if we are no longer inside same table ,cell then switch to table selection mode.
     // BUT only do this in an editor
 
     NS_ENSURE_STATE(mShell);
-    int16_t displaySelection = mShell->GetSelectionFlags();
-
-    // Editor has DISPLAY_ALL selection type
-    if (displaySelection == nsISelectionDisplay::DISPLAY_ALL)
-    {
+    bool editable = false;
+    RefPtr<nsPresContext> context = mShell->GetPresContext();
+    if (context) {
+      nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(nsContentUtils::GetHTMLEditor(context));
+      if (editor) {
+        nsCOMPtr<nsINode> editorHostNode = editor->GetActiveEditingHost();
+        editable = editorHostNode && nsContentUtils::ContentIsDescendantOf(aNewFocus, editorHostNode);
+      }
+    }
+
+    if (editable) {
       mCellParent = GetCellParent(aNewFocus);
 #ifdef DEBUG_TABLE_SELECTION
       if (mCellParent)
         printf(" * TakeFocus - Collapsing into new cell\n");
 #endif
     }
   }
   else {