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, smaug draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 04 Apr 2018 22:27:49 +0900
changeset 777693 094d1ed044e170d9dd8d24582c76018c63f67e5c
parent 777692 c224c4ec6ecb394eddd1a68791e5fffd8c117256
child 777694 cf9b6929b8106c453b00236e692956fd4d6ca186
push id105264
push usermasayuki@d-toybox.com
push dateThu, 05 Apr 2018 05:23:22 +0000
reviewersm_kato, smaug
bugs1449564
milestone61.0a1
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, smaug 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/composer/nsComposerCommands.cpp
editor/composer/nsComposerController.cpp
editor/composer/nsComposerDocumentCommands.cpp
editor/libeditor/HTMLAbsPositionEditor.cpp
editor/libeditor/HTMLAnonymousNodeEditor.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
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
@@ -2663,16 +2663,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/composer/nsComposerCommands.cpp
+++ b/editor/composer/nsComposerCommands.cpp
@@ -1000,47 +1000,46 @@ nsAlignCommand::SetState(mozilla::HTMLEd
 }
 
 nsAbsolutePositioningCommand::nsAbsolutePositioningCommand()
 : nsBaseStateUpdatingCommand(nsGkAtoms::_empty)
 {
 }
 
 NS_IMETHODIMP
-nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName,
-                                               nsISupports *aCommandRefCon,
-                                               bool *outCmdEnabled)
+nsAbsolutePositioningCommand::IsCommandEnabled(const char* aCommandName,
+                                               nsISupports* aCommandRefCon,
+                                               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
 nsAbsolutePositioningCommand::GetCurrentState(mozilla::HTMLEditor* aHTMLEditor,
                                               nsICommandParams* aParams)
 {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  bool isEnabled = aHTMLEditor->AbsolutePositioningEnabled();
-  if (!isEnabled) {
+  if (!aHTMLEditor->IsAbsolutePositionEditorEnabled()) {
     aParams->SetBooleanValue(STATE_MIXED,false);
     aParams->SetCStringValue(STATE_ATTRIBUTE, "");
     return NS_OK;
   }
 
   RefPtr<Element> container =
     aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
   aParams->SetBooleanValue(STATE_MIXED,  false);
@@ -1057,41 +1056,42 @@ nsAbsolutePositioningCommand::ToggleStat
 
   RefPtr<Element> container =
     aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
   return aHTMLEditor->SetSelectionToAbsoluteOrStatic(!container);
 }
 
 
 NS_IMETHODIMP
-nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
-                                          nsISupports *refCon,
-                                          bool *outCmdEnabled)
+nsDecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
+                                          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
 nsDecreaseZIndexCommand::DoCommand(const char *aCommandName,
                                    nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
@@ -1123,35 +1123,35 @@ nsDecreaseZIndexCommand::GetCommandState
   bool enabled = false;
   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
 }
 
 NS_IMETHODIMP
-nsIncreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
-                                          nsISupports *refCon,
-                                          bool *outCmdEnabled)
+nsIncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
+                                          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
 nsIncreaseZIndexCommand::DoCommand(const char *aCommandName,
                                    nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
--- a/editor/composer/nsComposerController.cpp
+++ b/editor/composer/nsComposerController.cpp
@@ -61,17 +61,18 @@ nsComposerController::RegisterEditorDocS
 
   // commands that may get or change state
   NS_REGISTER_FIRST_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentModified")
   NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentUseCSS")
   NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentReadOnly")
   NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_insertBrOnReturn")
   NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_defaultParagraphSeparator")
   NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_enableObjectResizing")
-  NS_REGISTER_LAST_COMMAND(nsSetDocumentStateCommand, "cmd_enableInlineTableEditing")
+  NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_enableInlineTableEditing")
+  NS_REGISTER_LAST_COMMAND(nsSetDocumentStateCommand, "cmd_enableAbsolutePositionEditing")
 
   NS_REGISTER_ONE_COMMAND(nsSetDocumentOptionsCommand, "cmd_setDocumentOptions")
 
   return NS_OK;
 }
 
 // static
 nsresult
--- a/editor/composer/nsComposerDocumentCommands.cpp
+++ b/editor/composer/nsComposerDocumentCommands.cpp
@@ -326,16 +326,31 @@ nsSetDocumentStateCommand::DoCommandPara
     bool enabled;
     nsresult rvOR = aParams->GetBooleanValue(STATE_ATTRIBUTE, &enabled);
     NS_ENSURE_SUCCESS(rvOR, rvOR);
 
     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;
+    }
+
+    bool enabled;
+    nsresult rvOR = aParams->GetBooleanValue(STATE_ATTRIBUTE, &enabled);
+    NS_ENSURE_SUCCESS(rvOR, rvOR);
+
+    htmlEditor->EnableAbsolutePositionEditor(enabled);
+    return NS_OK;
+  }
+
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsSetDocumentStateCommand::GetCommandStateParams(const char *aCommandName,
                                                  nsICommandParams *aParams,
                                                  nsISupports *refCon)
 {
@@ -461,16 +476,28 @@ nsSetDocumentStateCommand::GetCommandSta
     }
     // We returned the result as STATE_ATTRIBUTE with bool value 60 or earlier.
     // So, the result was ignored by both nsHTMLDocument::QueryCommandValue()
     // and nsHTMLDocument::QueryCommandState().
     return aParams->SetBooleanValue(STATE_ALL,
                                     htmlEditor->IsInlineTableEditorEnabled());
   }
 
+  // cmd_enableAbsolutePositioner is a Gecko specific command,
+  // "cmd_enableAbsolutePositioner".
+  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 aParams->SetBooleanValue(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/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -94,24 +94,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
@@ -304,17 +304,17 @@ HTMLEditor::DeleteRefToAnonymousNode(Man
 // or refreshed
 NS_IMETHODIMP
 HTMLEditor::CheckSelectionStateForAnonymousButtons(nsISelection* aSelection)
 {
   NS_ENSURE_ARG_POINTER(aSelection);
 
   // 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;
   }
@@ -327,17 +327,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
@@ -367,17 +367,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();
@@ -408,17 +408,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
@@ -102,17 +102,17 @@ HTMLEditor::InsertNodeIntoProperAncestor
 HTMLEditor::HTMLEditor()
   : mCRInParagraphCreatesParagraph(false)
   , mCSSAware(false)
   , mSelectedCellIndex(0)
   , mIsObjectResizingEnabled(false)
   , mIsResizing(false)
   , mPreserveRatio(false)
   , mResizedObjectIsAnImage(false)
-  , mIsAbsolutelyPositioningEnabled(true)
+  , mIsAbsolutelyPositioningEnabled(false)
   , mResizedObjectIsAbsolutelyPositioned(false)
   , mGrabberClicked(false)
   , mIsMoving(false)
   , mSnapToGridEnabled(false)
   , mIsInlineTableEditingEnabled(false)
   , mOriginalX(0)
   , mOriginalY(0)
   , mResizedObjectX(0)
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -587,16 +587,30 @@ public:
   {
     mIsInlineTableEditingEnabled = aEnable;
   }
   bool IsInlineTableEditorEnabled() const
   {
     return mIsInlineTableEditingEnabled;
   }
 
+  /**
+   * 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;
+  }
+
 protected:
   class BlobReader final : public nsIEditorBlobListener
   {
   public:
     BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
                bool aIsSafe, nsIDOMDocument* aSourceDoc,
                nsINode* aDestinationNode, int32_t aDestOffset,
                bool aDoDeleteSelection);
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -252,16 +252,18 @@ 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]
+[test_abs_positioner_positioning_elements.html]
 [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>