tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HTMLAnonymousNodeEditor.cpp (22274B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "HTMLEditor.h"
      6 
      7 #include "CSSEditUtils.h"
      8 #include "HTMLEditUtils.h"
      9 
     10 #include "mozilla/PresShell.h"
     11 #include "mozilla/PresShellInlines.h"
     12 #include "mozilla/dom/BindContext.h"
     13 #include "mozilla/dom/Element.h"
     14 #include "mozilla/dom/ElementInlines.h"
     15 #include "mozilla/dom/EventTarget.h"
     16 #include "mozilla/mozalloc.h"
     17 #include "nsAString.h"
     18 #include "nsCOMPtr.h"
     19 #include "nsComputedDOMStyle.h"
     20 #include "nsDebug.h"
     21 #include "nsError.h"
     22 #include "nsFocusManager.h"
     23 #include "nsGenericHTMLElement.h"
     24 #include "nsGkAtoms.h"
     25 #include "nsAtom.h"
     26 #include "nsIContent.h"
     27 #include "nsID.h"
     28 #include "mozilla/dom/Document.h"
     29 #include "nsIDocumentObserver.h"
     30 #include "nsStubMutationObserver.h"
     31 #include "nsINode.h"
     32 #include "nsISupportsImpl.h"
     33 #include "nsISupportsUtils.h"
     34 #include "nsLiteralString.h"
     35 #include "nsPresContext.h"
     36 #include "nsReadableUtils.h"
     37 #include "nsString.h"
     38 #include "nsStringFwd.h"
     39 #include "nsStyledElement.h"
     40 #include "nsUnicharUtils.h"
     41 #include "nscore.h"
     42 #include "nsContentUtils.h"  // for nsAutoScriptBlocker
     43 #include "nsROCSSPrimitiveValue.h"
     44 
     45 class nsIDOMEventListener;
     46 
     47 namespace mozilla {
     48 
     49 using namespace dom;
     50 
     51 // Retrieve the rounded number of CSS pixels from a computed CSS property.
     52 //
     53 // Note that this should only be called for properties whose resolved value
     54 // is CSS pixels (like width, height, left, top, right, bottom, margin, padding,
     55 // border-*-width, ...).
     56 //
     57 // See: https://drafts.csswg.org/cssom/#resolved-values
     58 static int32_t GetCSSFloatValue(nsComputedDOMStyle* aComputedStyle,
     59                                const nsACString& aProperty) {
     60  MOZ_ASSERT(aComputedStyle);
     61 
     62  // get the computed CSSValue of the property
     63  nsAutoCString value;
     64  aComputedStyle->GetPropertyValue(aProperty, value);
     65  // We only care about resolved values, not a big deal if the element is
     66  // undisplayed, for example, and the value is "auto" or what not.
     67  nsresult rv = NS_OK;
     68  int32_t val = value.ToInteger(&rv);
     69  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsAString::ToInteger() failed");
     70  return NS_SUCCEEDED(rv) ? val : 0;
     71 }
     72 
     73 /******************************************************************************
     74 * mozilla::ElementDeletionObserver
     75 *****************************************************************************/
     76 
     77 class ElementDeletionObserver final : public nsStubMultiMutationObserver {
     78 public:
     79  ElementDeletionObserver(nsIContent* aNativeAnonNode,
     80                          Element* aObservedElement)
     81      : mNativeAnonNode(aNativeAnonNode), mObservedElement(aObservedElement) {
     82    AddMutationObserverToNode(aNativeAnonNode);
     83    AddMutationObserverToNode(aObservedElement);
     84  }
     85 
     86  NS_DECL_ISUPPORTS
     87  NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
     88  NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
     89 
     90 protected:
     91  ~ElementDeletionObserver() = default;
     92  nsIContent* mNativeAnonNode;
     93  Element* mObservedElement;
     94 };
     95 
     96 NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
     97 
     98 void ElementDeletionObserver::ParentChainChanged(nsIContent* aContent) {
     99  // If the native anonymous content has been unbound already in
    100  // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
    101  if (aContent != mObservedElement || !mNativeAnonNode ||
    102      mNativeAnonNode->GetParent() != aContent) {
    103    return;
    104  }
    105 
    106  ManualNACPtr::RemoveContentFromNACArray(mNativeAnonNode);
    107 
    108  mObservedElement->RemoveMutationObserver(this);
    109  mObservedElement = nullptr;
    110  mNativeAnonNode->RemoveMutationObserver(this);
    111  mNativeAnonNode = nullptr;
    112  NS_RELEASE_THIS();
    113 }
    114 
    115 void ElementDeletionObserver::NodeWillBeDestroyed(nsINode* aNode) {
    116  NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedElement,
    117               "Wrong aNode!");
    118  if (aNode == mNativeAnonNode) {
    119    mObservedElement->RemoveMutationObserver(this);
    120    mObservedElement = nullptr;
    121  } else {
    122    mNativeAnonNode->RemoveMutationObserver(this);
    123    mNativeAnonNode->UnbindFromTree();
    124    mNativeAnonNode = nullptr;
    125  }
    126 
    127  NS_RELEASE_THIS();
    128 }
    129 
    130 /******************************************************************************
    131 * mozilla::HTMLEditor
    132 *****************************************************************************/
    133 
    134 ManualNACPtr HTMLEditor::CreateAnonymousElement(nsAtom* aTag,
    135                                                nsIContent& aParentContent,
    136                                                const nsAString& aAnonClass,
    137                                                bool aIsCreatedHidden) {
    138  // Don't put anonymous editor element into non-HTML element.
    139  // It is mainly for avoiding other anonymous element being inserted
    140  // into <svg:use>, but in general we probably don't want to insert
    141  // some random HTML anonymous element into a non-HTML element.
    142  if (!aParentContent.IsHTMLElement()) {
    143    return nullptr;
    144  }
    145 
    146  if (NS_WARN_IF(!GetDocument())) {
    147    return nullptr;
    148  }
    149 
    150  RefPtr<PresShell> presShell = GetPresShell();
    151  if (NS_WARN_IF(!presShell)) {
    152    return nullptr;
    153  }
    154 
    155  // Create a new node through the element factory
    156  RefPtr<Element> newElement = CreateHTMLContent(aTag);
    157  if (!newElement) {
    158    NS_WARNING("EditorBase::CreateHTMLContent() failed");
    159    return nullptr;
    160  }
    161 
    162  if (aIsCreatedHidden) {
    163    nsresult rv =
    164        newElement->SetAttr(kNameSpaceID_None, nsGkAtoms::hidden, u""_ns, true);
    165    if (NS_FAILED(rv)) {
    166      NS_WARNING("Element::SetAttr(nsGkAtoms::hidden, ...) failed");
    167      return nullptr;
    168    }
    169  }
    170 
    171  // add an _moz_anonclass attribute if needed
    172  if (!aAnonClass.IsEmpty()) {
    173    nsresult rv = newElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
    174                                      aAnonClass, true);
    175    if (NS_FAILED(rv)) {
    176      NS_WARNING("Element::SetAttr(nsGkAtoms::_moz_anonclass) failed");
    177      return nullptr;
    178    }
    179  }
    180 
    181  nsAutoScriptBlocker scriptBlocker;
    182 
    183  // establish parenthood of the element
    184  newElement->SetIsNativeAnonymousRoot();
    185  BindContext context(*aParentContent.AsElement(),
    186                      BindContext::ForNativeAnonymous);
    187  if (NS_FAILED(newElement->BindToTree(context, aParentContent))) {
    188    NS_WARNING("Element::BindToTree(BindContext::ForNativeAnonymous) failed");
    189    newElement->UnbindFromTree();
    190    return nullptr;
    191  }
    192 
    193  ManualNACPtr newNativeAnonymousContent(newElement.forget());
    194  auto* observer = new ElementDeletionObserver(newNativeAnonymousContent,
    195                                               aParentContent.AsElement());
    196  NS_ADDREF(observer);  // NodeWillBeDestroyed releases.
    197 
    198 #ifdef DEBUG
    199  // Editor anonymous content gets passed to PostRecreateFramesFor... Which
    200  // can't _really_ deal with anonymous content (because it can't get the frame
    201  // tree ordering right).  But for us the ordering doesn't matter so this is
    202  // sort of ok.
    203  newNativeAnonymousContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
    204                                         reinterpret_cast<void*>(true));
    205 #endif  // DEBUG
    206 
    207  // display the element
    208  presShell->ContentAppended(newNativeAnonymousContent, {});
    209 
    210  return newNativeAnonymousContent;
    211 }
    212 
    213 // Removes event listener and calls DeleteRefToAnonymousNode.
    214 void HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
    215                                            nsIDOMEventListener* aListener,
    216                                            bool aUseCapture,
    217                                            ManualNACPtr aElement,
    218                                            PresShell* aPresShell) {
    219  if (aElement) {
    220    aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
    221  }
    222  DeleteRefToAnonymousNode(std::move(aElement), aPresShell);
    223 }
    224 
    225 // Deletes all references to an anonymous element
    226 void HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
    227                                          PresShell* aPresShell) {
    228  // call ContentRemoved() for the anonymous content
    229  // node so its references get removed from the frame manager's
    230  // undisplay map, and its layout frames get destroyed!
    231 
    232  if (NS_WARN_IF(!aContent)) {
    233    return;
    234  }
    235 
    236  if (NS_WARN_IF(!aContent->GetParent())) {
    237    // aContent was already removed?
    238    return;
    239  }
    240 
    241  nsAutoScriptBlocker scriptBlocker;
    242  // Need to check whether aPresShell has been destroyed (but not yet deleted).
    243  // See bug 338129.
    244  if (aContent->IsInComposedDoc() && aPresShell &&
    245      !aPresShell->IsDestroying()) {
    246    MOZ_ASSERT(aContent->IsRootOfNativeAnonymousSubtree());
    247    MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
    248 
    249    // FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
    250    // passes NAC into it. This is not great!
    251    aPresShell->ContentWillBeRemoved(aContent, {});
    252  }
    253 
    254  // The ManualNACPtr destructor will invoke UnbindFromTree.
    255 }
    256 
    257 void HTMLEditor::HideAnonymousEditingUIs() {
    258  if (mAbsolutelyPositionedObject) {
    259    HideGrabberInternal();
    260    NS_ASSERTION(!mAbsolutelyPositionedObject,
    261                 "HTMLEditor::HideGrabberInternal() failed, but ignored");
    262  }
    263  if (mInlineEditedCell) {
    264    HideInlineTableEditingUIInternal();
    265    NS_ASSERTION(
    266        !mInlineEditedCell,
    267        "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
    268  }
    269  if (mResizedObject) {
    270    DebugOnly<nsresult> rvIgnored = HideResizersInternal();
    271    NS_WARNING_ASSERTION(
    272        NS_SUCCEEDED(rvIgnored),
    273        "HTMLEditor::HideResizersInternal() failed, but ignored");
    274    NS_ASSERTION(!mResizedObject,
    275                 "HTMLEditor::HideResizersInternal() failed, but ignored");
    276  }
    277 }
    278 
    279 void HTMLEditor::HideAnonymousEditingUIsIfUnnecessary() {
    280  // XXX Perhaps, this is wrong approach to hide multiple UIs because
    281  //     hiding one UI may causes overwriting existing UI with newly
    282  //     created one.  In such case, we will leak overwritten UI.
    283  if (mAbsolutelyPositionedObject) {
    284    const Element* const editingHost =
    285        mAbsolutelyPositionedObject->GetEditingHost();
    286    if (!IsAbsolutePositionEditorEnabled() || !editingHost ||
    287        editingHost->IsContentEditablePlainTextOnly()) {
    288      // XXX If we're moving something, we need to cancel or commit the
    289      //     operation now.
    290      HideGrabberInternal();
    291      NS_ASSERTION(!mAbsolutelyPositionedObject,
    292                   "HTMLEditor::HideGrabberInternal() failed, but ignored");
    293    }
    294  }
    295  if (mInlineEditedCell) {
    296    const Element* const editingHost = mInlineEditedCell->GetEditingHost();
    297    if (!IsInlineTableEditorEnabled() || !editingHost ||
    298        editingHost->IsContentEditablePlainTextOnly()) {
    299      // XXX If we're resizing a table element, we need to cancel or commit the
    300      //     operation now.
    301      HideInlineTableEditingUIInternal();
    302      NS_ASSERTION(
    303          !mInlineEditedCell,
    304          "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
    305    }
    306  }
    307  if (mResizedObject) {
    308    const Element* const editingHost = mResizedObject->GetEditingHost();
    309    if (!IsObjectResizerEnabled() || !editingHost ||
    310        editingHost->IsContentEditablePlainTextOnly()) {
    311      // XXX If we're resizing something, we need to cancel or commit the
    312      //     operation now.
    313      DebugOnly<nsresult> rvIgnored = HideResizersInternal();
    314      NS_WARNING_ASSERTION(
    315          NS_SUCCEEDED(rvIgnored),
    316          "HTMLEditor::HideResizersInternal() failed, but ignored");
    317      NS_ASSERTION(!mResizedObject,
    318                   "HTMLEditor::HideResizersInternal() failed, but ignored");
    319    }
    320  }
    321 }
    322 
    323 NS_IMETHODIMP HTMLEditor::CheckSelectionStateForAnonymousButtons() {
    324  AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
    325  if (NS_WARN_IF(!editActionData.CanHandle())) {
    326    return NS_ERROR_NOT_INITIALIZED;
    327  }
    328 
    329  nsresult rv = RefreshEditingUI();
    330  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    331                       "HTMLEditor::RefereshEditingUI() failed");
    332  return EditorBase::ToGenericNSResult(rv);
    333 }
    334 
    335 nsresult HTMLEditor::RefreshEditingUI() {
    336  MOZ_ASSERT(IsEditActionDataAvailable());
    337 
    338  // First, we need to remove unnecessary editing UI now since some of them
    339  // may be disabled while them are visible.
    340  HideAnonymousEditingUIsIfUnnecessary();
    341 
    342  // early way out if all contextual UI extensions are disabled
    343  if (!IsObjectResizerEnabled() && !IsAbsolutePositionEditorEnabled() &&
    344      !IsInlineTableEditorEnabled()) {
    345    return NS_OK;
    346  }
    347 
    348  // Don't change selection state if we're moving.
    349  if (mIsMoving) {
    350    return NS_OK;
    351  }
    352 
    353  // let's get the containing element of the selection
    354  RefPtr<Element> selectionContainerElement = GetSelectionContainerElement();
    355  if (NS_WARN_IF(!selectionContainerElement)) {
    356    return NS_OK;
    357  }
    358 
    359  // If we're not in a document, don't try to add resizers
    360  if (!selectionContainerElement->IsInComposedDoc()) {
    361    return NS_OK;
    362  }
    363 
    364  const RefPtr<Element> editingHost =
    365      ComputeEditingHost(LimitInBodyElement::No);
    366  if (editingHost && editingHost->IsContentEditablePlainTextOnly()) {
    367    return NS_OK;
    368  }
    369  MOZ_ASSERT_IF(editingHost,
    370                editingHost == selectionContainerElement->GetEditingHost());
    371 
    372  // what's its tag?
    373  RefPtr<Element> focusElement = std::move(selectionContainerElement);
    374  nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
    375 
    376  RefPtr<Element> absPosElement;
    377  if (IsAbsolutePositionEditorEnabled()) {
    378    // Absolute Positioning support is enabled, is the selection contained
    379    // in an absolutely positioned element ?
    380    absPosElement = GetAbsolutelyPositionedSelectionContainer();
    381    if (NS_WARN_IF(Destroyed())) {
    382      return NS_ERROR_EDITOR_DESTROYED;
    383    }
    384  }
    385 
    386  RefPtr<Element> cellElement;
    387  if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
    388    // Resizing or Inline Table Editing is enabled, we need to check if the
    389    // selection is contained in a table cell
    390    cellElement = GetInclusiveAncestorByTagNameAtSelection(*nsGkAtoms::td);
    391  }
    392 
    393  if (IsObjectResizerEnabled() && cellElement) {
    394    // we are here because Resizing is enabled AND selection is contained in
    395    // a cell
    396 
    397    // get the enclosing table
    398    if (nsGkAtoms::img != focusTagAtom) {
    399      // the element container of the selection is not an image, so we'll show
    400      // the resizers around the table
    401      // XXX There may be a bug.  cellElement may be not in <table> in invalid
    402      //     tree.  So, perhaps, GetClosestAncestorTableElement() returns
    403      //     nullptr, we should not set focusTagAtom to nsGkAtoms::table.
    404      focusElement =
    405          HTMLEditUtils::GetClosestAncestorTableElement(*cellElement);
    406      focusTagAtom = nsGkAtoms::table;
    407    }
    408  }
    409 
    410  // we allow resizers only around images, tables, and absolutely positioned
    411  // elements. If we don't have image/table, let's look at the latter case.
    412  if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
    413    focusElement = absPosElement;
    414  }
    415 
    416  // at this point, focusElement  contains the element for Resizing,
    417  //                cellElement   contains the element for InlineTableEditing
    418  //                absPosElement contains the element for Positioning
    419 
    420  // TODO: Since we've already stopped supporting the DOM mutation events.
    421  // So, we may not need to verity the result below.
    422 
    423  if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
    424      absPosElement != mAbsolutelyPositionedObject) {
    425    HideGrabberInternal();
    426    NS_ASSERTION(!mAbsolutelyPositionedObject,
    427                 "HTMLEditor::HideGrabberInternal() failed, but ignored");
    428  }
    429 
    430  if (IsObjectResizerEnabled() && mResizedObject &&
    431      mResizedObject != focusElement) {
    432    // Perhaps, even if HideResizersInternal() failed, we should try to hide
    433    // inline table editing UI.  However, it returns error only when we cannot
    434    // do anything.  So, it's okay for now.
    435    nsresult rv = HideResizersInternal();
    436    if (NS_FAILED(rv)) {
    437      NS_WARNING("HTMLEditor::HideResizersInternal() failed");
    438      return rv;
    439    }
    440    NS_ASSERTION(!mResizedObject,
    441                 "HTMLEditor::HideResizersInternal() failed, but ignored");
    442  }
    443 
    444  if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
    445      mInlineEditedCell != cellElement) {
    446    HideInlineTableEditingUIInternal();
    447    NS_ASSERTION(
    448        !mInlineEditedCell,
    449        "HTMLEditor::HideInlineTableEditingUIInternal failed, but ignored");
    450  }
    451 
    452  // now, let's display all contextual UI for good
    453  if (IsObjectResizerEnabled() && focusElement &&
    454      HTMLEditUtils::IsSimplyEditableNode(*focusElement) &&
    455      focusElement != editingHost) {
    456    if (nsGkAtoms::img == focusTagAtom) {
    457      mResizedObjectIsAnImage = true;
    458    }
    459    if (mResizedObject) {
    460      nsresult rv = RefreshResizersInternal();
    461      if (NS_FAILED(rv)) {
    462        NS_WARNING("HTMLEditor::RefreshResizersInternal() failed");
    463        return rv;
    464      }
    465    } else {
    466      nsresult rv = ShowResizersInternal(*focusElement);
    467      if (NS_FAILED(rv)) {
    468        NS_WARNING("HTMLEditor::ShowResizersInternal() failed");
    469        return rv;
    470      }
    471    }
    472  }
    473 
    474  if (IsAbsolutePositionEditorEnabled() && absPosElement &&
    475      HTMLEditUtils::IsSimplyEditableNode(*absPosElement) &&
    476      absPosElement != editingHost) {
    477    if (mAbsolutelyPositionedObject) {
    478      nsresult rv = RefreshGrabberInternal();
    479      if (NS_FAILED(rv)) {
    480        NS_WARNING("HTMLEditor::RefreshGrabberInternal() failed");
    481        return rv;
    482      }
    483    } else {
    484      nsresult rv = ShowGrabberInternal(*absPosElement);
    485      if (NS_FAILED(rv)) {
    486        NS_WARNING("HTMLEditor::ShowGrabberInternal() failed");
    487        return rv;
    488      }
    489    }
    490  }
    491 
    492  // XXX Shouldn't we check whether the `<table>` element is editable or not?
    493  if (IsInlineTableEditorEnabled() && cellElement &&
    494      HTMLEditUtils::IsSimplyEditableNode(*cellElement) &&
    495      cellElement != editingHost) {
    496    if (mInlineEditedCell) {
    497      nsresult rv = RefreshInlineTableEditingUIInternal();
    498      if (NS_FAILED(rv)) {
    499        NS_WARNING("HTMLEditor::RefreshInlineTableEditingUIInternal() failed");
    500        return rv;
    501      }
    502    } else {
    503      nsresult rv = ShowInlineTableEditingUIInternal(*cellElement);
    504      if (NS_FAILED(rv)) {
    505        NS_WARNING("HTMLEditor::ShowInlineTableEditingUIInternal() failed");
    506        return rv;
    507      }
    508    }
    509  }
    510 
    511  return NS_OK;
    512 }
    513 
    514 // Resizing and Absolute Positioning need to know everything about the
    515 // containing box of the element: position, size, margins, borders
    516 nsresult HTMLEditor::GetPositionAndDimensions(Element& aElement, int32_t& aX,
    517                                              int32_t& aY, int32_t& aW,
    518                                              int32_t& aH, int32_t& aBorderLeft,
    519                                              int32_t& aBorderTop,
    520                                              int32_t& aMarginLeft,
    521                                              int32_t& aMarginTop) {
    522  // Is the element positioned ? let's check the cheap way first...
    523  bool isPositioned = aElement.HasAttr(nsGkAtoms::_moz_abspos);
    524  if (!isPositioned) {
    525    // hmmm... the expensive way now...
    526    nsAutoString positionValue;
    527    DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetComputedProperty(
    528        aElement, *nsGkAtoms::position, positionValue);
    529    if (NS_WARN_IF(Destroyed())) {
    530      return NS_ERROR_EDITOR_DESTROYED;
    531    }
    532    NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    533                         "CSSEditUtils::GetComputedProperty(nsGkAtoms::"
    534                         "position) failed, but ignored");
    535    isPositioned = positionValue.EqualsLiteral("absolute");
    536  }
    537 
    538  if (isPositioned) {
    539    // Yes, it is absolutely positioned
    540    mResizedObjectIsAbsolutelyPositioned = true;
    541 
    542    // Get the all the computed css styles attached to the element node
    543    RefPtr<nsComputedDOMStyle> computedDOMStyle =
    544        CSSEditUtils::GetComputedStyle(&aElement);
    545    if (NS_WARN_IF(!computedDOMStyle)) {
    546      return NS_ERROR_FAILURE;
    547    }
    548 
    549    aBorderLeft = GetCSSFloatValue(computedDOMStyle, "border-left-width"_ns);
    550    aBorderTop = GetCSSFloatValue(computedDOMStyle, "border-top-width"_ns);
    551    aMarginLeft = GetCSSFloatValue(computedDOMStyle, "margin-left"_ns);
    552    aMarginTop = GetCSSFloatValue(computedDOMStyle, "margin-top"_ns);
    553 
    554    aX = GetCSSFloatValue(computedDOMStyle, "left"_ns) + aMarginLeft +
    555         aBorderLeft;
    556    aY = GetCSSFloatValue(computedDOMStyle, "top"_ns) + aMarginTop + aBorderTop;
    557    aW = GetCSSFloatValue(computedDOMStyle, "width"_ns);
    558    aH = GetCSSFloatValue(computedDOMStyle, "height"_ns);
    559  } else {
    560    mResizedObjectIsAbsolutelyPositioned = false;
    561    RefPtr<nsGenericHTMLElement> htmlElement =
    562        nsGenericHTMLElement::FromNode(aElement);
    563    if (!htmlElement) {
    564      return NS_ERROR_NULL_POINTER;
    565    }
    566    DebugOnly<nsresult> rvIgnored = GetElementOrigin(aElement, aX, aY);
    567    NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    568                         "HTMLEditor::GetElementOrigin() failed, but ignored");
    569 
    570    aW = htmlElement->OffsetWidth();
    571    aH = htmlElement->OffsetHeight();
    572 
    573    aBorderLeft = 0;
    574    aBorderTop = 0;
    575    aMarginLeft = 0;
    576    aMarginTop = 0;
    577  }
    578  return NS_OK;
    579 }
    580 
    581 nsresult HTMLEditor::SetAnonymousElementPositionWithoutTransaction(
    582    nsStyledElement& aStyledElement, int32_t aX, int32_t aY) {
    583  nsresult rv;
    584  rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
    585      *this, aStyledElement, *nsGkAtoms::left, aX);
    586  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    587    NS_WARNING(
    588        "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
    589        "destroyed the editor");
    590    return NS_ERROR_EDITOR_DESTROYED;
    591  }
    592  NS_WARNING_ASSERTION(
    593      NS_SUCCEEDED(rv),
    594      "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
    595      "failed, but ignored");
    596  rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
    597      *this, aStyledElement, *nsGkAtoms::top, aY);
    598  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    599    NS_WARNING(
    600        "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
    601        "destroyed the editor");
    602    return NS_ERROR_EDITOR_DESTROYED;
    603  }
    604  NS_WARNING_ASSERTION(
    605      NS_SUCCEEDED(rv),
    606      "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
    607      "failed, but ignored");
    608  return NS_OK;
    609 }
    610 
    611 }  // namespace mozilla