Bug 1449564 - part 2: Make absolute positioned element editor disabled in default and make it possible to enable it with new command r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 04 Apr 2018 22:27:49 +0900
changeset 432307 ccb713187e45a0ce52cf0ebe8969ddac9608e215
parent 432306 4e0960a6ffb6c283f29d75ba5bc2585df4c3caf0
child 432308 e93a23a4741c7760d76e33c3515e9b6ee2f5e26d
push id34471
push usershindli@mozilla.com
push dateMon, 20 Aug 2018 09:49:47 +0000
treeherdermozilla-central@41993cf46d6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1449564
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1449564 - part 2: Make absolute positioned element editor disabled in default and make it possible to enable it with new command r=m_kato We have another built-in UI of editor which is not implemented by any other browsers. That is a draggable handler to move absolute positioned elements. So, we should disable it in default for compatibility with the other browsers. However, different from resizers and inline table editor, we don't have command to enable/disable this feature but for backward compatibility, we should have it. Therefore, this patch adds new command "enableAbsolutePositionEditor". Note that whether resizing UI is available only with enableObjectResizing state is different from enableInlineTableEditing command. Resizers for absolute positioned elements are NOT available both enableObjectResizing and enableAbsolutePositionEditor are enabled. Additionally, this adds automated tests to check basic functions of absolute positioned editor. MozReview-Commit-ID: 9ZSGB8tLpFw
dom/html/nsHTMLDocument.cpp
editor/libeditor/HTMLAbsPositionEditor.cpp
editor/libeditor/HTMLAnonymousNodeEditor.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLEditorCommands.cpp
editor/libeditor/HTMLEditorController.cpp
editor/libeditor/HTMLEditorDocumentCommands.cpp
editor/libeditor/tests/mochitest.ini
editor/libeditor/tests/test_abs_positioner_appearance.html
editor/libeditor/tests/test_abs_positioner_positioning_elements.html
editor/libeditor/tests/test_resizers_appearance.html
editor/libeditor/tests/test_resizers_resizing_elements.html
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -2723,16 +2723,17 @@ static const struct MidasCommand gMidasC
   { "formatblock",   "cmd_paragraphState",  "", false, false },
   { "heading",       "cmd_paragraphState",  "", false, false },
   { "styleWithCSS",  "cmd_setDocumentUseCSS", "", false, true },
   { "contentReadOnly", "cmd_setDocumentReadOnly", "", false, true },
   { "insertBrOnReturn", "cmd_insertBrOnReturn", "", false, true },
   { "defaultParagraphSeparator", "cmd_defaultParagraphSeparator", "", false, false },
   { "enableObjectResizing", "cmd_enableObjectResizing", "", false, true },
   { "enableInlineTableEditing", "cmd_enableInlineTableEditing", "", false, true },
