tor-browser

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

HTMLInlineTableEditor.cpp (19036B)


      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 "mozilla/HTMLEditor.h"
      6 
      7 #include "EditorEventListener.h"
      8 #include "HTMLEditUtils.h"
      9 #include "mozilla/PresShell.h"
     10 #include "mozilla/dom/Element.h"
     11 #include "nsAString.h"
     12 #include "nsCOMPtr.h"
     13 #include "nsDebug.h"
     14 #include "nsError.h"
     15 #include "nsGenericHTMLElement.h"
     16 #include "nsIContent.h"
     17 #include "nsLiteralString.h"
     18 #include "nsReadableUtils.h"
     19 #include "nsString.h"
     20 #include "nscore.h"
     21 
     22 namespace mozilla {
     23 
     24 NS_IMETHODIMP HTMLEditor::SetInlineTableEditingEnabled(bool aIsEnabled) {
     25  EnableInlineTableEditor(aIsEnabled);
     26  return NS_OK;
     27 }
     28 
     29 NS_IMETHODIMP HTMLEditor::GetInlineTableEditingEnabled(bool* aIsEnabled) {
     30  *aIsEnabled = IsInlineTableEditorEnabled();
     31  return NS_OK;
     32 }
     33 
     34 NS_IMETHODIMP HTMLEditor::GetIsInlineTableEditingActive(bool* aIsActive) {
     35  MOZ_ASSERT(aIsActive);
     36  *aIsActive = !!mInlineEditedCell;
     37  return NS_OK;
     38 }
     39 
     40 nsresult HTMLEditor::ShowInlineTableEditingUIInternal(Element& aCellElement) {
     41  if (NS_WARN_IF(!HTMLEditUtils::IsTableCellElement(aCellElement))) {
     42    return NS_OK;
     43  }
     44 
     45  const RefPtr<Element> editingHost = ComputeEditingHost();
     46  if (NS_WARN_IF(!editingHost) ||
     47      NS_WARN_IF(!aCellElement.IsInclusiveDescendantOf(editingHost))) {
     48    return NS_ERROR_FAILURE;
     49  }
     50 
     51  if (NS_WARN_IF(mInlineEditedCell)) {
     52    return NS_ERROR_FAILURE;
     53  }
     54 
     55  mInlineEditedCell = &aCellElement;
     56 
     57  // the resizers and the shadow will be anonymous children of the body
     58  RefPtr<Element> rootElement = GetRoot();
     59  if (NS_WARN_IF(!rootElement)) {
     60    return NS_ERROR_FAILURE;
     61  }
     62 
     63  do {
     64    // The buttons of inline table editor will be children of the <body>
     65    // element.  Creating the anonymous elements may cause calling
     66    // HideInlineTableEditingUIInternal() via a mutation event listener.
     67    // So, we should store new button to a local variable, then, check:
     68    //   - whether creating a button is already set to the member or not
     69    //   - whether already created buttons are changed to another set
     70    // If creating the buttons are canceled, we hit the latter check.
     71    // If buttons for another table are created during this, we hit the latter
     72    // check too.
     73    // If buttons are just created again for same element, we hit the former
     74    // check.
     75    ManualNACPtr addColumnBeforeButton = CreateAnonymousElement(
     76        nsGkAtoms::a, *rootElement, u"mozTableAddColumnBefore"_ns, false);
     77    if (NS_WARN_IF(!addColumnBeforeButton)) {
     78      NS_WARNING(
     79          "HTMLEditor::CreateAnonymousElement(nsGkAtoms::a, "
     80          "mozTableAddColumnBefore) failed");
     81      break;  // Hide unnecessary buttons created above.
     82    }
     83    if (NS_WARN_IF(mAddColumnBeforeButton) ||
     84        NS_WARN_IF(mInlineEditedCell != &aCellElement)) {
     85      return NS_ERROR_FAILURE;  // Don't hide another set of buttons.
     86    }
     87    mAddColumnBeforeButton = std::move(addColumnBeforeButton);
     88 
     89    ManualNACPtr removeColumnButton = CreateAnonymousElement(
     90        nsGkAtoms::a, *rootElement, u"mozTableRemoveColumn"_ns, false);
     91    if (!removeColumnButton) {
     92      NS_WARNING(
     93          "HTMLEditor::CreateAnonymousElement(nsGkAtoms::a, "
     94          "mozTableRemoveColumn) failed");
     95      break;
     96    }
     97    if (NS_WARN_IF(mRemoveColumnButton) ||
     98        NS_WARN_IF(mInlineEditedCell != &aCellElement)) {
     99      return NS_ERROR_FAILURE;
    100    }
    101    mRemoveColumnButton = std::move(removeColumnButton);
    102 
    103    ManualNACPtr addColumnAfterButton = CreateAnonymousElement(
    104        nsGkAtoms::a, *rootElement, u"mozTableAddColumnAfter"_ns, false);
    105    if (!addColumnAfterButton) {
    106      NS_WARNING(
    107          "HTMLEditor::CreateAnonymousElement(nsGkAtoms::a, "
    108          "mozTableAddColumnAfter) failed");
    109      break;
    110    }
    111    if (NS_WARN_IF(mAddColumnAfterButton) ||
    112        NS_WARN_IF(mInlineEditedCell != &aCellElement)) {
    113      return NS_ERROR_FAILURE;
    114    }
    115    mAddColumnAfterButton = std::move(addColumnAfterButton);
    116 
    117    ManualNACPtr addRowBeforeButton = CreateAnonymousElement(
    118        nsGkAtoms::a, *rootElement, u"mozTableAddRowBefore"_ns, false);
    119    if (!addRowBeforeButton) {
    120      NS_WARNING(
    121          "HTMLEditor::CreateAnonymousElement(nsGkAtoms::a, "
    122          "mozTableAddRowBefore) failed");
    123      break;
    124    }
    125    if (NS_WARN_IF(mAddRowBeforeButton) ||
    126        NS_WARN_IF(mInlineEditedCell != &aCellElement)) {
    127      return NS_ERROR_FAILURE;
    128    }
    129    mAddRowBeforeButton = std::move(addRowBeforeButton);
    130 
    131    ManualNACPtr removeRowButton = CreateAnonymousElement(
    132        nsGkAtoms::a, *rootElement, u"mozTableRemoveRow"_ns, false);
    133    if (!removeRowButton) {
    134      NS_WARNING(
    135          "HTMLEditor::CreateAnonymousElement(nsGkAtoms::a, "
    136          "mozTableRemoveRow) failed");
    137      break;
    138    }
    139    if (NS_WARN_IF(mRemoveRowButton) ||
    140        NS_WARN_IF(mInlineEditedCell != &aCellElement)) {
    141      return NS_ERROR_FAILURE;
    142    }
    143    mRemoveRowButton = std::move(removeRowButton);
    144 
    145    ManualNACPtr addRowAfterButton = CreateAnonymousElement(
    146        nsGkAtoms::a, *rootElement, u"mozTableAddRowAfter"_ns, false);
    147    if (!addRowAfterButton) {
    148      NS_WARNING(
    149          "HTMLEditor::CreateAnonymousElement(nsGkAtoms::a, "
    150          "mozTableAddRowAfter) failed");
    151      break;
    152    }
    153    if (NS_WARN_IF(mAddRowAfterButton) ||
    154        NS_WARN_IF(mInlineEditedCell != &aCellElement)) {
    155      return NS_ERROR_FAILURE;
    156    }
    157    mAddRowAfterButton = std::move(addRowAfterButton);
    158 
    159    AddPointerClickListener(mAddColumnBeforeButton);
    160    AddPointerClickListener(mRemoveColumnButton);
    161    AddPointerClickListener(mAddColumnAfterButton);
    162    AddPointerClickListener(mAddRowBeforeButton);
    163    AddPointerClickListener(mRemoveRowButton);
    164    AddPointerClickListener(mAddRowAfterButton);
    165 
    166    nsresult rv = RefreshInlineTableEditingUIInternal();
    167    NS_WARNING_ASSERTION(
    168        NS_SUCCEEDED(rv),
    169        "HTMLEditor::RefreshInlineTableEditingUIInternal() failed");
    170    return rv;
    171  } while (true);
    172 
    173  HideInlineTableEditingUIInternal();
    174  return NS_ERROR_FAILURE;
    175 }
    176 
    177 void HTMLEditor::HideInlineTableEditingUIInternal() {
    178  mInlineEditedCell = nullptr;
    179 
    180  RemovePointerClickListener(mAddColumnBeforeButton);
    181  RemovePointerClickListener(mRemoveColumnButton);
    182  RemovePointerClickListener(mAddColumnAfterButton);
    183  RemovePointerClickListener(mAddRowBeforeButton);
    184  RemovePointerClickListener(mRemoveRowButton);
    185  RemovePointerClickListener(mAddRowAfterButton);
    186 
    187  // get the presshell's document observer interface.
    188  RefPtr<PresShell> presShell = GetPresShell();
    189  // We allow the pres shell to be null; when it is, we presume there
    190  // are no document observers to notify, but we still want to
    191  // UnbindFromTree.
    192 
    193  // Calling DeleteRefToAnonymousNode() may cause showing the UI again.
    194  // Therefore, we should forget all anonymous contents first.
    195  // Otherwise, we could leak the old content because of overwritten by
    196  // ShowInlineTableEditingUIInternal().
    197  ManualNACPtr addColumnBeforeButton(std::move(mAddColumnBeforeButton));
    198  ManualNACPtr removeColumnButton(std::move(mRemoveColumnButton));
    199  ManualNACPtr addColumnAfterButton(std::move(mAddColumnAfterButton));
    200  ManualNACPtr addRowBeforeButton(std::move(mAddRowBeforeButton));
    201  ManualNACPtr removeRowButton(std::move(mRemoveRowButton));
    202  ManualNACPtr addRowAfterButton(std::move(mAddRowAfterButton));
    203 
    204  DeleteRefToAnonymousNode(std::move(addColumnBeforeButton), presShell);
    205  DeleteRefToAnonymousNode(std::move(removeColumnButton), presShell);
    206  DeleteRefToAnonymousNode(std::move(addColumnAfterButton), presShell);
    207  DeleteRefToAnonymousNode(std::move(addRowBeforeButton), presShell);
    208  DeleteRefToAnonymousNode(std::move(removeRowButton), presShell);
    209  DeleteRefToAnonymousNode(std::move(addRowAfterButton), presShell);
    210 }
    211 
    212 nsresult HTMLEditor::DoInlineTableEditingAction(const Element& aElement) {
    213  nsAutoString classList;
    214  aElement.GetAttr(nsGkAtoms::_class, classList);
    215 
    216  if (!StringBeginsWith(classList, u"mozTable"_ns)) {
    217    return NS_OK;
    218  }
    219 
    220  if (NS_WARN_IF(!mInlineEditedCell) ||
    221      NS_WARN_IF(!mInlineEditedCell->IsInComposedDoc()) ||
    222      NS_WARN_IF(!mInlineEditedCell->GetParent()) ||
    223      NS_WARN_IF(
    224          !HTMLEditUtils::IsTableRowElement(*mInlineEditedCell->GetParent()))) {
    225    return NS_ERROR_NOT_AVAILABLE;
    226  }
    227 
    228  AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
    229  if (NS_WARN_IF(!editActionData.CanHandle())) {
    230    return NS_ERROR_NOT_INITIALIZED;
    231  }
    232 
    233  RefPtr<Element> tableElement =
    234      HTMLEditUtils::GetClosestAncestorTableElement(*mInlineEditedCell);
    235  if (!tableElement) {
    236    NS_WARNING("HTMLEditor::GetClosestAncestorTableElement() returned nullptr");
    237    return NS_ERROR_FAILURE;
    238  }
    239  int32_t rowCount, colCount;
    240  nsresult rv = GetTableSize(tableElement, &rowCount, &colCount);
    241  if (NS_FAILED(rv)) {
    242    NS_WARNING("HTMLEditor::GetTableSize() failed");
    243    return EditorBase::ToGenericNSResult(rv);
    244  }
    245 
    246  bool hideUI = false;
    247  bool hideResizersWithInlineTableUI = (mResizedObject == tableElement);
    248 
    249  if (classList.EqualsLiteral("mozTableAddColumnBefore")) {
    250    AutoEditActionDataSetter editActionData(*this,
    251                                            EditAction::eInsertTableColumn);
    252    nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    253    if (NS_FAILED(rv)) {
    254      NS_WARNING_ASSERTION(
    255          rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    256          "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    257      return EditorBase::ToGenericNSResult(rv);
    258    }
    259 
    260    DebugOnly<nsresult> rvIgnored =
    261        InsertTableColumnsWithTransaction(EditorDOMPoint(mInlineEditedCell), 1);
    262    NS_WARNING_ASSERTION(
    263        NS_SUCCEEDED(rvIgnored),
    264        "HTMLEditor::InsertTableColumnsWithTransaction("
    265        "EditorDOMPoint(mInlineEditedCell), 1) failed, but ignored");
    266  } else if (classList.EqualsLiteral("mozTableAddColumnAfter")) {
    267    AutoEditActionDataSetter editActionData(*this,
    268                                            EditAction::eInsertTableColumn);
    269    nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    270    if (NS_FAILED(rv)) {
    271      NS_WARNING_ASSERTION(
    272          rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    273          "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    274      return EditorBase::ToGenericNSResult(rv);
    275    }
    276    Element* nextCellElement = nullptr;
    277    for (nsIContent* maybeNextCellElement = mInlineEditedCell->GetNextSibling();
    278         maybeNextCellElement;
    279         maybeNextCellElement = maybeNextCellElement->GetNextSibling()) {
    280      if (HTMLEditUtils::IsTableCellElement(*maybeNextCellElement)) {
    281        nextCellElement = maybeNextCellElement->AsElement();
    282        break;
    283      }
    284    }
    285    DebugOnly<nsresult> rvIgnored = InsertTableColumnsWithTransaction(
    286        nextCellElement
    287            ? EditorDOMPoint(nextCellElement)
    288            : EditorDOMPoint::AtEndOf(*mInlineEditedCell->GetParentElement()),
    289        1);
    290    NS_WARNING_ASSERTION(
    291        NS_SUCCEEDED(rvIgnored),
    292        "HTMLEditor::InsertTableColumnsWithTransaction("
    293        "EditorDOMPoint(nextCellElement), 1) failed, but ignored");
    294  } else if (classList.EqualsLiteral("mozTableAddRowBefore")) {
    295    AutoEditActionDataSetter editActionData(*this,
    296                                            EditAction::eInsertTableRowElement);
    297    nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    298    if (NS_FAILED(rv)) {
    299      NS_WARNING_ASSERTION(
    300          rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    301          "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    302      return EditorBase::ToGenericNSResult(rv);
    303    }
    304    OwningNonNull<Element> targetCellElement(*mInlineEditedCell);
    305    DebugOnly<nsresult> rvIgnored = InsertTableRowsWithTransaction(
    306        targetCellElement, 1, InsertPosition::eBeforeSelectedCell);
    307    NS_WARNING_ASSERTION(
    308        NS_SUCCEEDED(rvIgnored),
    309        "HTMLEditor::InsertTableRowsWithTransaction(targetCellElement, 1, "
    310        "InsertPosition::eBeforeSelectedCell) failed, but ignored");
    311  } else if (classList.EqualsLiteral("mozTableAddRowAfter")) {
    312    AutoEditActionDataSetter editActionData(*this,
    313                                            EditAction::eInsertTableRowElement);
    314    nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    315    if (NS_FAILED(rv)) {
    316      NS_WARNING_ASSERTION(
    317          rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    318          "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    319      return EditorBase::ToGenericNSResult(rv);
    320    }
    321    OwningNonNull<Element> targetCellElement(*mInlineEditedCell);
    322    DebugOnly<nsresult> rvIgnored = InsertTableRowsWithTransaction(
    323        targetCellElement, 1, InsertPosition::eAfterSelectedCell);
    324    NS_WARNING_ASSERTION(
    325        NS_SUCCEEDED(rvIgnored),
    326        "HTMLEditor::InsertTableRowsWithTransaction(targetCellElement, 1, "
    327        "InsertPosition::eAfterSelectedCell) failed, but ignored");
    328  } else if (classList.EqualsLiteral("mozTableRemoveColumn")) {
    329    AutoEditActionDataSetter editActionData(*this,
    330                                            EditAction::eRemoveTableColumn);
    331    nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    332    if (NS_FAILED(rv)) {
    333      NS_WARNING_ASSERTION(
    334          rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    335          "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    336      return EditorBase::ToGenericNSResult(rv);
    337    }
    338    DebugOnly<nsresult> rvIgnored =
    339        DeleteSelectedTableColumnsWithTransaction(1);
    340    NS_WARNING_ASSERTION(
    341        NS_SUCCEEDED(rvIgnored),
    342        "HTMLEditor::DeleteSelectedTableColumnsWithTransaction(1) failed, but "
    343        "ignored");
    344    hideUI = (colCount == 1);
    345  } else if (classList.EqualsLiteral("mozTableRemoveRow")) {
    346    AutoEditActionDataSetter editActionData(*this,
    347                                            EditAction::eRemoveTableRowElement);
    348    nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    349    if (NS_FAILED(rv)) {
    350      NS_WARNING_ASSERTION(
    351          rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    352          "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    353      return EditorBase::ToGenericNSResult(rv);
    354    }
    355    DebugOnly<nsresult> rvIgnored = DeleteSelectedTableRowsWithTransaction(1);
    356    NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    357                         "HTMLEditor::DeleteSelectedTableRowsWithTransaction(1)"
    358                         " failed, but ignored");
    359    hideUI = (rowCount == 1);
    360  } else {
    361    return NS_OK;
    362  }
    363 
    364  if (NS_WARN_IF(Destroyed())) {
    365    return NS_OK;
    366  }
    367 
    368  if (hideUI) {
    369    HideInlineTableEditingUIInternal();
    370    if (hideResizersWithInlineTableUI) {
    371      DebugOnly<nsresult> rvIgnored = HideResizersInternal();
    372      NS_WARNING_ASSERTION(
    373          NS_SUCCEEDED(rvIgnored),
    374          "HTMLEditor::HideResizersInternal() failed, but ignored");
    375    }
    376  }
    377 
    378  return NS_OK;
    379 }
    380 
    381 void HTMLEditor::AddPointerClickListener(Element* aElement) {
    382  if (NS_WARN_IF(!aElement)) {
    383    return;
    384  }
    385  DebugOnly<nsresult> rvIgnored =
    386      aElement->AddEventListener(u"click"_ns, mEventListener, true);
    387  NS_WARNING_ASSERTION(
    388      NS_SUCCEEDED(rvIgnored),
    389      "EventTarget::AddEventListener(click) failed, but ignored");
    390 }
    391 
    392 void HTMLEditor::RemovePointerClickListener(Element* aElement) {
    393  if (NS_WARN_IF(!aElement)) {
    394    return;
    395  }
    396  aElement->RemoveEventListener(u"click"_ns, mEventListener, true);
    397 }
    398 
    399 nsresult HTMLEditor::RefreshInlineTableEditingUIInternal() {
    400  MOZ_ASSERT(IsEditActionDataAvailable());
    401 
    402  if (!mInlineEditedCell) {
    403    return NS_OK;
    404  }
    405 
    406  RefPtr<nsGenericHTMLElement> inlineEditingCellElement =
    407      nsGenericHTMLElement::FromNode(mInlineEditedCell);
    408  if (NS_WARN_IF(!inlineEditingCellElement)) {
    409    return NS_ERROR_FAILURE;
    410  }
    411 
    412  int32_t cellX = 0, cellY = 0;
    413  DebugOnly<nsresult> rvIgnored =
    414      GetElementOrigin(*mInlineEditedCell, cellX, cellY);
    415  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    416                       "HTMLEditor::GetElementOrigin() failed, but ignored");
    417 
    418  int32_t cellWidth = inlineEditingCellElement->OffsetWidth();
    419  int32_t cellHeight = inlineEditingCellElement->OffsetHeight();
    420 
    421  int32_t centerOfCellX = cellX + cellWidth / 2;
    422  int32_t centerOfCellY = cellY + cellHeight / 2;
    423 
    424  RefPtr<Element> tableElement =
    425      HTMLEditUtils::GetClosestAncestorTableElement(*mInlineEditedCell);
    426  if (!tableElement) {
    427    NS_WARNING("HTMLEditor::GetClosestAncestorTableElement() returned nullptr");
    428    return NS_ERROR_FAILURE;
    429  }
    430  int32_t rowCount = 0, colCount = 0;
    431  nsresult rv = GetTableSize(tableElement, &rowCount, &colCount);
    432  if (NS_FAILED(rv)) {
    433    NS_WARNING("HTMLEditor::GetTableSize() failed");
    434    return rv;
    435  }
    436 
    437  auto setInlineTableEditButtonPosition =
    438      [this](ManualNACPtr& aButtonElement, int32_t aNewX, int32_t aNewY)
    439          MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION -> nsresult {
    440    RefPtr<nsStyledElement> buttonStyledElement =
    441        nsStyledElement::FromNodeOrNull(aButtonElement.get());
    442    if (!buttonStyledElement) {
    443      return NS_OK;
    444    }
    445    nsresult rv = SetAnonymousElementPositionWithoutTransaction(
    446        *buttonStyledElement, aNewX, aNewY);
    447    if (NS_FAILED(rv)) {
    448      NS_WARNING(
    449          "HTMLEditor::SetAnonymousElementPositionWithoutTransaction() "
    450          "failed");
    451      return rv;
    452    }
    453    return NS_WARN_IF(buttonStyledElement != aButtonElement.get())
    454               ? NS_ERROR_FAILURE
    455               : NS_OK;
    456  };
    457 
    458  // clang-format off
    459  rv = setInlineTableEditButtonPosition(mAddColumnBeforeButton,
    460                                        centerOfCellX - 10, cellY - 7);
    461  if (NS_FAILED(rv)) {
    462    NS_WARNING("Failed to move button for add-column-before");
    463    return rv;
    464  }
    465  rv = setInlineTableEditButtonPosition(mRemoveColumnButton,
    466                                        centerOfCellX - 4, cellY - 7);
    467  if (NS_FAILED(rv)) {
    468    NS_WARNING("Failed to move button for remove-column");
    469    return rv;
    470  }
    471  rv = setInlineTableEditButtonPosition(mAddColumnAfterButton,
    472                                        centerOfCellX + 6, cellY - 7);
    473  if (NS_FAILED(rv)) {
    474    NS_WARNING("Failed to move button for add-column-after");
    475    return rv;
    476  }
    477  rv = setInlineTableEditButtonPosition(mAddRowBeforeButton,
    478                                        cellX - 7, centerOfCellY - 10);
    479  if (NS_FAILED(rv)) {
    480    NS_WARNING("Failed to move button for add-row-before");
    481    return rv;
    482  }
    483  rv = setInlineTableEditButtonPosition(mRemoveRowButton,
    484                                        cellX - 7, centerOfCellY - 4);
    485  if (NS_FAILED(rv)) {
    486    NS_WARNING("Failed to move button for remove-row");
    487    return rv;
    488  }
    489  rv = setInlineTableEditButtonPosition(mAddRowAfterButton,
    490                                        cellX - 7, centerOfCellY + 6);
    491  if (NS_FAILED(rv)) {
    492    NS_WARNING("Failed to move button for add-row-after");
    493    return rv;
    494  }
    495  // clang-format on
    496 
    497  return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : NS_OK;
    498 }
    499 
    500 }  // namespace mozilla