Bug 1318312 part.3 Selection should move focus at every selection change when it's called by JS r?smaug draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 14 Mar 2017 10:36:21 +0900
changeset 498031 1cac55df84971a6b33301d577b3e3067e7836805
parent 498030 9aa2777f807bda8a8d85f723123d9014d7a787c0
child 549058 cad429c72d3963cab4e6c9cdc612916d550698bb
push id49084
push usermasayuki@d-toybox.com
push dateTue, 14 Mar 2017 05:28:54 +0000
reviewerssmaug
bugs1318312
milestone55.0a1
Bug 1318312 part.3 Selection should move focus at every selection change when it's called by JS r?smaug Selection may be changed by methods of Selection or methods of Range retrieved by Selection.getRangeAt(). Selection::NotifySelectionListeners() is called after every selection change of each of them, so, this method must be a good point to move focus. If new common ancestor of all ranges is editable and in an editing host, we should move focus to it. Otherwise, if an editing host has focus but new common ancestor is not editable, we should move focus from the editing host. For consistency with the other browsers, this patch doesn't move focus to other focusable element. MozReview-Commit-ID: 6sNsuzwqECX
dom/base/nsRange.cpp
editor/libeditor/tests/mochitest.ini
editor/libeditor/tests/test_bug1318312.html
editor/libeditor/tests/test_bug676401.html
editor/libeditor/tests/test_contenteditable_focus.html
layout/generic/Selection.h
layout/generic/nsSelection.cpp
testing/web-platform/mozilla/meta/focus/Range_collapse.html.ini
testing/web-platform/mozilla/meta/focus/Range_selectNode.html.ini
testing/web-platform/mozilla/meta/focus/Range_setEnd.html.ini
testing/web-platform/mozilla/meta/focus/Range_setStart.html.ini
testing/web-platform/mozilla/meta/focus/Selection_addRange.html.ini
testing/web-platform/mozilla/meta/focus/Selection_addRange_into_iframe.html.ini
testing/web-platform/mozilla/meta/focus/Selection_collapse.html.ini
testing/web-platform/mozilla/meta/focus/Selection_collapseToEnd.html.ini
testing/web-platform/mozilla/meta/focus/Selection_collapseToStart.html.ini
testing/web-platform/mozilla/meta/focus/Selection_selectAllChildren.html.ini
testing/web-platform/mozilla/meta/focus/Selection_setBaseAndExtent.html.ini
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -963,17 +963,20 @@ nsRange::DoSetRange(nsINode* aStartN, in
 
   // This needs to be the last thing this function does, other than notifying
   // selection listeners. See comment in ParentChainChanged.
   mRoot = aRoot;
 
   // Notify any selection listeners. This has to occur last because otherwise the world
   // could be observed by a selection listener while the range was in an invalid state.
   if (mSelection) {
-    mSelection->NotifySelectionListeners(mCalledByJS);
+    // Be aware, this range may be modified or stop being a range for selection
+    // after this call.  Additionally, the selection instance may have gone.
+    RefPtr<Selection> selection = mSelection;
+    selection->NotifySelectionListeners(mCalledByJS);
   }
 }
 
 static int32_t
 IndexOf(nsINode* aChild)
 {
   nsINode* parent = aChild->GetParentNode();
 
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -221,16 +221,17 @@ skip-if = toolkit == 'android'
 [test_bug1306532.html]
 subsuite = clipboard
 skip-if = toolkit == 'android'
 [test_bug1310912.html]
 skip-if = toolkit == 'android' # bug 1315898
 [test_bug1314790.html]
 [test_bug1315065.html]
 [test_bug1316302.html]
+[test_bug1318312.html]
 [test_bug1328023.html]
 [test_bug1330796.html]
 [test_bug1332876.html]
 
 [test_CF_HTML_clipboard.html]
 subsuite = clipboard
 [test_composition_event_created_in_chrome.html]
 [test_contenteditable_focus.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug1318312.html
@@ -0,0 +1,108 @@
+<!DOCTYPE>
+<html>
+<head>
+<title>Test for bug1318312</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" />
+<style type="text/css">
+</style>
+</head>
+<body>
+<div id="outerEditor" contenteditable><p>content of outer editor</p>
+<div id="staticInEditor" contenteditable="false"><p>static content of outer editor</p>
+<div id="innerEditor" contenteditable><p>content of inner editor</p></div></div></div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var outerEditor = document.getElementById("outerEditor");
+
+function runTests()
+{
+  outerEditor.focus();
+  is(document.activeElement, outerEditor,
+     "outerEditor should have focus");
+
+  // Move cursor into the innerEditor with ArrowDown key.  Then, focus shouldn't
+  // be moved to innerEditor from outerEditor.
+  // Note that Chrome moves focus in this case.  However, we should do that
+  // at least for now because user can move focus with ArrowUp key even from
+  // innerEditor to outerEditor but we don't allow such navigation.
+  // FYI: Edge behaves same as us.
+  synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by moving caret");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the innerEditor");
+  is(document.getSelection().focusOffset, 0,
+     "focus offset of selection should be 0");
+
+  synthesizeKey("a", { code: "KeyA" });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by typing a character");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the innerEditor");
+  is(document.getSelection().focusOffset, 1,
+     "focus offset of selection should be 1");
+
+  synthesizeKey("KEY_Enter", { code: "Enter" });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by typing Enter");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").childNodes.item(1).firstChild,
+     "focus node of selection should be the text node in the second paragraph in the innerEditor");
+  is(document.getSelection().focusOffset, 0,
+     "focus offset of selection should be 0");
+
+  synthesizeKey("KEY_Backspace", { code: "Backspace" });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by typing Backspace (removing the line breaker)");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the innerEditor");
+  is(document.getSelection().focusOffset, 1,
+     "focus offset of selection should be 1");
+
+  synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by typing Shift+ArrowLeft (selecting 'a')");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the innerEditor");
+  is(document.getSelection().focusOffset, 0,
+     "focus offset of selection should be 0");
+  is(document.getSelection().anchorNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "anchor node of selection should be the text node in the innerEditor");
+  is(document.getSelection().anchorOffset, 1,
+     "anchor offset of selection should be 1");
+
+  synthesizeKey("KEY_Delete", { code: "Delete" });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by typing Delete (removing the 'a')");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the innerEditor");
+  is(document.getSelection().focusOffset, 0,
+     "focus offset of selection should be 0");
+
+  synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" });
+  is(document.activeElement, outerEditor,
+     "outerEditor should still have focus because focus shouldn't be moved by moving caret from innerEditor to outerEditor");
+  is(document.getSelection().focusNode, document.getElementById("outerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the outerEditor");
+  is(document.getSelection().focusOffset, 0,
+     "focus offset of selection should be 0");
+
+  // However, clicking in innerEditor should move focus.
+  synthesizeMouseAtCenter(innerEditor, {});
+  is(document.activeElement, innerEditor,
+     "innerEditor should get focus because focus should be moved to innerEditor even from outerEditor by click");
+  is(document.getSelection().focusNode, document.getElementById("innerEditor").firstChild.firstChild,
+     "focus node of selection should be the text node in the innerEditor");
+
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/libeditor/tests/test_bug676401.html
+++ b/editor/libeditor/tests/test_bug676401.html
@@ -38,19 +38,26 @@ var alwaysEnabledCommands = [
   "cut",
   "enableInlineTableEditing",
   "enableObjectResizing",
   "insertBrOnReturn",
   "selectAll",
   "styleWithCSS",
 ];
 
+function ensureNobodyHasFocus()
+{
+  document.activeElement.blur();
+}
+
 function IsCommandEnabled(command) {
   var enabled;
 
+  ensureNobodyHasFocus();
+
   // non-editable div: should return false unless alwaysEnabled
   window.getSelection().selectAllChildren(gBlock1);
   enabled = document.queryCommandEnabled(command);
   is(enabled, alwaysEnabledCommands.indexOf(command) != -1,
      "'" + command + "' should not be enabled on a non-editable block.");
 
   // editable div: should return true
   window.getSelection().selectAllChildren(gBlock2);
@@ -85,16 +92,18 @@ function runTests() {
     IsCommandEnabled(commands[i]);
 
   // Mozilla-specific stuff
   commands = ["enableInlineTableEditing", "enableObjectResizing", "insertBrOnReturn"];
   for (i = 0; i < commands.length; i++)
     IsCommandEnabled(commands[i]);
 
   // These are privileged, and available only to chrome.
+  ensureNobodyHasFocus();
+  window.getSelection().selectAllChildren(gBlock2);
   commands = ["paste"];
   for (i = 0; i < commands.length; i++) {
     is(document.queryCommandEnabled(commands[i]), false,
        "Command should not be enabled for non-privileged code");
     is(SpecialPowers.wrap(document).queryCommandEnabled(commands[i]), true,
        "Command should be enabled for privileged code");
     is(document.execCommand(commands[i], false, false), false, "Should return false: " + commands[i]);
     is(SpecialPowers.wrap(document).execCommand(commands[i], false, false), true, "Should return true: " + commands[i]);
--- a/editor/libeditor/tests/test_contenteditable_focus.html
+++ b/editor/libeditor/tests/test_contenteditable_focus.html
@@ -129,24 +129,24 @@ function runTestsInternal()
   is(startNode, editor,
      "the caret should stay on the other editor");
   ok(selCon.caretVisible,
      "caret isn't visible in the inputTextInEditor");
   // Move focus to the other editor again
   otherEditor.focus();
   is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
      "the other editor didn't get focus #2");
-  // Set selection to the span element in the editor (unfocused)
+  // Set selection to the span element in the editor.
   range = document.createRange();
   range.setStart(spanInEditor.firstChild, 5);
   selection.removeAllRanges();
   selection.addRange(range);
   is(selection.rangeCount, 1, "selection range is lost from the document");
-  is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
-     "the other editor shouldn't lose focus by selection range change");
+  is(SpecialPowers.unwrap(fm.focusedElement), editor,
+     "the other editor should lose focus by selection range change");
   ok(selCon.caretVisible, "caret isn't visible in inputTextInEditor");
   // Move focus to the editor
   editor.focus();
   is(SpecialPowers.unwrap(fm.focusedElement), editor,
      "the editor didn't get focus #2");
   is(selection.rangeCount, 1, "selection range is lost from the document");
   range = selection.getRangeAt(0);
   ok(range.collapsed, "the selection range isn't collapsed");
--- a/layout/generic/Selection.h
+++ b/layout/generic/Selection.h
@@ -18,18 +18,22 @@
 #include "nsISelectionPrivate.h"
 #include "nsRange.h"
 #include "nsThreadUtils.h"
 #include "nsWrapperCache.h"
 
 struct CachedOffsetForFrame;
 class nsAutoScrollTimer;
 class nsIContentIterator;
+class nsIDocument;
+class nsIEditor;
 class nsIFrame;
+class nsIHTMLEditor;
 class nsFrameSelection;
+class nsPIDOMWindowOuter;
 struct SelectionDetails;
 class nsCopySupport;
 class nsHTMLCopyEncoder;
 
 namespace mozilla {
 class ErrorResult;
 struct AutoPrepareFocusRange;
 } // namespace mozilla
@@ -349,16 +353,53 @@ private:
 
   void UserSelectRangesToAdd(nsRange* aItem, nsTArray<RefPtr<nsRange> >& rangesToAdd);
 
   /**
    * Helper method for AddItem.
    */
   nsresult AddItemInternal(nsRange* aRange, int32_t* aOutIndex);
 
+  nsIDocument* GetDocument() const;
+  nsPIDOMWindowOuter* GetWindow() const;
+  nsIEditor* GetEditor() const;
+
+  /**
+   * GetCommonEditingHostForAllRanges() returns common editing host of all
+   * ranges if there is. If at least one of the ranges is in non-editable
+   * element, returns nullptr.  See following examples for the detail:
+   *
+   *  <div id="a" contenteditable>
+   *    an[cestor
+   *    <div id="b" contenteditable="false">
+   *      non-editable
+   *      <div id="c" contenteditable>
+   *        desc]endant
+   *  in this case, this returns div#a because div#c is also in div#a.
+   *
+   *  <div id="a" contenteditable>
+   *    an[ce]stor
+   *    <div id="b" contenteditable="false">
+   *      non-editable
+   *      <div id="c" contenteditable>
+   *        de[sc]endant
+   *  in this case, this returns div#a because second range is also in div#a
+   *  and common ancestor of the range (i.e., div#c) is editable.
+   *
+   *  <div id="a" contenteditable>
+   *    an[ce]stor
+   *    <div id="b" contenteditable="false">
+   *      [non]-editable
+   *      <div id="c" contenteditable>
+   *        de[sc]endant
+   *  in this case, this returns nullptr because the second range is in
+   *  non-editable area.
+   */
+  Element* GetCommonEditingHostForAllRanges();
+
   // These are the ranges inside this selection. They are kept sorted in order
   // of DOM start position.
   //
   // This data structure is sorted by the range beginnings. As the ranges are
   // disjoint, it is also implicitly sorted by the range endings. This allows
   // us to perform binary searches when searching for existence of a range,
   // giving us O(log n) search time.
   //
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -82,16 +82,17 @@ static NS_DEFINE_CID(kFrameTraversalCID,
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/layers/ScrollInputMethods.h"
 #include "nsViewManager.h"
 
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
 #include "nsFocusManager.h"
+#include "nsPIDOMWindow.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::layers::ScrollInputMethod;
 
 //#define DEBUG_TABLE 1
 
 static bool IsValidSelectionPoint(nsFrameSelection *aFrameSel, nsINode *aNode);
@@ -1874,16 +1875,18 @@ printf(" * TakeFocus - moving into new c
           mDomSelections[index]->Extend(aNewFocus, aContentOffset);
       }
     }
   }
 
   // Don't notify selection listeners if batching is on:
   if (GetBatching())
     return NS_OK;
+
+  // Be aware, the Selection instance may be destroyed after this call.
   return NotifySelectionListeners(SelectionType::eNormal);
 }
 
 
 UniquePtr<SelectionDetails>
 nsFrameSelection::LookUpSelection(nsIContent *aContent,
                                   int32_t aContentOffset,
                                   int32_t aContentLength,
@@ -1914,16 +1917,17 @@ nsFrameSelection::SetDragState(bool aSta
 
   mDragState = aState;
     
   if (!mDragState)
   {
     mDragSelectingCells = false;
     // Notify that reason is mouse up.
     PostReason(nsISelectionListener::MOUSEUP_REASON);
+    // Be aware, the Selection instance may be destroyed after this call.
     NotifySelectionListeners(SelectionType::eNormal);
   }
 }
 
 Selection*
 nsFrameSelection::GetSelection(SelectionType aSelectionType) const
 {
   int8_t index = GetIndexFromSelectionType(aSelectionType);
@@ -2411,28 +2415,30 @@ nsFrameSelection::EndBatchChanges(int16_
 {
   mBatching--;
   NS_ASSERTION(mBatching >=0,"Bad mBatching");
 
   if (mBatching == 0 && mChangesDuringBatching) {
     int16_t postReason = PopReason() | aReason;
     PostReason(postReason);
     mChangesDuringBatching = false;
+    // Be aware, the Selection instance may be destroyed after this call.
     NotifySelectionListeners(SelectionType::eNormal);
   }
 }
 
 
 nsresult
 nsFrameSelection::NotifySelectionListeners(SelectionType aSelectionType)
 {
   int8_t index = GetIndexFromSelectionType(aSelectionType);
   if (index >=0 && mDomSelections[index])
   {
-    return mDomSelections[index]->NotifySelectionListeners();
+    RefPtr<Selection> selection = mDomSelections[index];
+    return selection->NotifySelectionListeners();
   }
   return NS_ERROR_FAILURE;
 }
 
 // Start of Table Selection methods
 
 static bool IsCell(nsIContent *aContent)
 {
@@ -4936,17 +4942,20 @@ Selection::RemoveAllRanges(ErrorResult& 
   if (NS_FAILED(result)) {
     aRv.Throw(result);
     return;
   }
 
   // Turn off signal for table selection
   mFrameSelection->ClearTableCellSelection();
 
+  // Be aware, this instance may be destroyed after this call.
+  // XXX Why doesn't this call Selection::NotifySelectionListener() directly?
   result = mFrameSelection->NotifySelectionListeners(GetType());
+
   // Also need to notify the frames!
   // PresShell::CharacterDataChanged should do that on DocumentChanged
   if (NS_FAILED(result)) {
     aRv.Throw(result);
   }
 }
 
 /** AddRange adds the specified range to the selection
@@ -5021,16 +5030,18 @@ Selection::AddRangeInternal(nsRange& aRa
   }
 
   RefPtr<nsPresContext>  presContext = GetPresContext();
   selectFrames(presContext, &aRange, true);
 
   if (!mFrameSelection)
     return;//nothing to do
 
+  // Be aware, this instance may be destroyed after this call.
+  // XXX Why doesn't this call Selection::NotifySelectionListener() directly?
   result = mFrameSelection->NotifySelectionListeners(GetType());
   if (NS_FAILED(result)) {
     aRv.Throw(result);
   }
 }
 
 // Selection::RemoveRange
 //
@@ -5115,16 +5126,19 @@ Selection::RemoveRange(nsRange& aRange, 
     // might appear to be moving randomly (bug 337871).
     if (mSelectionType != SelectionType::eSpellCheck && cnt > 0) {
       ScrollIntoView(nsISelectionController::SELECTION_FOCUS_REGION);
     }
   }
 
   if (!mFrameSelection)
     return;//nothing to do
+
+  // Be aware, this instance may be destroyed after this call.
+  // XXX Why doesn't this call Selection::NotifySelectionListener() directly?
   rv = mFrameSelection->NotifySelectionListeners(GetType());
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
 
 
@@ -5233,16 +5247,19 @@ Selection::Collapse(nsINode& aParentNode
   int32_t rangeIndex = -1;
   result = AddItem(range, &rangeIndex);
   if (NS_FAILED(result)) {
     aRv.Throw(result);
     return;
   }
   setAnchorFocusRange(0);
   selectFrames(presContext, range, true);
+
+  // Be aware, this instance may be destroyed after this call.
+  // XXX Why doesn't this call Selection::NotifySelectionListener() directly?
   result = mFrameSelection->NotifySelectionListeners(GetType());
   if (NS_FAILED(result)) {
     aRv.Throw(result);
   }
 }
 
 /*
  * Sets the whole selection to be one point
@@ -5813,16 +5830,19 @@ Selection::Extend(nsINode& aParentNode, 
   if (GetDirection() != oldDirection) {
     printf("    direction changed to %s\n",
            GetDirection() == eDirNext? "eDirNext":"eDirPrevious");
   }
   nsCOMPtr<nsIContent> content = do_QueryInterface(&aParentNode);
   printf ("Sel. Extend to %p %s %d\n", content.get(),
           nsAtomCString(content->NodeInfo()->NameAtom()).get(), aOffset);
 #endif
+
+  // Be aware, this instance may be destroyed after this call.
+  // XXX Why doesn't this call Selection::NotifySelectionListener() directly?
   res = mFrameSelection->NotifySelectionListeners(GetType());
   if (NS_FAILED(res)) {
     aRv.Throw(res);
   }
 }
 
 NS_IMETHODIMP
 Selection::SelectAllChildren(nsIDOMNode* aParentNode)
@@ -5985,16 +6005,40 @@ nsIPresShell*
 Selection::GetPresShell() const
 {
   if (!mFrameSelection)
     return nullptr;//nothing to do
 
   return mFrameSelection->GetShell();
 }
 
+nsIDocument*
+Selection::GetDocument() const
+{
+  nsIPresShell* presShell = GetPresShell();
+  return presShell ? presShell->GetDocument() : nullptr;
+}
+
+nsPIDOMWindowOuter*
+Selection::GetWindow() const
+{
+  nsIDocument* document = GetDocument();
+  return document ? document->GetWindow() : nullptr;
+}
+
+nsIEditor*
+Selection::GetEditor() const
+{
+  nsPresContext* presContext = GetPresContext();
+  if (!presContext) {
+    return nullptr;
+  }
+  return nsContentUtils::GetHTMLEditor(presContext);
+}
+
 nsIFrame *
 Selection::GetSelectionAnchorGeometry(SelectionRegion aRegion, nsRect* aRect)
 {
   if (!mFrameSelection)
     return nullptr;  // nothing to do
 
   NS_ENSURE_TRUE(aRect, nullptr);
 
@@ -6289,30 +6333,113 @@ Selection::RemoveSelectionListener(nsISe
                                    ErrorResult& aRv)
 {
   bool result = mSelectionListeners.RemoveObject(aListenerToRemove); // Releases
   if (!result) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
+Element*
+Selection::GetCommonEditingHostForAllRanges()
+{
+  Element* editingHost = nullptr;
+  for (RangeData& rangeData : mRanges) {
+    nsRange* range = rangeData.mRange;
+    MOZ_ASSERT(range);
+    nsINode* commonAncestorNode = range->GetCommonAncestor();
+    if (!commonAncestorNode || !commonAncestorNode->IsContent()) {
+      return nullptr;
+    }
+    nsIContent* commonAncestor = commonAncestorNode->AsContent();
+    Element* foundEditingHost = commonAncestor->GetEditingHost();
+    // Even when common ancestor is a non-editable element in a contenteditable
+    // element, we don't need to move focus to the contenteditable element
+    // because Chromium doesn't set focus to it.
+    if (!foundEditingHost) {
+      return nullptr;
+    }
+    if (!editingHost) {
+      editingHost = foundEditingHost;
+      continue;
+    }
+    if (editingHost == foundEditingHost) {
+      continue;
+    }
+    if (nsContentUtils::ContentIsDescendantOf(foundEditingHost, editingHost)) {
+      continue;
+    }
+    if (nsContentUtils::ContentIsDescendantOf(editingHost, foundEditingHost)) {
+      editingHost = foundEditingHost;
+      continue;
+    }
+    // editingHost and foundEditingHost are not a descendant of the other.
+    // So, there is no common editing host.
+    return nullptr;
+  }
+  return editingHost;
+}
+
 nsresult
 Selection::NotifySelectionListeners(bool aCalledByJS)
 {
   AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
   mCalledByJS = aCalledByJS;
   return NotifySelectionListeners();
 }
 
 nsresult
 Selection::NotifySelectionListeners()
 {
   if (!mFrameSelection)
     return NS_OK;//nothing to do
- 
+
+  // When normal selection is changed by Selection API, we need to move focus
+  // if common ancestor of all ranges are in an editing host.  Note that we
+  // don't need to move focus *to* the other focusable node because other
+  // browsers don't do it either.
+  if (mSelectionType == SelectionType::eNormal && mCalledByJS) {
+    nsPIDOMWindowOuter* window = GetWindow();
+    nsIDocument* document = GetDocument();
+    // If the document is in design mode or doesn't have contenteditable
+    // element, we don't need to move focus.
+    if (window && document && !document->HasFlag(NODE_IS_EDITABLE) &&
+        GetEditor()) {
+      RefPtr<Element> newEditingHost = GetCommonEditingHostForAllRanges();
+      nsFocusManager* fm = nsFocusManager::GetFocusManager();
+      nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
+      nsIContent* focusedContent =
+        fm->GetFocusedDescendant(window, false, getter_AddRefs(focusedWindow));
+      nsCOMPtr<Element> focusedElement = do_QueryInterface(focusedContent);
+      // When all selected ranges are in an editing host, it should take focus.
+      if (newEditingHost && newEditingHost != focusedElement) {
+        MOZ_ASSERT(!newEditingHost->IsInNativeAnonymousSubtree());
+        nsCOMPtr<nsIDOMElement> domElementToFocus =
+          do_QueryInterface(newEditingHost->AsDOMNode());
+        // Note that don't steal focus from focused window if the window doesn't
+        // have focus.
+        fm->SetFocus(domElementToFocus, nsIFocusManager::FLAG_NOSWITCHFRAME);
+      }
+      // Otherwise, if current focused element is an editing host, it should
+      // be blurred if there is no common editing host of the selected ranges.
+      else if (!newEditingHost && focusedElement &&
+               focusedElement == focusedElement->GetEditingHost()) {
+        IgnoredErrorResult err;
+        focusedElement->Blur(err);
+        NS_WARNING_ASSERTION(!err.Failed(),
+                             "Failed to blur focused element");
+      }
+    }
+  }
+
+  // After moving focus, especially in selection listeners, our internal code
+  // should not move focus with using this class.
+  AutoRestore<bool> calledFromExternalRestorer(mCalledByJS);
+  mCalledByJS = false;
+
   if (mFrameSelection->GetBatching()) {
     mFrameSelection->SetDirty();
     return NS_OK;
   }
   nsCOMArray<nsISelectionListener> selectionListeners(mSelectionListeners);
   int32_t cnt = selectionListeners.Count();
   if (cnt != mSelectionListeners.Count()) {
     return NS_ERROR_OUT_OF_MEMORY;  // nsCOMArray is fallible
--- a/testing/web-platform/mozilla/meta/focus/Range_collapse.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Range_collapse.html.ini
@@ -1,17 +1,2 @@
 [Range_collapse.html]
   type: testharness
-
-  [Active element should be 'editor' after Range.collapse(false) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.collapse(true) of selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.collapse(false) of selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Range.collapse(false) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.collapse(false) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Range_selectNode.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Range_selectNode.html.ini
@@ -1,128 +1,2 @@
 [Range_selectNode.html]
   type: testharness
-
-  [Active element should be 'editor' after Range.selectNode() with the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNode() with the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNode() with the first text node of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'staticBefore' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNode() with the first text node of 'outerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'staticInEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNode() with the first text node of 'innerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'anchor' when active element is the 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'staticBefore' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNode() with the first text node of 'editor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNode() with the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'anchor' when active element is the 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'staticBefore' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNode() with the first text node of 'editor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNode() with the first text node of 'outerEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'staticInEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNode() with the first text node of 'anchor' when active element is the 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNode() with the first text node of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNode() with the first text node of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNode() with the first text node of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNodeContents() with the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNodeContents() with the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNodeContents() with the first text node of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'staticBefore' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNodeContents() with the first text node of 'outerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'staticInEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNodeContents() with the first text node of 'innerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'anchor' when active element is the 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'staticBefore' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNodeContents() with the first text node of 'editor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNodeContents() with the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'anchor' when active element is the 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'staticBefore' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNodeContents() with the first text node of 'editor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNodeContents() with the first text node of 'outerEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'staticInEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.selectNodeContents() with the first text node of 'anchor' when active element is the 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.selectNodeContents() with the first text node of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.selectNodeContents() with the first text node of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.selectNodeContents() with the first text node of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Range_setEnd.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Range_setEnd.html.ini
@@ -1,122 +1,2 @@
 [Range_setEnd.html]
   type: testharness
-
-  [Active element should be the <body> after Range.setEnd() with start of the first text node of 'staticBefore' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEnd() with start of the first text node of 'editor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEnd() with start of the first text node of 'outerEditor' (before the selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEnd() with start of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEnd() with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEnd() with start of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEnd() with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEnd() with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEnd() with start of the first text node of 'editor' (before the selection, between end of the first text node of 'editor' and end of the first text node of 'outerEditor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndBefore() with start of the first text node of 'staticBefore' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEndBefore() with start of the first text node of 'editor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEndBefore() with start of the first text node of 'outerEditor' (before the selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEndBefore() with start of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndBefore() with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEndBefore() with start of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEndBefore() with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setEndBefore() with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEndBefore() with start of the first text node of 'editor' (before the selection, between end of the first text node of 'editor' and end of the first text node of 'outerEditor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticAfter']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setEndAfter() with the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'editor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEnd() with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEnd() with start of the first text node of 'staticAfter' (after end of the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEnd() with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEnd() with start of the first text node of 'staticAfter' (after end of the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndAfter() with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndAfter() with start of the first text node of 'staticAfter' (after end of the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndAfter() with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndAfter() with start of the first text node of 'staticAfter' (after end of the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndBefore() with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndBefore() with start of the first text node of 'staticAfter' (after end of the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndBefore() with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setEndBefore() with start of the first text node of 'staticAfter' (after end of the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEnd() with end of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setEnd() with end of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'innerEditor' and selection end is in 'staticAfter']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setEndAfter() with end of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setEndAfter() with end of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'innerEditor' and selection end is in 'staticAfter']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Range_setStart.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Range_setStart.html.ini
@@ -1,200 +1,2 @@
 [Range_setStart.html]
   type: testharness
-
-  [Active element should be 'editor' after Range.setStart() with end of the first text node of 'editor' (before the selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStart() with end of the first text node of 'outerEditor' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticInEditor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStart() with end of the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticAfter' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStart() with end of the first text node of 'editor' (before the collapsed selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStart() with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStart() with end of the first text node of 'innerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStart() with end of the first text node of 'editor' (before the selection, between start of the first text node of 'staticBefore' and start of the first text node of 'editor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStart() with end of the first text node of 'outerEditor' (before the selection, between start of the first text node of 'editor' and start of the first text node of 'outerEditor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticInEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'staticInEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStart() with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'innerEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStart() with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'staticInEditor' and start of the first text node of 'innerEditor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStartAfter() with end of the first text node of 'editor' (before the selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartAfter() with end of the first text node of 'outerEditor' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticInEditor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStartAfter() with end of the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticAfter' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStartAfter() with end of the first text node of 'editor' (before the collapsed selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartAfter() with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStartAfter() with end of the first text node of 'innerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStartAfter() with end of the first text node of 'editor' (before the selection, between start of the first text node of 'staticBefore' and start of the first text node of 'editor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartAfter() with end of the first text node of 'outerEditor' (before the selection, between start of the first text node of 'editor' and start of the first text node of 'outerEditor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticInEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'staticInEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStartAfter() with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'innerEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStartAfter() with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'staticInEditor' and start of the first text node of 'innerEditor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStartBefore() with the first text node of 'editor' (before the selection) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartBefore() with the first text node of 'outerEditor' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStart() with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticBefore' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'editor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStart() with end of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with end of the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartAfter() with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticBefore' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'editor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartAfter() with end of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartAfter() with end of the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with end of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with end of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartBefore() with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with end of the first text node of 'staticBefore' (before the selection) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with end of the first text node of 'editor' (before the selection) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartBefore() with end of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with end of the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStart() with start of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStart() with start of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStart() with start of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStart() with start of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Range.setStartBefore() with start of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Range.setStartBefore() with start of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Range.setStartBefore() with start of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Range.setStartBefore() with start of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'outerEditor']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_addRange.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_addRange.html.ini
@@ -1,233 +1,2 @@
 [Selection_addRange.html]
   type: testharness
-
-  [Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'outerEditor' and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'anchor']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_addRange_into_iframe.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_addRange_into_iframe.html.ini
@@ -1,8 +1,2 @@
 [Selection_addRange_into_iframe.html]
   type: testharness
-
-  [Active element should be 'editor1' in the <iframe> after Selection.addRange() but parent's active document should be the <body>]
-    expected: FAIL
-
-  [Active element should be 'editor2' in the <iframe> after Selection.addRange() but parent's active document should be the <body>]
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_collapse.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_collapse.html.ini
@@ -1,25 +1,10 @@
 [Selection_collapse.html]
   type: testharness
-  [Active element should be 'editor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'outerEditor' to start of the first text node of 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.collapse() moving selection from first text node in 'outerEditor' to start of the first text node of 'staticInEditor']
-    expected: FAIL
-
   [Active element should be the <body> after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of the <body>]
     expected: FAIL
 
   [Active element should be 'editor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'editor']
     expected: FAIL
 
   [Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'outerEditor']
     expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_collapseToEnd.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_collapseToEnd.html.ini
@@ -1,10 +1,2 @@
 [Selection_collapseToEnd.html]
   type: testharness
-  [Active element should be 'editor' after Selection.collapseToEnd() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_collapseToStart.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_collapseToStart.html.ini
@@ -1,7 +1,2 @@
 [Selection_collapseToStart.html]
   type: testharness
-  [Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_selectAllChildren.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_selectAllChildren.html.ini
@@ -1,20 +1,11 @@
 [Selection_selectAllChildren.html]
   type: testharness
 
-  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'editor']
     expected: FAIL
 
   [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'editor']
     expected: FAIL
 
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'editor']
     expected: FAIL
@@ -26,22 +17,16 @@
     expected: FAIL
 
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'outerEditor']
     expected: FAIL
 
   [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'outerEditor']
     expected: FAIL
 
-  [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'outerEditor']
     expected: FAIL
 
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'innerEditor']
     expected: FAIL
 
   [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'innerEditor']
     expected: FAIL
@@ -49,17 +34,8 @@
   [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'innerEditor']
     expected: FAIL
 
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'innerEditor']
     expected: FAIL
 
   [Active element should be the <body> after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'innerEditor']
     expected: FAIL
-
-  [Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
--- a/testing/web-platform/mozilla/meta/focus/Selection_setBaseAndExtent.html.ini
+++ b/testing/web-platform/mozilla/meta/focus/Selection_setBaseAndExtent.html.ini
@@ -1,233 +1,2 @@
 [Selection_setBaseAndExtent.html]
   type: testharness
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body> and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'outerEditor' and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is the <body>]
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'editor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'outerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'innerEditor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'anchor']
-    expected: FAIL
-
-  [Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'anchor']
-    expected: FAIL