+  { "enableAbsolutePositionEditing", "cmd_enableAbsolutePositionEditing", "", false, true },
 #if 0
 // no editor support to remove alignments right now
   { "justifynone",   "cmd_align",           "", true,  false },
 
 // the following will need special review before being turned on
   { "saveas",        "cmd_saveAs",          "", true,  false },
   { "print",         "cmd_print",           "", true,  false },
 #endif
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -104,24 +104,24 @@ HTMLEditor::GetAbsolutelyPositionedSelec
     element = element->GetParentElement();
   }
   return nullptr;
 }
 
 NS_IMETHODIMP
 HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled)
 {
-  *aIsEnabled = AbsolutePositioningEnabled();
+  *aIsEnabled = IsAbsolutePositionEditorEnabled();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled)
 {
-  mIsAbsolutelyPositioningEnabled = aIsEnabled;
+  EnableAbsolutePositionEditor(aIsEnabled);
   return NS_OK;
 }
 
 nsresult
 HTMLEditor::RelativeChangeElementZIndex(Element& aElement,
                                         int32_t aChange,
                                         int32_t* aReturn)
 {
--- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
+++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
@@ -290,17 +290,17 @@ NS_IMETHODIMP
 HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
 {
   if (NS_WARN_IF(!aSelection)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // early way out if all contextual UI extensions are disabled
   if (NS_WARN_IF(!IsObjectResizerEnabled() &&
-                 !mIsAbsolutelyPositioningEnabled &&
+                 !IsAbsolutePositionEditorEnabled() &&
                  !IsInlineTableEditorEnabled())) {
     return NS_OK;
   }
 
   // Don't change selection state if we're moving.
   if (mIsMoving) {
     return NS_OK;
   }
@@ -315,17 +315,17 @@ HTMLEditor::CheckSelectionStateForAnonym
   if (!focusElement->IsInUncomposedDoc()) {
     return NS_OK;
   }
 
   // what's its tag?
   nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
 
   RefPtr<Element> absPosElement;
-  if (mIsAbsolutelyPositioningEnabled) {
+  if (IsAbsolutePositionEditorEnabled()) {
     // Absolute Positioning support is enabled, is the selection contained
     // in an absolutely positioned element ?
     absPosElement = GetAbsolutelyPositionedSelectionContainer();
   }
 
   RefPtr<Element> cellElement;
   if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
     // Resizing or Inline Table Editing is enabled, we need to check if the
@@ -356,17 +356,17 @@ HTMLEditor::CheckSelectionStateForAnonym
   // at this point, focusElement  contains the element for Resizing,
   //                cellElement   contains the element for InlineTableEditing
   //                absPosElement contains the element for Positioning
 
   // Note: All the Hide/Show methods below may change attributes on real
   // content which means a DOMAttrModified handler may cause arbitrary
   // side effects while this code runs (bug 420439).
 
-  if (mIsAbsolutelyPositioningEnabled && mAbsolutelyPositionedObject &&
+  if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
       absPosElement != mAbsolutelyPositionedObject) {
     HideGrabber();
     NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
   }
 
   if (IsObjectResizerEnabled() && mResizedObject &&
       mResizedObject != focusElement) {
     nsresult rv = HideResizers();
@@ -397,17 +397,17 @@ HTMLEditor::CheckSelectionStateForAnonym
     } else {
       nsresult rv = ShowResizers(*focusElement);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
-  if (mIsAbsolutelyPositioningEnabled && absPosElement &&
+  if (IsAbsolutePositionEditorEnabled() && absPosElement &&
       IsModifiableNode(*absPosElement) && absPosElement != hostContent) {
     if (mAbsolutelyPositionedObject) {
       nsresult rv = RefreshGrabber();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     } else {
       nsresult rv = ShowGrabber(*absPosElement);
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -115,17 +115,17 @@ HTMLEditor::HTMLEditor()
   : mCRInParagraphCreatesParagraph(false)
   , mCSSAware(false)
   , mSelectedCellIndex(0)
   , mHasShownResizers(false)
   , mIsObjectResizingEnabled(false)
   , mIsResizing(false)
   , mPreserveRatio(false)
   , mResizedObjectIsAnImage(false)
-  , mIsAbsolutelyPositioningEnabled(true)
+  , mIsAbsolutelyPositioningEnabled(false)
   , mResizedObjectIsAbsolutelyPositioned(false)
   , mHasShownGrabber(false)
   , mGrabberClicked(false)
   , mIsMoving(false)
   , mSnapToGridEnabled(false)
   , mHasShownInlineTableEditor(false)
   , mIsInlineTableEditingEnabled(false)
   , mOriginalX(0)
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -242,22 +242,32 @@ public:
   {
     mIsInlineTableEditingEnabled = aEnable;
   }
   bool IsInlineTableEditorEnabled() const
   {
     return mIsInlineTableEditingEnabled;
   }
 
-  // non-virtual methods of interface methods
-  bool AbsolutePositioningEnabled() const
+  /**
+   * Enable/disable absolute position editor, resizing absolute positioned
+   * elements (required object resizers enabled) or positioning them with
+   * dragging grabber.
+   */
+  void EnableAbsolutePositionEditor(bool aEnable)
+  {
+    mIsAbsolutelyPositioningEnabled = aEnable;
+  }
+  bool IsAbsolutePositionEditorEnabled() const
   {
     return mIsAbsolutelyPositioningEnabled;
   }
 
+  // non-virtual methods of interface methods
+
   /**
    * returns the deepest absolutely positioned container of the selection
    * if it exists or null.
    */
   already_AddRefed<Element> GetAbsolutelyPositionedSelectionContainer();
 
   Element* GetPositionedElement() const
   {
--- a/editor/libeditor/HTMLEditorCommands.cpp
+++ b/editor/libeditor/HTMLEditorCommands.cpp
@@ -1079,46 +1079,45 @@ AlignCommand::SetState(HTMLEditor* aHTML
 AbsolutePositioningCommand::AbsolutePositioningCommand()
   : StateUpdatingCommandBase(nsGkAtoms::_empty)
 {
 }
 
 NS_IMETHODIMP
 AbsolutePositioningCommand::IsCommandEnabled(const char* aCommandName,
                                              nsISupports* aCommandRefCon,
-                                             bool* outCmdEnabled)
+                                             bool* aOutCmdEnabled)
 {
-  *outCmdEnabled = false;
+  *aOutCmdEnabled = false;
 
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (!editor) {
     return NS_OK;
   }
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   if (!htmlEditor->IsSelectionEditable()) {
     return NS_OK;
   }
-  *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
+  *aOutCmdEnabled = htmlEditor->IsAbsolutePositionEditorEnabled();
   return NS_OK;
 }
 
 nsresult
 AbsolutePositioningCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
                                             nsICommandParams* aParams)
 {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCommandParams* params = aParams->AsCommandParams();
-  bool isEnabled = aHTMLEditor->AbsolutePositioningEnabled();
-  if (!isEnabled) {
+  if (!aHTMLEditor->IsAbsolutePositionEditorEnabled()) {
     params->SetBool(STATE_MIXED, false);
     params->SetCString(STATE_ATTRIBUTE, EmptyCString());
     return NS_OK;
   }
 
   RefPtr<Element> container =
     aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
   params->SetBool(STATE_MIXED,  false);
@@ -1138,40 +1137,41 @@ AbsolutePositioningCommand::ToggleState(
   RefPtr<Element> container =
     aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
   return aHTMLEditor->SetSelectionToAbsoluteOrStatic(!container);
 }
 
 
 NS_IMETHODIMP
 DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* refCon,
-                                        bool* outCmdEnabled)
+                                        nsISupports* aRefCon,
+                                        bool* aOutCmdEnabled)
 {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
+  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aRefCon);
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_FAILURE;
   }
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
-  *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
-  if (!(*outCmdEnabled))
+  if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
+    *aOutCmdEnabled = false;
     return NS_OK;
+  }
 
   RefPtr<Element> positionedElement = htmlEditor->GetPositionedElement();
-  *outCmdEnabled = false;
   if (!positionedElement) {
+    *aOutCmdEnabled = false;
     return NS_OK;
   }
 
   int32_t z = htmlEditor->GetZIndex(*positionedElement);
-  *outCmdEnabled = (z > 0);
+  *aOutCmdEnabled = (z > 0);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DecreaseZIndexCommand::DoCommand(const char* aCommandName,
                                  nsISupports* refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
@@ -1204,34 +1204,34 @@ DecreaseZIndexCommand::GetCommandStatePa
   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return aParams->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
 }
 
 NS_IMETHODIMP
 IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* refCon,
-                                        bool* outCmdEnabled)
+                                        nsISupports* aRefCon,
+                                        bool* aOutCmdEnabled)
 {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
+  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aRefCon);
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_FAILURE;
   }
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
-  *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
-  if (!(*outCmdEnabled))
+  if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
+    *aOutCmdEnabled = false;
     return NS_OK;
+  }
 
-  Element* positionedElement = htmlEditor->GetPositionedElement();
-  *outCmdEnabled = (nullptr != positionedElement);
+  *aOutCmdEnabled = !!htmlEditor->GetPositionedElement();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IncreaseZIndexCommand::DoCommand(const char* aCommandName,
                                  nsISupports* refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
--- a/editor/libeditor/HTMLEditorController.cpp
+++ b/editor/libeditor/HTMLEditorController.cpp
@@ -64,17 +64,18 @@ HTMLEditorController::RegisterEditorDocS
 
   // commands that may get or change state
   NS_REGISTER_FIRST_COMMAND(SetDocumentStateCommand, "cmd_setDocumentModified")
   NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_setDocumentUseCSS")
   NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_setDocumentReadOnly")
   NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_insertBrOnReturn")
   NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_defaultParagraphSeparator")
   NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_enableObjectResizing")
-  NS_REGISTER_LAST_COMMAND(SetDocumentStateCommand, "cmd_enableInlineTableEditing")
+  NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_enableInlineTableEditing")
+  NS_REGISTER_LAST_COMMAND(SetDocumentStateCommand, "cmd_enableAbsolutePositionEditing")
 
   NS_REGISTER_ONE_COMMAND(SetDocumentOptionsCommand, "cmd_setDocumentOptions")
 
   return NS_OK;
 }
 
 // static
 nsresult
--- a/editor/libeditor/HTMLEditorDocumentCommands.cpp
+++ b/editor/libeditor/HTMLEditorDocumentCommands.cpp
@@ -357,16 +357,31 @@ SetDocumentStateCommand::DoCommandParams
     bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     htmlEditor->EnableInlineTableEditor(enabled);
     return NS_OK;
   }
 
+  if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
+    NS_ENSURE_ARG_POINTER(aParams);
+    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+    if (NS_WARN_IF(!htmlEditor)) {
+      return NS_ERROR_INVALID_ARG;
+    }
+    ErrorResult error;
+    bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.StealNSResult();
+    }
+    htmlEditor->EnableAbsolutePositionEditor(enabled);
+    return NS_OK;
+  }
+
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 SetDocumentStateCommand::GetCommandStateParams(const char* aCommandName,
                                                nsICommandParams* aParams,
                                                nsISupports* refCon)
 {
@@ -519,16 +534,28 @@ SetDocumentStateCommand::GetCommandState
     // and nsHTMLDocument::QueryCommandState().
     rv = params->SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
+  // cmd_enableAbsolutePositionEditing is a Gecko specific command,
+  // "cenableAbsolutePositionEditing".
+  if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
+    NS_ENSURE_ARG_POINTER(aParams);
+    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+    if (NS_WARN_IF(!htmlEditor)) {
+      return NS_ERROR_INVALID_ARG;
+    }
+    return params->SetBool(STATE_ALL,
+                           htmlEditor->IsAbsolutePositionEditorEnabled());
+  }
+
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /**
  * Commands just for state notification
  *  As of 11/21/02, possible commands are:
  *    "obs_documentCreated"
  *    "obs_documentWillBeDestroyed"
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -254,16 +254,20 @@ skip-if = toolkit == 'android' # bug 131
 [test_bug1385905.html]
 [test_bug1390562.html]
 [test_bug1394758.html]
 [test_bug1399722.html]
 [test_bug1406726.html]
 [test_bug1409520.html]
 [test_bug1425997.html]
 
+[test_abs_positioner_appearance.html]
+skip-if = toolkit == 'android' && debug # bug 1480702, causes permanent failure of non-related test
+[test_abs_positioner_positioning_elements.html]
+skip-if = android_version == '18' # bug 1147989
 [test_CF_HTML_clipboard.html]
 subsuite = clipboard
 [test_composition_event_created_in_chrome.html]
 [test_contenteditable_focus.html]
 [test_documentCharacterSet.html]
 [test_dom_input_event_on_htmleditor.html]
 skip-if = toolkit == 'android' # bug 1054087
 [test_dom_input_event_on_texteditor.html]
copy from editor/libeditor/tests/test_resizers_appearance.html
copy to editor/libeditor/tests/test_abs_positioner_appearance.html
--- a/editor/libeditor/tests/test_resizers_appearance.html
+++ b/editor/libeditor/tests/test_abs_positioner_appearance.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <title>Test for resizers appearance</title>
+  <title>Test for absolute positioner appearance</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none;">
 
@@ -28,68 +28,140 @@ SimpleTest.waitForFocus(async function()
         resolve();
       }, {once: true});
     });
   }
 
   let editor = document.getElementById("editor");
   let outOfEditor = document.getElementById("clickaway");
 
-  const kTests = [
-    { description: "<img>",
-      innerHTML: "<img id=\"target\" src=\"green.png\" width=\"100\" height=\"100\">",
-      resizable: true,
-    },
-    { description: "<table>",
-      innerHTML: "<table id=\"target\" border><tr><td>1-1</td><td>1-2</td></tr><tr><td>2-1</td><td>2-2</td></tr></table>",
-      resizable: true,
-    },
-    { description: "absolute positioned <div>",
-      innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>",
-      resizable: true,
-    },
-    { description: "fixed positioned <div>",
-      innerHTML: "<div id=\"target\" style=\"position: fixed; top: 50px; left: 50px;\">positioned</div>",
-      resizable: false,
-    },
-    { description: "relative positioned <div>",
-      innerHTML: "<div id=\"target\" style=\"position: relative; top: 50px; left: 50px;\">positioned</div>",
-      resizable: false,
-    },
-  ];
+  async function testIfAppears() {
+    const kTests = [
+      { description: "absolute positioned <div>",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>",
+        movable: true,
+      },
+      { description: "fixed positioned <div>",
+        innerHTML: "<div id=\"target\" style=\"position: fixed; top: 50px; left: 50px;\">positioned</div>",
+        movable: false,
+      },
+      { description: "relative positioned <div>",
+        innerHTML: "<div id=\"target\" style=\"position: relative; top: 50px; left: 50px;\">positioned</div>",
+        movable: false,
+      },
+    ];
+
+    for (const kTest of kTests) {
+      const kDescription = "testIfAppears, " + kTest.description + ": ";
+      editor.innerHTML = kTest.innerHTML;
+      let target = document.getElementById("target");
+
+      document.execCommand("enableAbsolutePositionEditing", false, false);
+      ok(!document.queryCommandState("enableAbsolutePositionEditing"),
+         kDescription + "Absolute positioned element editor should be disabled by the call of execCommand");
+
+      synthesizeMouseAtCenter(outOfEditor, {});
+      let promiseSelectionChangeEvent1 = waitForSelectionChange();
+      synthesizeMouseAtCenter(target, {});
+      await promiseSelectionChangeEvent1;
+
+      ok(!target.hasAttribute("_moz_abspos"),
+         kDescription + "While enableAbsolutePositioner is disabled, positioner shouldn't appear");
+
+      document.execCommand("enableAbsolutePositionEditing", false, true);
+      ok(document.queryCommandState("enableAbsolutePositionEditing"),
+         kDescription + "Absolute positioned element editor should be enabled by the call of execCommand");
+
+      synthesizeMouseAtCenter(outOfEditor, {});
+      let promiseSelectionChangeEvent2 = waitForSelectionChange();
+      synthesizeMouseAtCenter(target, {});
+      await promiseSelectionChangeEvent2;
+
+      is(target.hasAttribute("_moz_abspos"), kTest.movable,
+         kDescription + (kTest.movable ? "While enableAbsolutePositionEditing is enabled, positioner should appear" :
+                                         "Even while enableAbsolutePositionEditing is enabled, positioner shouldn't appear"));
+    }
+  }
 
-  for (const kTest of kTests) {
-    const kDescription = kTest.description + ": ";
-    editor.innerHTML = kTest.innerHTML;
-    let target = document.getElementById("target");
-
-    document.execCommand("enableObjectResizing", false, false);
-    ok(!document.queryCommandState("enableObjectResizing"),
-       kDescription + "Object resizer should be disabled by the call of execCommand");
-
-    synthesizeMouseAtCenter(outOfEditor, {});
-    let promiseSelectionChangeEvent1 = waitForSelectionChange();
-    synthesizeMouseAtCenter(target, {});
-    await promiseSelectionChangeEvent1;
+  async function testStyle() {
+    // See HTMLEditor::GetTemporaryStyleForFocusedPositionedElement().
+    const kTests = [
+      { description: "background-color: transparent; color: white;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-color: transparent; " +
+                                              "color: white;\">positioned</div>",
+        value: "black",
+      },
+      { description: "background-color: transparent; color: black;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-color: transparent; " +
+                                              "color: black;\">positioned</div>",
+        value: "white",
+      },
+      { description: "background-color: black; color: white;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-color: black; " +
+                                              "color: white;\">positioned</div>",
+        value: "",
+      },
+      { description: "background-color: white; color: black;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-color: white; " +
+                                              "color: black;\">positioned</div>",
+        value: "",
+      },
+      { description: "background-image: green.png; background-color: black; color: white;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-image: green.png; " +
+                                              "background-color: black; " +
+                                              "color: white;\">positioned</div>",
+        value: "",
+      },
+      { description: "background-image: green.png; background-color: white; color: black;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-image: green.png; " +
+                                              "background-color: white; " +
+                                              "color: black;\">positioned</div>",
+        value: "",
+      },
+      { description: "background-image: green.png;",
+        innerHTML: "<div id=\"target\" style=\"position: absolute; " +
+                                              "top: 50%; left: 50%; " +
+                                              "background-image: green.png;\">positioned</div>",
+        value: "white", // XXX Why? background-image is not "none"...
+      },
+    ];
 
-    ok(!target.hasAttribute("_moz_resizing"),
-       kDescription + ": While enableObjectResizing is disabled, resizers shouldn't appear");
+    document.execCommand("enableAbsolutePositionEditing", false, true);
+    ok(document.queryCommandState("enableAbsolutePositionEditing"),
+       "testStyle, Absolute positioned element editor should be enabled by the call of execCommand");
 
-    document.execCommand("enableObjectResizing", false, true);
-    ok(document.queryCommandState("enableObjectResizing"),
-       kDescription + "Object resizer should be enabled by the call of execCommand");
+    for (const kTest of kTests) {
+      const kDescription = "testStyle, " + kTest.description + ": ";
+
+      editor.innerHTML = kTest.innerHTML;
+      let target = document.getElementById("target");
 
-    synthesizeMouseAtCenter(outOfEditor, {});
-    let promiseSelectionChangeEvent2 = waitForSelectionChange();
-    synthesizeMouseAtCenter(target, {});
-    await promiseSelectionChangeEvent2;
+      synthesizeMouseAtCenter(outOfEditor, {});
+      let promiseSelectionChangeEvent = waitForSelectionChange();
+      synthesizeMouseAtCenter(target, {});
+      await promiseSelectionChangeEvent;
 
-    is(target.hasAttribute("_moz_resizing"), kTest.resizable,
-       kDescription + (kTest.resizable ? "While enableObjectResizing is enabled, resizers should appear" :
-                                         "Even while enableObjectResizing is enabled, resizers shouldn't appear"));
+      is(target.getAttribute("_moz_abspos"), kTest.value,
+         kDescription + "The value of _moz_abspos attribute is unexpected");
+    }
   }
 
+  await testIfAppears();
+  await testStyle();
+
   SimpleTest.finish();
 });
 </script>
 </pre>
 </body>
 </html>
copy from editor/libeditor/tests/test_resizers_resizing_elements.html
copy to editor/libeditor/tests/test_abs_positioner_positioning_elements.html
--- a/editor/libeditor/tests/test_resizers_resizing_elements.html
+++ b/editor/libeditor/tests/test_abs_positioner_positioning_elements.html
@@ -1,230 +1,120 @@
 <!DOCTYPE HTML>
 <html>
 <head>
-  <title>Test for resizers of some elements</title>
+  <title>Test for positioners of absolute positioned elements</title>
   <script type="application/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>
   #target {
     background-color: green;
   }
   </style>
 </head>
 <body>
 <p id="display"></p>
-<div id="content" contenteditable style="width: 200px; height: 200px;"></div>
-<div id="clickaway" style="width: 10px; height: 10px"></div>
+<div id="content" contenteditable style="height: 200px; width: 200px;"></div>
+<div id="clickaway" style="position: absolute; top: 250px; width: 10px; height: 10px; z-index: 100;"></div>
 <img src="green.png"><!-- for ensuring to load the image at first test of <img> case -->
 <pre id="test">
 <script type="application/javascript">
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(async function() {
-  document.execCommand("enableObjectResizing", false, true);
-  ok(document.queryCommandState("enableObjectResizing"),
-     "Object resizer should be enabled by the call of execCommand");
+  document.execCommand("enableAbsolutePositionEditing", false, true);
+  ok(document.queryCommandState("enableAbsolutePositionEditing"),
+     "Absolute positioned element editor should be enabled by the call of execCommand");
 
   let outOfEditor = document.getElementById("clickaway");
 
-  function cancel(e) { e.stopPropagation(); }
+  function cancel(e) { /* TODO: e.stopPropagation(); */ }
   let content = document.getElementById("content");
   content.addEventListener("mousedown", cancel);
   content.addEventListener("mousemove", cancel);
   content.addEventListener("mouseup", cancel);
 
   async function waitForSelectionChange() {
     return new Promise(resolve => {
       document.addEventListener("selectionchange", () => {
         resolve();
       }, {once: true});
     });
   }
 
-  async function doTest(aDescription, aPreserveRatio, aInnerHTML) {
-    let description = aDescription;
-    if (SpecialPowers.getBoolPref("editor.resizing.preserve_ratio")) {
-      description += " (preserve ratio pref is true)";
-    }
-    description += ": ";
+  async function doTest(aDescription, aInnerHTML) {
     content.innerHTML = aInnerHTML;
+    let description = aDescription + ": ";
     let target = document.getElementById("target");
+    target.style.position = "absolute";
 
-    /**
-     * This function is a generic resizer test.
-     * We have 8 resizers that we'd like to test, and each can be moved in 8 different directions.
-     * In specifying baseX, W can be considered to be the width of the image, and for baseY, H
-     * can be considered to be the height of the image. deltaX and deltaY are regular pixel values
-     * which can be positive or negative.
-     */
-    const W = 1;
-    const H = 1;
-    async function testResizer(baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY) {
-      ok(true, description + "testResizer(" + [baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY].join(", ") + ")");
+    async function testPositioner(aDeltaX, aDeltaY) {
+      ok(true, description + "testPositioner(" + [aDeltaX, aDeltaY].join(", ") + ")");
 
-      // Reset the dimensions of the target.
-      target.style.width = "150px";
-      target.style.height = "150px";
-      let rect = target.getBoundingClientRect();
-      is(rect.width, 150, description + "Sanity check the width");
-      is(rect.height, 150, description + "Sanity check the height");
+      // Reset the position of the target.
+      target.style.top = "50px";
+      target.style.left = "50px";
 
-      // Click on the target to show the resizers
+      // Click on the target to show the positioner.
       let promiseSelectionChangeEvent = waitForSelectionChange();
       synthesizeMouseAtCenter(target, {});
       await promiseSelectionChangeEvent;
 
-      // Determine which resizer we're dealing with.
-      let basePosX = rect.width * baseX;
-      let basePosY = rect.height * baseY;
+      let rect = target.getBoundingClientRect();
+
+      ok(target.hasAttribute("_moz_abspos"),
+         description + "While enableAbsolutePositionEditing is enabled, the positioner should appear");
 
-      // Click on the correct resizer
-      synthesizeMouse(target, basePosX, basePosY, {type: "mousedown"});
-      // Drag it delta pixels to the right and bottom (or maybe left and top!)
-      synthesizeMouse(target, basePosX + deltaX, basePosY + deltaY, {type: "mousemove"});
+      // left is abs positioned element's left + margin-left + border-left-width + 12.
+      // XXX Perhaps, we need to add border-left-width here if you add new test to have thick border.
+      const kPositionerX = 18
+      // top is abs positioned element's top + margin-top + border-top-width - 14.
+      // XXX Perhaps, we need to add border-top-width here if you add new test to have thick border.
+      const kPositionerY = -7;
+
+      // Click on the positioner.
+      synthesizeMouse(target, kPositionerX, kPositionerY, {type: "mousedown"});
+      // Drag it delta pixels.
+      synthesizeMouse(target, kPositionerX + aDeltaX, kPositionerY + aDeltaY, {type: "mousemove"});
       // Release the mouse button
-      synthesizeMouse(target, basePosX + deltaX, basePosY + deltaY, {type: "mouseup"});
+      synthesizeMouse(target, kPositionerX + aDeltaX, kPositionerY + aDeltaY, {type: "mouseup"});
       // Move the mouse delta more pixels to the same direction to make sure that the
-      // resize operation has stopped.
-      synthesizeMouse(target, basePosX + deltaX * 2, basePosY + deltaY * 2, {type: "mousemove"});
-      // Click outside of the editor to hide the resizers
+      // positioning operation has stopped.
+      synthesizeMouse(target, kPositionerX + aDeltaX * 2, kPositionerY + aDeltaY * 2, {type: "mousemove"});
+      // Click outside of the image to hide the positioner.
       synthesizeMouseAtCenter(outOfEditor, {});
 
-      // Get the new dimensions for the target
+      // Get the new dimensions for the absolute positioned element.
       let newRect = target.getBoundingClientRect();
-      isfuzzy(newRect.width, rect.width + expectedDeltaX, 1, description + "The width should be increased by " + expectedDeltaX + " pixels");
-      isfuzzy(newRect.height, rect.height + expectedDeltaY, 1, description + "The height should be increased by " + expectedDeltaY + "pixels");
+      isfuzzy(newRect.x, rect.x + aDeltaX, 1, description + "The left should be increased by " + aDeltaX + " pixels");
+      isfuzzy(newRect.y, rect.y + aDeltaY, 1, description + "The top should be increased by " + aDeltaY + "pixels");
     }
 
-    // Account for changes in the resizing behavior when we're trying to preserve
-    // the aspect ration of image.
-    // ignoredGrowth means we don't change the size of a dimension because otherwise
-    // the aspect ratio would change undesirably.
-    // needlessGrowth means that we change the size of a dimension perpendecular to
-    // the mouse movement axis in order to preserve the aspect ratio.
-    // reversedGrowth means that we change the size of a dimension in the opposite
-    // direction to the mouse movement in order to maintain the aspect ratio.
-    const ignoredGrowth = aPreserveRatio ? 0 : 1;
-    const needlessGrowth = aPreserveRatio ? 1 : 0;
-    const reversedGrowth = aPreserveRatio ? -1 : 1;
-
-    // top resizer
-    await testResizer(W/2,   0, -10, -10,   0,  10);
-    await testResizer(W/2,   0, -10,   0,   0,   0);
-    await testResizer(W/2,   0, -10,  10,   0, -10);
-    await testResizer(W/2,   0,   0, -10,   0,  10);
-    await testResizer(W/2,   0,   0,   0,   0,   0);
-    await testResizer(W/2,   0,   0,  10,   0, -10);
-    await testResizer(W/2,   0,  10, -10,   0,  10);
-    await testResizer(W/2,   0,  10,   0,   0,   0);
-    await testResizer(W/2,   0,  10,  10,   0, -10);
-
-    // top right resizer
-    await testResizer(  W,   0, -10, -10, -10 * reversedGrowth, 10);
-    await testResizer(  W,   0, -10,   0, -10 * ignoredGrowth,   0);
-    await testResizer(  W,   0, -10,  10, -10, -10);
-    await testResizer(  W,   0,   0, -10,  10 * needlessGrowth,  10);
-    await testResizer(  W,   0,   0,   0,   0,   0);
-    await testResizer(  W,   0,   0,  10,   0, -10 * ignoredGrowth);
-    await testResizer(  W,   0,  10, -10,  10,  10);
-    await testResizer(  W,   0,  10,   0,  10,  10 * needlessGrowth);
-    await testResizer(  W,   0,  10,  10,  10, -10 * reversedGrowth);
-
-    // right resizer
-    await testResizer(  W, H/2, -10, -10, -10,   0);
-    await testResizer(  W, H/2, -10,   0, -10,   0);
-    await testResizer(  W, H/2, -10,  10, -10,   0);
-    await testResizer(  W, H/2,   0, -10,   0,   0);
-    await testResizer(  W, H/2,   0,   0,   0,   0);
-    await testResizer(  W, H/2,   0,  10,   0,   0);
-    await testResizer(  W, H/2,  10, -10,  10,   0);
-    await testResizer(  W, H/2,  10,   0,  10,   0);
-    await testResizer(  W, H/2,  10,  10,  10,   0);
-
-    // bottom right resizer
-    await testResizer(  W,   H, -10, -10, -10, -10);
-    await testResizer(  W,   H, -10,   0, -10 * ignoredGrowth,   0);
-    await testResizer(  W,   H, -10,  10, -10 * reversedGrowth,  10);
-    await testResizer(  W,   H,   0, -10,   0, -10 * ignoredGrowth);
-    await testResizer(  W,   H,   0,   0,   0,   0);
-    await testResizer(  W,   H,   0,  10,  10 * needlessGrowth,  10);
-    await testResizer(  W,   H,  10, -10,  10, -10 * reversedGrowth);
-    await testResizer(  W,   H,  10,   0,  10,  10 * needlessGrowth);
-    await testResizer(  W,   H,  10,  10,  10,  10);
-
-    // bottom resizer
-    await testResizer(W/2,   H, -10, -10,   0, -10);
-    await testResizer(W/2,   H, -10,   0,   0,   0);
-    await testResizer(W/2,   H, -10,  10,   0,  10);
-    await testResizer(W/2,   H,   0, -10,   0, -10);
-    await testResizer(W/2,   H,   0,   0,   0,   0);
-    await testResizer(W/2,   H,   0,  10,   0,  10);
-    await testResizer(W/2,   H,  10, -10,   0, -10);
-    await testResizer(W/2,   H,  10,   0,   0,   0);
-    await testResizer(W/2,   H,  10,  10,   0,  10);
-
-    // bottom left resizer
-    await testResizer(  0,   H, -10, -10,  10, -10 * reversedGrowth);
-    await testResizer(  0,   H, -10,   0,  10,  10 * needlessGrowth);
-    await testResizer(  0,   H, -10,  10,  10,  10);
-    await testResizer(  0,   H,   0, -10,   0, -10 * ignoredGrowth);
-    await testResizer(  0,   H,   0,   0,   0,   0);
-    await testResizer(  0,   H,   0,  10,  10 * needlessGrowth,  10);
-    await testResizer(  0,   H,  10, -10, -10, -10);
-    await testResizer(  0,   H,  10,   0, -10 * ignoredGrowth,   0);
-    await testResizer(  0,   H,  10,  10, -10 * reversedGrowth,  10);
-
-    // left resizer
-    await testResizer(  0, H/2, -10, -10,  10,   0);
-    await testResizer(  0, H/2, -10,   0,  10,   0);
-    await testResizer(  0, H/2, -10,  10,  10,   0);
-    await testResizer(  0, H/2,   0, -10,   0,   0);
-    await testResizer(  0, H/2,   0,   0,   0,   0);
-    await testResizer(  0, H/2,   0,  10,   0,   0);
-    await testResizer(  0, H/2,  10, -10, -10,   0);
-    await testResizer(  0, H/2,  10,   0, -10,   0);
-    await testResizer(  0, H/2,  10,  10, -10,   0);
-
-    // top left resizer
-    await testResizer(  0,   0, -10, -10,  10,  10);
-    await testResizer(  0,   0, -10,   0,  10,  10 * needlessGrowth);
-    await testResizer(  0,   0, -10,  10,  10, -10 * reversedGrowth);
-    await testResizer(  0,   0,   0, -10,  10 * needlessGrowth,  10);
-    await testResizer(  0,   0,   0,   0,   0,   0);
-    await testResizer(  0,   0,   0,  10,   0, -10 * ignoredGrowth);
-    await testResizer(  0,   0,  10, -10, -10 * reversedGrowth,  10);
-    await testResizer(  0,   0,  10,   0, -10 * ignoredGrowth,   0);
-    await testResizer(  0,   0,  10,  10, -10, -10);
+    await testPositioner( 10,  10);
+    await testPositioner( 10, -10);
+    await testPositioner(-10,  10);
+    await testPositioner(-10, -10);
   }
 
   const kTests = [
-    { description: "Resiziers for <img>",
+    { description: "Positioner for <img>",
       innerHTML: "<img id=\"target\" src=\"green.png\">",
-      mayPreserveRatio: true,
     },
-    { description: "Resiziers for <table>",
+    { description: "Positioner for <table>",
       innerHTML: "<table id=\"target\" border><tr><td>cell</td><td>cell</td></tr></table>",
-      mayPreserveRatio: false,
     },
-    { description: "Resiziers for absolute positioned <div>",
-      innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>",
-      mayPreserveRatio: false,
+    { description: "Positioner for <div>",
+      innerHTML: "<div id=\"target\">div element</div>",
     },
   ];
 
-  await SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", false]]});
   for (const kTest of kTests) {
-    await doTest(kTest.description, false, kTest.innerHTML);
-  }
-  await SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", true]]});
-  for (const kTest of kTests) {
-    await doTest(kTest.description, kTest.mayPreserveRatio, kTest.innerHTML);
+    await doTest(kTest.description, kTest.innerHTML);
   }
   content.innerHTML = "";
   SimpleTest.finish();
 });
 </script>
 </pre>
 </body>
 </html>
--- a/editor/libeditor/tests/test_resizers_appearance.html
+++ b/editor/libeditor/tests/test_resizers_appearance.html
@@ -39,57 +39,62 @@ SimpleTest.waitForFocus(async function()
       resizable: true,
     },
     { description: "<table>",
       innerHTML: "<table id=\"target\" border><tr><td>1-1</td><td>1-2</td></tr><tr><td>2-1</td><td>2-2</td></tr></table>",
       resizable: true,
     },
     { description: "absolute positioned <div>",
       innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>",
-      resizable: true,
+      resizable: function () { return document.queryCommandState("enableAbsolutePositionEditing"); },
     },
     { description: "fixed positioned <div>",
       innerHTML: "<div id=\"target\" style=\"position: fixed; top: 50px; left: 50px;\">positioned</div>",
       resizable: false,
     },
     { description: "relative positioned <div>",
       innerHTML: "<div id=\"target\" style=\"position: relative; top: 50px; left: 50px;\">positioned</div>",
       resizable: false,
     },
   ];
 
-  for (const kTest of kTests) {
-    const kDescription = kTest.description + ": ";
-    editor.innerHTML = kTest.innerHTML;
-    let target = document.getElementById("target");
+  for (let kEnableAbsolutePositionEditor of [true, false]) {
+    document.execCommand("enableAbsolutePositionEditing", false, kEnableAbsolutePositionEditor);
+    for (const kTest of kTests) {
+      const kDescription = kTest.description +
+        (kEnableAbsolutePositionEditor ? " (enabled absolute position editor)" : "") + ": ";
+      editor.innerHTML = kTest.innerHTML;
+      let target = document.getElementById("target");
 
-    document.execCommand("enableObjectResizing", false, false);
-    ok(!document.queryCommandState("enableObjectResizing"),
-       kDescription + "Object resizer should be disabled by the call of execCommand");
+      document.execCommand("enableObjectResizing", false, false);
+      ok(!document.queryCommandState("enableObjectResizing"),
+         kDescription + "Object resizer should be disabled by the call of execCommand");
 
-    synthesizeMouseAtCenter(outOfEditor, {});
-    let promiseSelectionChangeEvent1 = waitForSelectionChange();
-    synthesizeMouseAtCenter(target, {});
-    await promiseSelectionChangeEvent1;
+      synthesizeMouseAtCenter(outOfEditor, {});
+      let promiseSelectionChangeEvent1 = waitForSelectionChange();
+      synthesizeMouseAtCenter(target, {});
+      await promiseSelectionChangeEvent1;
 
-    ok(!target.hasAttribute("_moz_resizing"),
-       kDescription + ": While enableObjectResizing is disabled, resizers shouldn't appear");
+      ok(!target.hasAttribute("_moz_resizing"),
+         kDescription + ": While enableObjectResizing is disabled, resizers shouldn't appear");
 
-    document.execCommand("enableObjectResizing", false, true);
-    ok(document.queryCommandState("enableObjectResizing"),
-       kDescription + "Object resizer should be enabled by the call of execCommand");
+      document.execCommand("enableObjectResizing", false, true);
+      ok(document.queryCommandState("enableObjectResizing"),
+         kDescription + "Object resizer should be enabled by the call of execCommand");
 
-    synthesizeMouseAtCenter(outOfEditor, {});
-    let promiseSelectionChangeEvent2 = waitForSelectionChange();
-    synthesizeMouseAtCenter(target, {});
-    await promiseSelectionChangeEvent2;
+      synthesizeMouseAtCenter(outOfEditor, {});
+      let promiseSelectionChangeEvent2 = waitForSelectionChange();
+      synthesizeMouseAtCenter(target, {});
+      await promiseSelectionChangeEvent2;
 
-    is(target.hasAttribute("_moz_resizing"), kTest.resizable,
-       kDescription + (kTest.resizable ? "While enableObjectResizing is enabled, resizers should appear" :
-                                         "Even while enableObjectResizing is enabled, resizers shouldn't appear"));
+      const kResizable = typeof kTest.resizable === "function" ? kTest.resizable() : kTest.resizable;
+      is(target.hasAttribute("_moz_resizing"), kResizable,
+         kDescription + (kResizable ? "While enableObjectResizing is enabled, resizers should appear" :
+                                      "Even while enableObjectResizing is enabled, resizers shouldn't appear"));
+    }
   }
 
   SimpleTest.finish();
 });
 </script>
 </pre>
 </body>
 </html>
--- a/editor/libeditor/tests/test_resizers_resizing_elements.html
+++ b/editor/libeditor/tests/test_resizers_resizing_elements.html
@@ -42,16 +42,19 @@ SimpleTest.waitForFocus(async function()
     });
   }
 
   async function doTest(aDescription, aPreserveRatio, aInnerHTML) {
     let description = aDescription;
     if (SpecialPowers.getBoolPref("editor.resizing.preserve_ratio")) {
       description += " (preserve ratio pref is true)";
     }
+    if (document.queryCommandState("enableAbsolutePositionEditing")) {
+      description += " (absolute position editor is enabled)";
+    }
     description += ": ";
     content.innerHTML = aInnerHTML;
     let target = document.getElementById("target");
 
     /**
      * This function is a generic resizer test.
      * We have 8 resizers that we'd like to test, and each can be moved in 8 different directions.
      * In specifying baseX, W can be considered to be the width of the image, and for baseY, H
@@ -197,33 +200,41 @@ SimpleTest.waitForFocus(async function()
     await testResizer(  0,   0,  10,   0, -10 * ignoredGrowth,   0);
     await testResizer(  0,   0,  10,  10, -10, -10);
   }
 
   const kTests = [
     { description: "Resiziers for <img>",
       innerHTML: "<img id=\"target\" src=\"green.png\">",
       mayPreserveRatio: true,
+      isAbsolutePosition: false,
     },
     { description: "Resiziers for <table>",
       innerHTML: "<table id=\"target\" border><tr><td>cell</td><td>cell</td></tr></table>",
       mayPreserveRatio: false,
+      isAbsolutePosition: false,
     },
     { description: "Resiziers for absolute positioned <div>",
       innerHTML: "<div id=\"target\" style=\"position: absolute; top: 50px; left: 50px;\">positioned</div>",
       mayPreserveRatio: false,
+      isAbsolutePosition: true,
     },
   ];
 
+  // Resizers for absolute positioned element are available only when
+  // enableAbsolutePositionEditing is enabled.  So, let's enable it
+  // during testing resizers for absolute positioned elements.
   await SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", false]]});
   for (const kTest of kTests) {
+    document.execCommand("enableAbsolutePositionEditing", false, kTests.isAbsolutePosition);
     await doTest(kTest.description, false, kTest.innerHTML);
   }
   await SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", true]]});
   for (const kTest of kTests) {
+    document.execCommand("enableAbsolutePositionEditing", false, kTests.isAbsolutePosition);
     await doTest(kTest.description, kTest.mayPreserveRatio, kTest.innerHTML);
   }
   content.innerHTML = "";
   SimpleTest.finish();
 });
 </script>
 </pre>
 </body>