tor-browser

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

EditorBase.h (124008B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef mozilla_EditorBase_h
      7 #define mozilla_EditorBase_h
      8 
      9 #include "mozilla/intl/BidiEmbeddingLevel.h"
     10 #include "mozilla/Assertions.h"      // for MOZ_ASSERT, etc.
     11 #include "mozilla/EditAction.h"      // for EditAction and EditSubAction
     12 #include "mozilla/EditorDOMPoint.h"  // for EditorDOMPoint
     13 #include "mozilla/EditorForwards.h"
     14 #include "mozilla/EventForwards.h"       // for InputEventTargetRanges
     15 #include "mozilla/Likely.h"              // for MOZ_UNLIKELY, MOZ_LIKELY
     16 #include "mozilla/Maybe.h"               // for Maybe
     17 #include "mozilla/OwningNonNull.h"       // for OwningNonNull
     18 #include "mozilla/PendingStyles.h"       // for PendingStyle, PendingStyleCache
     19 #include "mozilla/RangeBoundary.h"       // for RawRangeBoundary, RangeBoundary
     20 #include "mozilla/SelectionState.h"      // for RangeUpdater, etc.
     21 #include "mozilla/StyleSheet.h"          // for StyleSheet
     22 #include "mozilla/TransactionManager.h"  // for TransactionManager
     23 #include "mozilla/WeakPtr.h"             // for WeakPtr
     24 #include "mozilla/dom/DataTransfer.h"    // for dom::DataTransfer
     25 #include "mozilla/dom/HTMLBRElement.h"   // for dom::HTMLBRElement
     26 #include "mozilla/dom/Selection.h"
     27 #include "mozilla/dom/Text.h"
     28 #include "nsAtom.h"    // for nsAtom, nsStaticAtom
     29 #include "nsCOMPtr.h"  // for already_AddRefed, nsCOMPtr
     30 #include "nsCycleCollectionParticipant.h"
     31 #include "nsGkAtoms.h"
     32 #include "nsIClipboard.h"            // for nsIClipboard::ClipboardType
     33 #include "nsIContentInlines.h"       // for nsINode::IsEditable()
     34 #include "nsIEditor.h"               // for nsIEditor, etc.
     35 #include "nsISelectionController.h"  // for nsISelectionController constants
     36 #include "nsISelectionListener.h"    // for nsISelectionListener
     37 #include "nsISupportsImpl.h"         // for EditorBase::Release, etc.
     38 #include "nsIWeakReferenceUtils.h"   // for nsWeakPtr
     39 #include "nsLiteralString.h"         // for NS_LITERAL_STRING
     40 #include "nsPIDOMWindow.h"           // for nsPIDOMWindowInner, etc.
     41 #include "nsString.h"                // for nsCString
     42 #include "nsTArray.h"                // for nsTArray and AutoTArray
     43 #include "nsWeakReference.h"         // for nsSupportsWeakReference
     44 #include "nscore.h"                  // for nsresult, nsAString, etc.
     45 
     46 #include <tuple>  // for std::tuple
     47 
     48 class mozInlineSpellChecker;
     49 class nsAtom;
     50 class nsCaret;
     51 class nsIContent;
     52 class nsIDocumentEncoder;
     53 class nsIDocumentStateListener;
     54 class nsIEditActionListener;
     55 class nsINode;
     56 class nsIPrincipal;
     57 class nsISupports;
     58 class nsITransferable;
     59 class nsITransaction;
     60 class nsIWidget;
     61 class nsRange;
     62 
     63 namespace mozilla {
     64 class AlignStateAtSelection;
     65 class AutoTransactionsConserveSelection;
     66 class AutoUpdateViewBatch;
     67 class ErrorResult;
     68 class IMEContentObserver;
     69 class ListElementSelectionState;
     70 class ListItemElementSelectionState;
     71 class ParagraphStateAtSelection;
     72 class PresShell;
     73 class TextComposition;
     74 class TextInputListener;
     75 class TextServicesDocument;
     76 namespace dom {
     77 class AbstractRange;
     78 class DataTransfer;
     79 class Document;
     80 class DragEvent;
     81 class Element;
     82 class EventTarget;
     83 class HTMLBRElement;
     84 }  // namespace dom
     85 
     86 namespace widget {
     87 struct IMEState;
     88 }  // namespace widget
     89 
     90 /**
     91 * Implementation of an editor object.  it will be the controller/focal point
     92 * for the main editor services. i.e. the GUIManager, publishing, transaction
     93 * manager, event interfaces. the idea for the event interfaces is to have them
     94 * delegate the actual commands to the editor independent of the XPFE
     95 * implementation.
     96 */
     97 class EditorBase : public nsIEditor,
     98                   public nsISelectionListener,
     99                   public nsSupportsWeakReference {
    100 public:
    101  /****************************************************************************
    102   * NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other
    103   *       classes under libeditor except EditorEventListener and
    104   *       HTMLEditorEventListener because each public method which may fire
    105   *       eEditorInput event will need to instantiate new stack class for
    106   *       managing input type value of eEditorInput and cache some objects
    107   *       for smarter handling.  In other words, when you add new root
    108   *       method to edit the DOM tree, you can make your new method public.
    109   ****************************************************************************/
    110 
    111  using DataTransfer = dom::DataTransfer;
    112  using Document = dom::Document;
    113  using Element = dom::Element;
    114  using InterlinePosition = dom::Selection::InterlinePosition;
    115  using Selection = dom::Selection;
    116  using Text = dom::Text;
    117 
    118  enum class EditorType { Text, HTML };
    119 
    120  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    121  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
    122 
    123  // nsIEditor methods
    124  NS_DECL_NSIEDITOR
    125 
    126  // nsISelectionListener method
    127  NS_DECL_NSISELECTIONLISTENER
    128 
    129  /**
    130   * The default constructor. This should suffice. the setting of the
    131   * interfaces is done after the construction of the editor class.
    132   */
    133  explicit EditorBase(EditorType aEditorType);
    134 
    135  [[nodiscard]] bool IsInitialized() const {
    136    return mDocument && mDidPostCreate;
    137  }
    138  [[nodiscard]] bool IsBeingInitialized() const {
    139    return mDocument && !mDidPostCreate;
    140  }
    141  [[nodiscard]] bool Destroyed() const { return mDidPreDestroy; }
    142 
    143  Document* GetDocument() const { return mDocument; }
    144  nsPIDOMWindowOuter* GetWindow() const;
    145  nsPIDOMWindowInner* GetInnerWindow() const;
    146 
    147  /**
    148   * MaybeNodeRemovalsObservedByDevTools() returns true when the mutations in
    149   * the document is observed by DevTools.
    150   *
    151   * @return                    true if the editor is an HTMLEditor instance
    152   *                            and the mutations in the document is observed by
    153   *                            DevTools.
    154   */
    155  [[nodiscard]] bool MaybeNodeRemovalsObservedByDevTools() const;
    156 
    157  /**
    158   * MayHaveBeforeInputEventListenersForTelemetry() returns true when the
    159   * window may have or have had one or more `beforeinput` event listeners.
    160   * Note that this may return false even if there is a `beforeinput`.
    161   * See nsPIDOMWindowInner::HasBeforeInputEventListenersForTelemetry()'s
    162   * comment for the detail.
    163   */
    164  bool MayHaveBeforeInputEventListenersForTelemetry() const {
    165    if (const nsPIDOMWindowInner* window = GetInnerWindow()) {
    166      return window->HasBeforeInputEventListenersForTelemetry();
    167    }
    168    return false;
    169  }
    170 
    171  /**
    172   * MutationObserverHasObservedNodeForTelemetry() returns true when a node in
    173   * the window may have been observed by the web apps with a mutation observer
    174   * (i.e., `MutationObserver.observe()` called by chrome script and addon's
    175   * script does not make this returns true).
    176   * Note that this may return false even if there is a node observed by
    177   * a MutationObserver.  See
    178   * nsPIDOMWindowInner::MutationObserverHasObservedNodeForTelemetry()'s comment
    179   * for the detail.
    180   */
    181  bool MutationObserverHasObservedNodeForTelemetry() const {
    182    if (const nsPIDOMWindowInner* window = GetInnerWindow()) {
    183      return window->MutationObserverHasObservedNodeForTelemetry();
    184    }
    185    return false;
    186  }
    187 
    188  /**
    189   * This checks whether the call with aPrincipal should or should not be
    190   * treated as user input.
    191   */
    192  [[nodiscard]] static bool TreatAsUserInput(nsIPrincipal* aPrincipal);
    193 
    194  PresShell* GetPresShell() const;
    195  nsPresContext* GetPresContext() const;
    196  already_AddRefed<nsCaret> GetCaret() const;
    197 
    198  already_AddRefed<nsIWidget> GetWidget() const;
    199 
    200  nsISelectionController* GetSelectionController() const;
    201 
    202  nsresult GetSelection(SelectionType aSelectionType,
    203                        Selection** aSelection) const;
    204 
    205  Selection* GetSelection(
    206      SelectionType aSelectionType = SelectionType::eNormal) const {
    207    if (aSelectionType == SelectionType::eNormal &&
    208        IsEditActionDataAvailable()) {
    209      return &SelectionRef();
    210    }
    211    nsISelectionController* sc = GetSelectionController();
    212    if (!sc) {
    213      return nullptr;
    214    }
    215    Selection* selection = sc->GetSelection(ToRawSelectionType(aSelectionType));
    216    return selection;
    217  }
    218 
    219  /**
    220   * @return Ancestor limiter of normal selection
    221   */
    222  [[nodiscard]] nsIContent* GetSelectionAncestorLimiter() const {
    223    Selection* selection = GetSelection(SelectionType::eNormal);
    224    return selection ? selection->GetAncestorLimiter() : nullptr;
    225  }
    226 
    227  /**
    228   * Create a DataTransfer object that can be shared between the paste event
    229   * and pasting into a DOM element.
    230   */
    231  already_AddRefed<DataTransfer> CreateDataTransferForPaste(
    232      EventMessage aEventMessage,
    233      nsIClipboard::ClipboardType aClipboardType) const;
    234 
    235  /**
    236   * Fast non-refcounting editor root element accessor
    237   */
    238  Element* GetRoot() const { return mRootElement; }
    239 
    240  /**
    241   * Likewise, but gets the text control element instead of the root for
    242   * plaintext editors.
    243   */
    244  Element* GetExposedRoot() const;
    245 
    246  /**
    247   * Set or unset TextInputListener.  If setting non-nullptr when the editor
    248   * already has a TextInputListener, this will crash in debug build.
    249   */
    250  void SetTextInputListener(TextInputListener* aTextInputListener);
    251 
    252  /**
    253   * Set or unset IMEContentObserver.  If setting non-nullptr when the editor
    254   * already has an IMEContentObserver, this will crash in debug build.
    255   */
    256  void SetIMEContentObserver(IMEContentObserver* aIMEContentObserver);
    257 
    258  /**
    259   * Returns current composition.
    260   */
    261  TextComposition* GetComposition() const;
    262 
    263  /**
    264   * Get preferred IME status of current widget.
    265   */
    266  [[nodiscard]] virtual Result<widget::IMEState, nsresult>
    267  GetPreferredIMEState() const = 0;
    268 
    269  /**
    270   * Returns true if there is composition string and not fixed.
    271   */
    272  bool IsIMEComposing() const;
    273 
    274  /**
    275   * Commit composition if there is.
    276   * Note that when there is a composition, this requests to commit composition
    277   * to native IME.  Therefore, when there is composition, this can do anything.
    278   * For example, the editor instance, the widget or the process itself may
    279   * be destroyed.
    280   */
    281  nsresult CommitComposition();
    282 
    283  /**
    284   * ToggleTextDirection() toggles text-direction of the root element.
    285   *
    286   * @param aPrincipal          Set subject principal if it may be called by
    287   *                            JS.  If set to nullptr, will be treated as
    288   *                            called by system.
    289   */
    290  MOZ_CAN_RUN_SCRIPT nsresult
    291  ToggleTextDirectionAsAction(nsIPrincipal* aPrincipal = nullptr);
    292 
    293  /**
    294   * SwitchTextDirectionTo() sets the text-direction of the root element to
    295   * LTR or RTL.
    296   */
    297  enum class TextDirection {
    298    eLTR,
    299    eRTL,
    300  };
    301  MOZ_CAN_RUN_SCRIPT void SwitchTextDirectionTo(TextDirection aTextDirection);
    302 
    303  /**
    304   * Finalizes selection and caret for the editor.
    305   */
    306  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult FinalizeSelection();
    307 
    308  /**
    309   * Returns true if selection is in an editable element and both the range
    310   * start and the range end are editable.  E.g., even if the selection range
    311   * includes non-editable elements, returns true when one of common ancestors
    312   * of the range start and the range end is editable.  Otherwise, false.
    313   */
    314  bool IsSelectionEditable();
    315 
    316  /**
    317   * Returns number of undo or redo items.
    318   */
    319  size_t NumberOfUndoItems() const {
    320    return mTransactionManager ? mTransactionManager->NumberOfUndoItems() : 0;
    321  }
    322  size_t NumberOfRedoItems() const {
    323    return mTransactionManager ? mTransactionManager->NumberOfRedoItems() : 0;
    324  }
    325 
    326  /**
    327   * Returns number of maximum undo/redo transactions.
    328   */
    329  int32_t NumberOfMaximumTransactions() const {
    330    return mTransactionManager
    331               ? mTransactionManager->NumberOfMaximumTransactions()
    332               : 0;
    333  }
    334 
    335  /**
    336   * Returns true if this editor can store transactions for undo/redo.
    337   */
    338  bool IsUndoRedoEnabled() const {
    339    return mTransactionManager &&
    340           mTransactionManager->NumberOfMaximumTransactions();
    341  }
    342 
    343  /**
    344   * Return true if it's possible to undo/redo right now.
    345   */
    346  bool CanUndo() const {
    347    return IsUndoRedoEnabled() && NumberOfUndoItems() > 0;
    348  }
    349  bool CanRedo() const {
    350    return IsUndoRedoEnabled() && NumberOfRedoItems() > 0;
    351  }
    352 
    353  /**
    354   * Enables or disables undo/redo feature.  Returns true if it succeeded,
    355   * otherwise, e.g., we're undoing or redoing, returns false.
    356   */
    357  bool EnableUndoRedo(int32_t aMaxTransactionCount = -1) {
    358    if (!mTransactionManager) {
    359      mTransactionManager = new TransactionManager();
    360    }
    361    return mTransactionManager->EnableUndoRedo(aMaxTransactionCount);
    362  }
    363  bool DisableUndoRedo() {
    364    if (!mTransactionManager) {
    365      return true;
    366    }
    367    return mTransactionManager->DisableUndoRedo();
    368  }
    369  bool ClearUndoRedo() {
    370    if (!mTransactionManager) {
    371      return true;
    372    }
    373    return mTransactionManager->ClearUndoRedo();
    374  }
    375 
    376  /**
    377   * See Document::AreClipboardCommandsUnconditionallyEnabled.
    378   */
    379  bool AreClipboardCommandsUnconditionallyEnabled() const;
    380 
    381  /**
    382   * IsCutCommandEnabled() returns whether cut command can be enabled or
    383   * disabled.  This always returns true if we're in non-chrome HTML/XHTML
    384   * document.  Otherwise, same as the result of `IsCopyToClipboardAllowed()`.
    385   */
    386  MOZ_CAN_RUN_SCRIPT bool IsCutCommandEnabled() const;
    387 
    388  /**
    389   * IsCopyCommandEnabled() returns copy command can be enabled or disabled.
    390   * This always returns true if we're in non-chrome HTML/XHTML document.
    391   * Otherwise, same as the result of `IsCopyToClipboardAllowed()`.
    392   */
    393  MOZ_CAN_RUN_SCRIPT bool IsCopyCommandEnabled() const;
    394 
    395  /**
    396   * IsCopyToClipboardAllowed() returns true if the selected content can
    397   * be copied into the clipboard.  This returns true when:
    398   * - `Selection` is not collapsed and we're not a password editor.
    399   * - `Selection` is not collapsed and we're a password editor but selection
    400   *   range is in unmasked range.
    401   */
    402  bool IsCopyToClipboardAllowed() const {
    403    AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
    404    if (NS_WARN_IF(!editActionData.CanHandle())) {
    405      return false;
    406    }
    407    return IsCopyToClipboardAllowedInternal();
    408  }
    409 
    410  /**
    411   * Called before starting to handle eMouseDown or eMouseUp in PresShell.
    412   *
    413   * @return true if IME consumed aMouseEvent.
    414   */
    415  MOZ_CAN_RUN_SCRIPT bool WillHandleMouseButtonEvent(
    416      WidgetMouseEvent& aMouseEvent);
    417 
    418  /**
    419   * HandleDropEvent() is called from EditorEventListener::Drop that is handler
    420   * of drop event.
    421   */
    422  MOZ_CAN_RUN_SCRIPT nsresult HandleDropEvent(dom::DragEvent* aDropEvent);
    423 
    424  MOZ_CAN_RUN_SCRIPT virtual nsresult HandleKeyPressEvent(
    425      WidgetKeyboardEvent* aKeyboardEvent);
    426 
    427  virtual dom::EventTarget* GetDOMEventTarget() const = 0;
    428 
    429  /**
    430   * OnCompositionStart() is called when editor receives eCompositionStart
    431   * event which should be handled in this editor.
    432   */
    433  nsresult OnCompositionStart(WidgetCompositionEvent& aCompositionStartEvent);
    434 
    435  /**
    436   * OnCompositionChange() is called when editor receives an eCompositioChange
    437   * event which should be handled in this editor.
    438   *
    439   * @param aCompositionChangeEvent     eCompositionChange event which should
    440   *                                    be handled in this editor.
    441   */
    442  MOZ_CAN_RUN_SCRIPT nsresult
    443  OnCompositionChange(WidgetCompositionEvent& aCompositionChangeEvent);
    444 
    445  /**
    446   * OnCompositionEnd() is called when editor receives an eCompositionChange
    447   * event and it's followed by eCompositionEnd event and after
    448   * OnCompositionChange() is called.
    449   */
    450  MOZ_CAN_RUN_SCRIPT void OnCompositionEnd(
    451      WidgetCompositionEvent& aCompositionEndEvent);
    452 
    453  /**
    454   * Accessor methods to flags.
    455   */
    456  uint32_t Flags() const { return mFlags; }
    457 
    458  MOZ_CAN_RUN_SCRIPT nsresult AddFlags(uint32_t aFlags) {
    459    const uint32_t kOldFlags = Flags();
    460    const uint32_t kNewFlags = (kOldFlags | aFlags);
    461    if (kNewFlags == kOldFlags) {
    462      return NS_OK;
    463    }
    464    return SetFlags(kNewFlags);  // virtual call and may be expensive.
    465  }
    466  MOZ_CAN_RUN_SCRIPT nsresult RemoveFlags(uint32_t aFlags) {
    467    const uint32_t kOldFlags = Flags();
    468    const uint32_t kNewFlags = (kOldFlags & ~aFlags);
    469    if (kNewFlags == kOldFlags) {
    470      return NS_OK;
    471    }
    472    return SetFlags(kNewFlags);  // virtual call and may be expensive.
    473  }
    474  MOZ_CAN_RUN_SCRIPT nsresult AddAndRemoveFlags(uint32_t aAddingFlags,
    475                                                uint32_t aRemovingFlags) {
    476    MOZ_ASSERT(!(aAddingFlags & aRemovingFlags),
    477               "Same flags are specified both adding and removing");
    478    const uint32_t kOldFlags = Flags();
    479    const uint32_t kNewFlags = ((kOldFlags | aAddingFlags) & ~aRemovingFlags);
    480    if (kNewFlags == kOldFlags) {
    481      return NS_OK;
    482    }
    483    return SetFlags(kNewFlags);  // virtual call and may be expensive.
    484  }
    485 
    486  bool IsSingleLineEditor() const {
    487    const bool isSingleLineEditor =
    488        (mFlags & nsIEditor::eEditorSingleLineMask) != 0;
    489    MOZ_ASSERT_IF(isSingleLineEditor, IsTextEditor());
    490    return isSingleLineEditor;
    491  }
    492 
    493  bool IsPasswordEditor() const {
    494    const bool isPasswordEditor =
    495        (mFlags & nsIEditor::eEditorPasswordMask) != 0;
    496    MOZ_ASSERT_IF(isPasswordEditor, IsTextEditor());
    497    return isPasswordEditor;
    498  }
    499 
    500  // FYI: Both IsRightToLeft() and IsLeftToRight() may return false if
    501  //      the editor inherits the content node's direction.
    502  bool IsRightToLeft() const {
    503    return (mFlags & nsIEditor::eEditorRightToLeft) != 0;
    504  }
    505  bool IsLeftToRight() const {
    506    return (mFlags & nsIEditor::eEditorLeftToRight) != 0;
    507  }
    508 
    509  bool IsReadonly() const {
    510    return (mFlags & nsIEditor::eEditorReadonlyMask) != 0;
    511  }
    512 
    513  bool IsMailEditor() const {
    514    return (mFlags & nsIEditor::eEditorMailMask) != 0;
    515  }
    516 
    517  bool IsInteractionAllowed() const {
    518    const bool isInteractionAllowed =
    519        (mFlags & nsIEditor::eEditorAllowInteraction) != 0;
    520    MOZ_ASSERT_IF(isInteractionAllowed, IsHTMLEditor());
    521    return isInteractionAllowed;
    522  }
    523 
    524  bool ShouldSkipSpellCheck() const {
    525    return (mFlags & nsIEditor::eEditorSkipSpellCheck) != 0;
    526  }
    527 
    528  bool HasIndependentSelection() const {
    529    MOZ_ASSERT_IF(mSelectionController, IsTextEditor());
    530    return !!mSelectionController;
    531  }
    532 
    533  bool IsModifiable() const { return !IsReadonly(); }
    534 
    535  /**
    536   * IsInEditSubAction() return true while the instance is handling an edit
    537   * sub-action.  Otherwise, false.
    538   */
    539  bool IsInEditSubAction() const { return mIsInEditSubAction; }
    540 
    541  /**
    542   * IsEmpty() checks whether the editor is empty.  If editor has only padding
    543   * <br> element for empty editor, returns true.  If editor's root element has
    544   * non-empty text nodes or other nodes like <br>, returns false.
    545   */
    546  virtual bool IsEmpty() const = 0;
    547 
    548  /**
    549   * SuppressDispatchingInputEvent() suppresses or unsuppresses dispatching
    550   * "input" event.
    551   */
    552  void SuppressDispatchingInputEvent(bool aSuppress) {
    553    mDispatchInputEvent = !aSuppress;
    554  }
    555 
    556  /**
    557   * IsSuppressingDispatchingInputEvent() returns true if the editor stops
    558   * dispatching input event.  Otherwise, false.
    559   */
    560  bool IsSuppressingDispatchingInputEvent() const {
    561    return !mDispatchInputEvent;
    562  }
    563 
    564  /**
    565   * Returns true if markNodeDirty() has any effect.  Returns false if
    566   * markNodeDirty() is a no-op.
    567   */
    568  bool OutputsMozDirty() const {
    569    // Return true for Composer (!IsInteractionAllowed()) or mail
    570    // (IsMailEditor()), but false for webpages.
    571    return !IsInteractionAllowed() || IsMailEditor();
    572  }
    573 
    574  /**
    575   * Get the focused element, if we're focused.  Returns null otherwise.
    576   */
    577  virtual Element* GetFocusedElement() const;
    578 
    579  /**
    580   * Whether the aGUIEvent should be handled by this editor or not.  When this
    581   * returns false, The aGUIEvent shouldn't be handled on this editor,
    582   * i.e., The aGUIEvent should be handled by another inner editor or ancestor
    583   * elements.
    584   */
    585  virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) const;
    586 
    587  /**
    588   * FindSelectionRoot() returns a selection root of this editor when aNode
    589   * gets focus.  aNode must be a content node or a document node.  When the
    590   * target isn't a part of this editor, returns nullptr.  If this is for
    591   * designMode, you should set the document node to aNode except that an
    592   * element in the document has focus.
    593   */
    594  [[nodiscard]] virtual Element* FindSelectionRoot(const nsINode& aNode) const;
    595 
    596  /**
    597   * OnFocus() is called when we get a focus event.
    598   *
    599   * @param aOriginalEventTargetNode    The original event target node of the
    600   *                                    focus event.
    601   */
    602  MOZ_CAN_RUN_SCRIPT virtual nsresult OnFocus(
    603      const nsINode& aOriginalEventTargetNode);
    604 
    605  /**
    606   * OnBlur() is called when we're blurred.
    607   *
    608   * @param aEventTarget        The event target of the blur event.
    609   */
    610  virtual nsresult OnBlur(const dom::EventTarget* aEventTarget) = 0;
    611 
    612  /** Resyncs spellchecking state (enabled/disabled).  This should be called
    613   * when anything that affects spellchecking state changes, such as the
    614   * spellcheck attribute value.
    615   */
    616  void SyncRealTimeSpell();
    617 
    618  /**
    619   * Do "cut".
    620   *
    621   * @param aPrincipal          If you know current context is subject
    622   *                            principal or system principal, set it.
    623   *                            When nullptr, this checks it automatically.
    624   */
    625  MOZ_CAN_RUN_SCRIPT nsresult CutAsAction(nsIPrincipal* aPrincipal = nullptr);
    626 
    627  /**
    628   * CanPaste() returns true if user can paste something at current selection.
    629   */
    630  virtual bool CanPaste(nsIClipboard::ClipboardType aClipboardType) const = 0;
    631 
    632  /**
    633   * Do "undo" or "redo".
    634   *
    635   * @param aCount              How many count of transactions should be
    636   *                            handled.
    637   * @param aPrincipal          Set subject principal if it may be called by
    638   *                            JS.  If set to nullptr, will be treated as
    639   *                            called by system.
    640   */
    641  MOZ_CAN_RUN_SCRIPT nsresult UndoAsAction(uint32_t aCount,
    642                                           nsIPrincipal* aPrincipal = nullptr);
    643  MOZ_CAN_RUN_SCRIPT nsresult RedoAsAction(uint32_t aCount,
    644                                           nsIPrincipal* aPrincipal = nullptr);
    645 
    646  /**
    647   * InsertTextAsAction() inserts aStringToInsert at selection.
    648   * Although this method is implementation of nsIEditor.insertText(),
    649   * this treats the input is an edit action.  If you'd like to insert text
    650   * as part of edit action, you probably should use InsertTextAsSubAction().
    651   *
    652   * @param aStringToInsert     The string to insert.
    653   * @param aPrincipal          Set subject principal if it may be called by
    654   *                            JS.  If set to nullptr, will be treated as
    655   *                            called by system.
    656   */
    657  MOZ_CAN_RUN_SCRIPT nsresult InsertTextAsAction(
    658      const nsAString& aStringToInsert, nsIPrincipal* aPrincipal = nullptr);
    659 
    660  /**
    661   * InsertLineBreakAsAction() is called when user inputs a line break with
    662   * Enter or something.  If the instance is `HTMLEditor`, this is called
    663   * when Shift + Enter or "insertlinebreak" command.
    664   *
    665   * @param aPrincipal          Set subject principal if it may be called by
    666   *                            JS.  If set to nullptr, will be treated as
    667   *                            called by system.
    668   */
    669  MOZ_CAN_RUN_SCRIPT virtual nsresult InsertLineBreakAsAction(
    670      nsIPrincipal* aPrincipal = nullptr) = 0;
    671 
    672  /**
    673   * CanDeleteSelection() returns true if `Selection` is not collapsed and
    674   * it's allowed to be removed.
    675   */
    676  bool CanDeleteSelection() const {
    677    AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
    678    if (NS_WARN_IF(!editActionData.CanHandle())) {
    679      return false;
    680    }
    681    return IsModifiable() && !SelectionRef().IsCollapsed();
    682  }
    683 
    684  /**
    685   * DeleteSelectionAsAction() removes selection content or content around
    686   * caret with transactions.  This should be used for handling it as an
    687   * edit action.  If you'd like to remove selection for preparing to insert
    688   * something, you probably should use DeleteSelectionAsSubAction().
    689   *
    690   * @param aDirectionAndAmount How much range should be removed.
    691   * @param aStripWrappers      Whether the parent blocks should be removed
    692   *                            when they become empty.
    693   * @param aPrincipal          Set subject principal if it may be called by
    694   *                            JS.  If set to nullptr, will be treated as
    695   *                            called by system.
    696   */
    697  MOZ_CAN_RUN_SCRIPT nsresult
    698  DeleteSelectionAsAction(nsIEditor::EDirection aDirectionAndAmount,
    699                          nsIEditor::EStripWrappers aStripWrappers,
    700                          nsIPrincipal* aPrincipal = nullptr);
    701 
    702  enum class AllowBeforeInputEventCancelable {
    703    No,
    704    Yes,
    705  };
    706 
    707  enum class PreventSetSelection {
    708    No,
    709    Yes,
    710  };
    711 
    712  /**
    713   * Replace text in aReplaceRange or all text in this editor with aString and
    714   * treat the change as inserting the string.
    715   *
    716   * @param aString             The string to set.
    717   * @param aReplaceRange       The range to be replaced.
    718   *                            If nullptr, all contents will be replaced.
    719   *                            NOTE: Currently, nullptr is not allowed if
    720   *                                  the editor is an HTMLEditor.
    721   * @param aAllowBeforeInputEventCancelable
    722   *                            Whether `beforeinput` event which will be
    723   *                            dispatched for this can be cancelable or not.
    724   * @param aPreventSetSelection
    725   *                            Whether setting selection after replacing text.
    726   *                            If No, selection is the tail of replaced text.
    727   *                            If Yes, selection isn't changed.
    728   * @param aPrincipal          Set subject principal if it may be called by
    729   *                            JS.  If set to nullptr, will be treated as
    730   *                            called by system.
    731   */
    732  MOZ_CAN_RUN_SCRIPT nsresult ReplaceTextAsAction(
    733      const nsAString& aString, nsRange* aReplaceRange,
    734      AllowBeforeInputEventCancelable aAllowBeforeInputEventCancelable,
    735      PreventSetSelection aPreventSetSelection = PreventSetSelection::No,
    736      nsIPrincipal* aPrincipal = nullptr);
    737 
    738  /**
    739   * Can we paste |aTransferable| or, if |aTransferable| is null, will a call
    740   * to pasteTransferable later possibly succeed if given an instance of
    741   * nsITransferable then? True if the doc is modifiable, and, if
    742   * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|.
    743   */
    744  virtual bool CanPasteTransferable(nsITransferable* aTransferable) = 0;
    745 
    746  /**
    747   * PasteAsAction() pastes clipboard content to Selection.  This method
    748   * may dispatch ePaste event first.  If its defaultPrevent() is called,
    749   * this does nothing but returns NS_OK.
    750   *
    751   * @param aClipboardType      nsIClipboard::kGlobalClipboard or
    752   *                            nsIClipboard::kSelectionClipboard.
    753   * @param aDispatchPasteEvent Yes if this should dispatch ePaste event
    754   *                            before pasting.  Otherwise, No.
    755   * @param aDataTransfer       The object containing the data to use for the
    756   *                            paste operation. May be nullptr, in which case
    757   *                            this will just get the data from the clipboard.
    758   * @param aPrincipal          Set subject principal if it may be called by
    759   *                            JS.  If set to nullptr, will be treated as
    760   *                            called by system.
    761   */
    762  enum class DispatchPasteEvent { No, Yes };
    763  MOZ_CAN_RUN_SCRIPT nsresult
    764  PasteAsAction(nsIClipboard::ClipboardType aClipboardType,
    765                DispatchPasteEvent aDispatchPasteEvent,
    766                DataTransfer* aDataTransfer = nullptr,
    767                nsIPrincipal* aPrincipal = nullptr);
    768 
    769  /**
    770   * Paste aTransferable at Selection.
    771   *
    772   * @param aTransferable       Must not be nullptr.
    773   * @param aDispatchPasteEvent Yes if this should dispatch ePaste event
    774   *                            before pasting.  Otherwise, No.
    775   * @param aPrincipal          Set subject principal if it may be called by
    776   *                            JS.  If set to nullptr, will be treated as
    777   *                            called by system.
    778   */
    779  MOZ_CAN_RUN_SCRIPT nsresult PasteTransferableAsAction(
    780      nsITransferable* aTransferable, DispatchPasteEvent aDispatchPasteEvent,
    781      nsIPrincipal* aPrincipal = nullptr);
    782 
    783  /**
    784   * PasteAsQuotationAsAction() pastes content in clipboard as quotation.
    785   * If the editor is TextEditor or in plaintext mode, will paste the content
    786   * with appending ">" to start of each line.
    787   * if the editor is HTMLEditor and is not in plaintext mode, will patste it
    788   * into newly created blockquote element.
    789   *
    790   * @param aClipboardType      nsIClipboard::kGlobalClipboard or
    791   *                            nsIClipboard::kSelectionClipboard.
    792   * @param aDispatchPasteEvent Yes if this should dispatch ePaste event
    793   *                            before pasting.  Otherwise, No.
    794   * @param aDataTransfer       The object containing the data to use for the
    795   *                            paste operation. May be nullptr, in which case
    796   *                            this will just get the data from the clipboard.
    797   * @param aPrincipal          Set subject principal if it may be called by
    798   *                            JS.  If set to nullptr, will be treated as
    799   *                            called by system.
    800   */
    801  MOZ_CAN_RUN_SCRIPT nsresult
    802  PasteAsQuotationAsAction(nsIClipboard::ClipboardType aClipboardType,
    803                           DispatchPasteEvent aDispatchPasteEvent,
    804                           DataTransfer* aDataTransfer = nullptr,
    805                           nsIPrincipal* aPrincipal = nullptr);
    806 
    807  /**
    808   * Return true if `beforeinput` or `input` event is being dispatched.
    809   */
    810  [[nodiscard]] bool IsDispatchingInputEvent() const {
    811    return mEditActionData && mEditActionData->IsDispatchingInputEvent();
    812  }
    813 
    814 protected:  // May be used by friends.
    815  class AutoEditActionDataSetter;
    816 
    817  /**
    818   * TopLevelEditSubActionData stores temporary data while we're handling
    819   * top-level edit sub-action.
    820   */
    821  struct MOZ_STACK_CLASS TopLevelEditSubActionData final {
    822    friend class AutoEditActionDataSetter;
    823 
    824    // Set selected range before edit.  Then, RangeUpdater keep modifying
    825    // the range while we're changing the DOM tree.
    826    RefPtr<RangeItem> mSelectedRange;
    827 
    828    // Computing changed range while we're handling sub actions.
    829    RefPtr<nsRange> mChangedRange;
    830 
    831    // XXX In strict speaking, mCachedPendingStyles isn't enough to cache
    832    //     inline styles because inline style can be specified with "style"
    833    //     attribute and/or CSS in <style> elements or CSS files.  So, we need
    834    //     to look for better implementation about this.
    835    // FYI: Initialization cost of AutoPendingStyleCacheArray is expensive and
    836    //      it is not used by TextEditor so that we should construct it only
    837    //      when we're an HTMLEditor.
    838    Maybe<AutoPendingStyleCacheArray> mCachedPendingStyles;
    839 
    840    // If we tried to delete selection, set to true.
    841    bool mDidDeleteSelection;
    842 
    843    // If we have explicitly set selection inter line, set to true.
    844    // `AfterEdit()` or something shouldn't overwrite it in such case.
    845    bool mDidExplicitlySetInterLine;
    846 
    847    // If we have deleted non-collapsed range set to true, there are only 2
    848    // cases for now:
    849    //   - non-collapsed range was selected.
    850    //   - selection was collapsed in a text node and a Unicode character
    851    //     was removed.
    852    bool mDidDeleteNonCollapsedRange;
    853 
    854    // If we have deleted parent empty blocks, set to true.
    855    bool mDidDeleteEmptyParentBlocks;
    856 
    857    // If we're a contenteditable editor, we temporarily increase edit count
    858    // of the document between `BeforeEdit()` and `AfterEdit()`.  I.e., if
    859    // we increased the count in `BeforeEdit()`, we need to decrease it in
    860    // `AfterEdit()`, however, the document may be changed to designMode or
    861    // non-editable.  Therefore, we need to store with this whether we need
    862    // to restore it.
    863    bool mRestoreContentEditableCount;
    864 
    865    // If we explicitly normalized whitespaces around the changed range,
    866    // set to true.
    867    bool mDidNormalizeWhitespaces;
    868 
    869    // Set to true by default.  If somebody inserts an HTML fragment
    870    // intentionally, any empty elements shouldn't be cleaned up later.  In the
    871    // case this is set to false.
    872    // TODO: We should not do this by default.  If it's necessary, each edit
    873    //       action handler do it by itself instead.  Then, we can avoid such
    874    //       unnecessary DOM tree scan.
    875    bool mNeedsToCleanUpEmptyElements;
    876 
    877    /**
    878     * The following methods modifies some data of this struct and
    879     * `EditSubActionData` struct.  Currently, these are required only
    880     * by `HTMLEditor`.  Therefore, for cutting the runtime cost of
    881     * `TextEditor`, these methods should be called only by `HTMLEditor`.
    882     * But it's fine to use these methods in `TextEditor` if necessary.
    883     * If so, you need to call `DidDeleteText()` and `DidInsertText()`
    884     * from `SetTextNodeWithoutTransaction()`.
    885     */
    886    void DidCreateElement(EditorBase& aEditorBase, Element& aNewElement);
    887    void DidInsertContent(EditorBase& aEditorBase, nsIContent& aNewContent);
    888    void WillDeleteContent(EditorBase& aEditorBase,
    889                           nsIContent& aRemovingContent);
    890    void DidSplitContent(EditorBase& aEditorBase, nsIContent& aSplitContent,
    891                         nsIContent& aNewContent);
    892    void DidJoinContents(EditorBase& aEditorBase,
    893                         const EditorRawDOMPoint& aJoinedPoint);
    894    void DidInsertText(EditorBase& aEditorBase,
    895                       const EditorRawDOMPoint& aInsertionBegin,
    896                       const EditorRawDOMPoint& aInsertionEnd);
    897    void DidDeleteText(EditorBase& aEditorBase,
    898                       const EditorRawDOMPoint& aStartInTextNode);
    899    void WillDeleteRange(EditorBase& aEditorBase,
    900                         const EditorRawDOMPoint& aStart,
    901                         const EditorRawDOMPoint& aEnd);
    902 
    903   private:
    904    void Clear() {
    905      mDidExplicitlySetInterLine = false;
    906      // We don't need to clear other members which are referred only when the
    907      // editor is an HTML editor anymore.  Note that if `mSelectedRange` is
    908      // non-nullptr, that means that we're in `HTMLEditor`.
    909      if (!mSelectedRange) {
    910        return;
    911      }
    912      mSelectedRange->Clear();
    913      mChangedRange->Reset();
    914      if (mCachedPendingStyles.isSome()) {
    915        mCachedPendingStyles->Clear();
    916      }
    917      mDidDeleteSelection = false;
    918      mDidDeleteNonCollapsedRange = false;
    919      mDidDeleteEmptyParentBlocks = false;
    920      mRestoreContentEditableCount = false;
    921      mDidNormalizeWhitespaces = false;
    922      mNeedsToCleanUpEmptyElements = true;
    923    }
    924 
    925    /**
    926     * Extend mChangedRange to include `aNode`.
    927     */
    928    nsresult AddNodeToChangedRange(const HTMLEditor& aHTMLEditor,
    929                                   nsINode& aNode);
    930 
    931    /**
    932     * Extend mChangedRange to include `aPoint`.
    933     */
    934    nsresult AddPointToChangedRange(const HTMLEditor& aHTMLEditor,
    935                                    const EditorRawDOMPoint& aPoint);
    936 
    937    /**
    938     * Extend mChangedRange to include `aStart` and `aEnd`.
    939     */
    940    nsresult AddRangeToChangedRange(const HTMLEditor& aHTMLEditor,
    941                                    const EditorRawDOMPoint& aStart,
    942                                    const EditorRawDOMPoint& aEnd);
    943 
    944    TopLevelEditSubActionData() = default;
    945    TopLevelEditSubActionData(const TopLevelEditSubActionData& aOther) = delete;
    946  };
    947 
    948  struct MOZ_STACK_CLASS EditSubActionData final {
    949    // While this is set to false, TopLevelEditSubActionData::mChangedRange
    950    // shouldn't be modified since in some cases, modifying it in the setter
    951    // itself may be faster.  Note that we should affect this only for current
    952    // edit sub action since mutation event listener may edit different range.
    953    bool mAdjustChangedRangeFromListener;
    954 
    955   private:
    956    void Clear() { mAdjustChangedRangeFromListener = true; }
    957 
    958    friend EditorBase;
    959  };
    960 
    961 protected:  // AutoEditActionDataSetter, this shouldn't be accessed by friends.
    962  /**
    963   * SettingDataTransfer enum class is used to specify whether DataTransfer
    964   * should be initialized with or without format.  For example, when user
    965   * uses Accel + Shift + V to paste text without format, DataTransfer should
    966   * have only plain/text data to make web apps treat it without format.
    967   */
    968  enum class SettingDataTransfer {
    969    eWithFormat,
    970    eWithoutFormat,
    971  };
    972 
    973  /**
    974   * AutoEditActionDataSetter grabs some necessary objects for handling any
    975   * edit actions and store the edit action what we're handling.  When this is
    976   * created, its pointer is set to the mEditActionData, and this guarantees
    977   * the lifetime of grabbing objects until it's destroyed.
    978   */
    979  class MOZ_STACK_CLASS AutoEditActionDataSetter final {
    980   public:
    981    // NOTE: aPrincipal will be used when we implement "beforeinput" event.
    982    //       It's set only when maybe we shouldn't dispatch it because of
    983    //       called by JS.  I.e., if this is nullptr, we can always dispatch
    984    //       it.
    985    AutoEditActionDataSetter(const EditorBase& aEditorBase,
    986                             EditAction aEditAction,
    987                             nsIPrincipal* aPrincipal = nullptr);
    988    AutoEditActionDataSetter() = delete;
    989    AutoEditActionDataSetter(const AutoEditActionDataSetter& aOther) = delete;
    990    ~AutoEditActionDataSetter();
    991 
    992    void SetSelectionCreatedByDoubleclick(bool aSelectionCreatedByDoubleclick) {
    993      mSelectionCreatedByDoubleclick = aSelectionCreatedByDoubleclick;
    994    }
    995 
    996    [[nodiscard]] bool SelectionCreatedByDoubleclick() const {
    997      return mSelectionCreatedByDoubleclick;
    998    }
    999 
   1000    void UpdateEditAction(EditAction aEditAction) {
   1001      MOZ_ASSERT(!mHasTriedToDispatchBeforeInputEvent,
   1002                 "It's too late to update EditAction since this may have "
   1003                 "already dispatched a beforeinput event");
   1004      mEditAction = aEditAction;
   1005    }
   1006 
   1007    /**
   1008     * CanHandle() or CanHandleAndHandleBeforeInput() must be called
   1009     * immediately after creating the instance.  If caller does not need to
   1010     * handle "beforeinput" event or caller needs to set additional information
   1011     * the events later, use the former.  Otherwise, use the latter.  If caller
   1012     * uses the former, it's required to call MaybeDispatchBeforeInputEvent() by
   1013     * itself.
   1014     *
   1015     */
   1016    [[nodiscard]] bool CanHandle() const {
   1017 #ifdef DEBUG
   1018      mHasCanHandleChecked = true;
   1019 #endif  // #ifdef DEBUG
   1020      // Don't allow to run new edit action when an edit action caused
   1021      // destroying the editor while it's being handled.
   1022      if (mEditAction != EditAction::eInitializing &&
   1023          HasEditorDestroyedDuringHandlingEditActionAndNotYetReinitialized()) {
   1024        NS_WARNING("Editor was destroyed during an edit action being handled");
   1025        return false;
   1026      }
   1027      return IsDataAvailable();
   1028    }
   1029    [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1030    CanHandleAndMaybeDispatchBeforeInputEvent() {
   1031      if (MOZ_UNLIKELY(NS_WARN_IF(!CanHandle()))) {
   1032        return NS_ERROR_NOT_INITIALIZED;
   1033      }
   1034      nsresult rv = MaybeFlushPendingNotifications();
   1035      if (MOZ_UNLIKELY(NS_FAILED(rv))) {
   1036        return rv;
   1037      }
   1038      return MaybeDispatchBeforeInputEvent();
   1039    }
   1040    [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1041    CanHandleAndFlushPendingNotifications() {
   1042      if (MOZ_UNLIKELY(NS_WARN_IF(!CanHandle()))) {
   1043        return NS_ERROR_NOT_INITIALIZED;
   1044      }
   1045      MOZ_ASSERT(MayEditActionRequireLayout(mRawEditAction));
   1046      return MaybeFlushPendingNotifications();
   1047    }
   1048 
   1049    [[nodiscard]] bool IsDataAvailable() const {
   1050      return mSelection && mEditorBase.mDocument;
   1051    }
   1052 
   1053    /**
   1054     * MaybeDispatchBeforeInputEvent() considers whether this instance needs to
   1055     * dispatch "beforeinput" event or not.  Then,
   1056     * mHasTriedToDispatchBeforeInputEvent is set to true.
   1057     *
   1058     * @param aDeleteDirectionAndAmount
   1059     *                  If `MayEditActionDeleteAroundCollapsedSelection(
   1060     *                  mEditAction)` returns true, this must be set.
   1061     *                  Otherwise, don't set explicitly.
   1062     * @return          If this method actually dispatches "beforeinput" event
   1063     *                  and it's canceled, returns
   1064     *                  NS_ERROR_EDITOR_ACTION_CANCELED.
   1065     */
   1066    [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult MaybeDispatchBeforeInputEvent(
   1067        nsIEditor::EDirection aDeleteDirectionAndAmount = nsIEditor::eNone);
   1068 
   1069    /**
   1070     * MarkAsBeforeInputHasBeenDispatched() should be called only when updating
   1071     * the DOM occurs asynchronously from user input (e.g., inserting blob
   1072     * object which is loaded asynchronously) and `beforeinput` has already
   1073     * been dispatched (always should be so).
   1074     */
   1075    void MarkAsBeforeInputHasBeenDispatched() {
   1076      MOZ_ASSERT(!HasTriedToDispatchBeforeInputEvent());
   1077      MOZ_ASSERT(mEditAction == EditAction::ePaste ||
   1078                 mEditAction == EditAction::ePasteAsQuotation ||
   1079                 mEditAction == EditAction::eDrop);
   1080      mHasTriedToDispatchBeforeInputEvent = true;
   1081    }
   1082 
   1083    /**
   1084     * MarkAsHandled() is called before dispatching `input` event and notifying
   1085     * editor observers.  After this is called, any nested edit action become
   1086     * non illegal case.
   1087     */
   1088    void MarkAsHandled() {
   1089      MOZ_ASSERT(!mHandled);
   1090      mHandled = true;
   1091    }
   1092 
   1093    /**
   1094     * ShouldAlreadyHaveHandledBeforeInputEventDispatching() returns true if the
   1095     * edit action requires to handle "beforeinput" event but not yet dispatched
   1096     * it nor considered as not dispatched it and can dispatch it when this is
   1097     * called.
   1098     */
   1099    bool ShouldAlreadyHaveHandledBeforeInputEventDispatching() const {
   1100      return !HasTriedToDispatchBeforeInputEvent() &&
   1101             NeedsBeforeInputEventHandling(mEditAction) &&
   1102             IsBeforeInputEventEnabled() /* &&
   1103              // If we still need to dispatch a clipboard event, we should
   1104              // dispatch it first, then, we need to dispatch beforeinput
   1105              // event later.
   1106              !NeedsToDispatchClipboardEvent()*/
   1107          ;
   1108    }
   1109 
   1110    /**
   1111     * HasTriedToDispatchBeforeInputEvent() returns true if the instance's
   1112     * MaybeDispatchBeforeInputEvent() has already been called.
   1113     */
   1114    bool HasTriedToDispatchBeforeInputEvent() const {
   1115      return mHasTriedToDispatchBeforeInputEvent;
   1116    }
   1117 
   1118    bool IsCanceled() const { return mBeforeInputEventCanceled; }
   1119 
   1120    /**
   1121     * Returns a `Selection` for normal selection.  The lifetime is guaranteed
   1122     * during alive this instance in the stack.
   1123     */
   1124    MOZ_KNOWN_LIVE Selection& SelectionRef() const {
   1125      MOZ_ASSERT(!mSelection ||
   1126                 (mSelection->GetType() == SelectionType::eNormal));
   1127      return *mSelection;
   1128    }
   1129 
   1130    Text* GetCachedTextNode() const {
   1131      MOZ_ASSERT(mEditorBase.IsTextEditor());
   1132      return mTextNode;
   1133    }
   1134 
   1135    nsIPrincipal* GetPrincipal() const { return mPrincipal; }
   1136    EditAction GetEditAction() const { return mEditAction; }
   1137 
   1138    template <typename PT, typename CT>
   1139    void SetSpellCheckRestartPoint(const EditorDOMPointBase<PT, CT>& aPoint) {
   1140      MOZ_ASSERT(aPoint.IsSet());
   1141      // We should store only container and offset because new content may
   1142      // be inserted before referring child.
   1143      // XXX Shouldn't we compare whether aPoint is before
   1144      //     mSpellCheckRestartPoint if it's set.
   1145      mSpellCheckRestartPoint =
   1146          EditorDOMPoint(aPoint.GetContainer(), aPoint.Offset());
   1147    }
   1148    void ClearSpellCheckRestartPoint() { mSpellCheckRestartPoint.Clear(); }
   1149    const EditorDOMPoint& GetSpellCheckRestartPoint() const {
   1150      return mSpellCheckRestartPoint;
   1151    }
   1152 
   1153    void SetData(const nsAString& aData) {
   1154      MOZ_ASSERT(!mHasTriedToDispatchBeforeInputEvent,
   1155                 "It's too late to set data since this may have already "
   1156                 "dispatched a beforeinput event");
   1157      mData = aData;
   1158    }
   1159    const nsString& GetData() const { return mData; }
   1160 
   1161    void SetColorData(const nsAString& aData);
   1162 
   1163    /**
   1164     * InitializeDataTransfer(DataTransfer*) sets mDataTransfer to
   1165     * aDataTransfer.  In this case, aDataTransfer should not be read/write
   1166     * because it'll be set to InputEvent.dataTransfer and which should be
   1167     * read-only.
   1168     */
   1169    void InitializeDataTransfer(DataTransfer* aDataTransfer);
   1170    /**
   1171     * InitializeDataTransfer(nsITransferable*) creates new DataTransfer
   1172     * instance, initializes it with aTransferable and sets mDataTransfer to
   1173     * it.
   1174     */
   1175    void InitializeDataTransfer(nsITransferable* aTransferable);
   1176    /**
   1177     * InitializeDataTransfer(const nsAString&) creates new DataTransfer
   1178     * instance, initializes it with aString and sets mDataTransfer to it.
   1179     */
   1180    void InitializeDataTransfer(const nsAString& aString);
   1181    /**
   1182     * InitializeDataTransferWithClipboard() creates new DataTransfer instance,
   1183     * initializes it with clipboard and sets mDataTransfer to it.
   1184     */
   1185    void InitializeDataTransferWithClipboard(
   1186        SettingDataTransfer aSettingDataTransfer, DataTransfer* aDataTransfer,
   1187        nsIClipboard::ClipboardType aClipboardType);
   1188    DataTransfer* GetDataTransfer() const { return mDataTransfer; }
   1189 
   1190    /**
   1191     * AppendTargetRange() appends aTargetRange to target ranges.  This should
   1192     * be used only by edit action handlers which do not want to set target
   1193     * ranges to selection ranges.
   1194     */
   1195    void AppendTargetRange(dom::StaticRange& aTargetRange);
   1196    void AppendTargetRange(RefPtr<dom::StaticRange>&& aTargetRange);
   1197 
   1198    /**
   1199     * Make dispatching `beforeinput` forcibly non-cancelable.
   1200     */
   1201    void MakeBeforeInputEventNonCancelable() {
   1202      mMakeBeforeInputEventNonCancelable = true;
   1203    }
   1204 
   1205    /**
   1206     * NotifyOfDispatchingClipboardEvent() is called after dispatching
   1207     * a clipboard event.
   1208     */
   1209    void NotifyOfDispatchingClipboardEvent() {
   1210      MOZ_ASSERT(NeedsToDispatchClipboardEvent());
   1211      MOZ_ASSERT(!mHasTriedToDispatchClipboardEvent);
   1212      mHasTriedToDispatchClipboardEvent = true;
   1213    }
   1214 
   1215    void Abort() { mAborted = true; }
   1216    bool IsAborted() const { return mAborted; }
   1217 
   1218    void OnEditorDestroy() {
   1219      if (!mHandled && mHasTriedToDispatchBeforeInputEvent) {
   1220        // Remember the editor was destroyed only when this edit action is being
   1221        // handled because they are caused by mutation event listeners or
   1222        // something other unexpected event listeners.  In the cases, new child
   1223        // edit action shouldn't been aborted.
   1224        mEditorWasDestroyedDuringHandlingEditAction = true;
   1225        mEditorWasReinitialized = false;
   1226      }
   1227      if (mParentData) {
   1228        mParentData->OnEditorDestroy();
   1229      }
   1230    }
   1231    void OnEditorInitialized();
   1232    /**
   1233     * Return true if the editor was destroyed at least once while the
   1234     * EditAction is being handled.  Note that the editor may have already been
   1235     * reinitialized even if this returns true.
   1236     */
   1237    [[nodiscard]] bool HasEditorDestroyedDuringHandlingEditAction() const {
   1238      return mEditorWasDestroyedDuringHandlingEditAction;
   1239    }
   1240    /**
   1241     * Return true if the editor was destroyed while the EditAction is being
   1242     * handled and has not been reinitialized.  I.e., the editor is still under
   1243     * the destroyed state.
   1244     */
   1245    [[nodiscard]] bool
   1246    HasEditorDestroyedDuringHandlingEditActionAndNotYetReinitialized() const {
   1247      return mEditorWasDestroyedDuringHandlingEditAction &&
   1248             !mEditorWasReinitialized;
   1249    }
   1250 
   1251    void SetTopLevelEditSubAction(EditSubAction aEditSubAction,
   1252                                  EDirection aDirection = eNone) {
   1253      mTopLevelEditSubAction = aEditSubAction;
   1254      TopLevelEditSubActionDataRef().Clear();
   1255      switch (mTopLevelEditSubAction) {
   1256        case EditSubAction::eInsertNode:
   1257        case EditSubAction::eMoveNode:
   1258        case EditSubAction::eCreateNode:
   1259        case EditSubAction::eSplitNode:
   1260        case EditSubAction::eInsertText:
   1261        case EditSubAction::eInsertTextComingFromIME:
   1262        case EditSubAction::eSetTextProperty:
   1263        case EditSubAction::eRemoveTextProperty:
   1264        case EditSubAction::eRemoveAllTextProperties:
   1265        case EditSubAction::eSetText:
   1266        case EditSubAction::eInsertLineBreak:
   1267        case EditSubAction::eInsertParagraphSeparator:
   1268        case EditSubAction::eCreateOrChangeList:
   1269        case EditSubAction::eIndent:
   1270        case EditSubAction::eOutdent:
   1271        case EditSubAction::eSetOrClearAlignment:
   1272        case EditSubAction::eCreateOrRemoveBlock:
   1273        case EditSubAction::eFormatBlockForHTMLCommand:
   1274        case EditSubAction::eMergeBlockContents:
   1275        case EditSubAction::eRemoveList:
   1276        case EditSubAction::eCreateOrChangeDefinitionListItem:
   1277        case EditSubAction::eInsertElement:
   1278        case EditSubAction::eInsertQuotation:
   1279        case EditSubAction::eInsertQuotedText:
   1280        case EditSubAction::ePasteHTMLContent:
   1281        case EditSubAction::eInsertHTMLSource:
   1282        case EditSubAction::eSetPositionToAbsolute:
   1283        case EditSubAction::eSetPositionToStatic:
   1284        case EditSubAction::eDecreaseZIndex:
   1285        case EditSubAction::eIncreaseZIndex:
   1286          MOZ_ASSERT(aDirection == eNext);
   1287          mDirectionOfTopLevelEditSubAction = eNext;
   1288          break;
   1289        case EditSubAction::eJoinNodes:
   1290        case EditSubAction::eDeleteText:
   1291          MOZ_ASSERT(aDirection == ePrevious);
   1292          mDirectionOfTopLevelEditSubAction = ePrevious;
   1293          break;
   1294        case EditSubAction::eUndo:
   1295        case EditSubAction::eRedo:
   1296        case EditSubAction::eComputeTextToOutput:
   1297        case EditSubAction::eCreatePaddingBRElementForEmptyEditor:
   1298        case EditSubAction::eMaintainWhiteSpaceVisibility:
   1299        case EditSubAction::eNone:
   1300          MOZ_ASSERT(aDirection == eNone);
   1301          mDirectionOfTopLevelEditSubAction = eNone;
   1302          break;
   1303        case EditSubAction::eDeleteNode:
   1304        case EditSubAction::eDeleteSelectedContent:
   1305          // Unfortunately, eDeleteNode and eDeleteSelectedContent is used with
   1306          // any direction.  We might have specific sub-action for each
   1307          // direction, but there are some points referencing
   1308          // eDeleteSelectedContent so that we should keep storing direction
   1309          // as-is for now.
   1310          mDirectionOfTopLevelEditSubAction = aDirection;
   1311          break;
   1312      }
   1313    }
   1314    EditSubAction GetTopLevelEditSubAction() const {
   1315      MOZ_ASSERT(IsDataAvailable());
   1316      return mTopLevelEditSubAction;
   1317    }
   1318    EDirection GetDirectionOfTopLevelEditSubAction() const {
   1319      return mDirectionOfTopLevelEditSubAction;
   1320    }
   1321 
   1322    const TopLevelEditSubActionData& TopLevelEditSubActionDataRef() const {
   1323      return mParentData ? mParentData->TopLevelEditSubActionDataRef()
   1324                         : mTopLevelEditSubActionData;
   1325    }
   1326    TopLevelEditSubActionData& TopLevelEditSubActionDataRef() {
   1327      return mParentData ? mParentData->TopLevelEditSubActionDataRef()
   1328                         : mTopLevelEditSubActionData;
   1329    }
   1330 
   1331    const EditSubActionData& EditSubActionDataRef() const {
   1332      return mEditSubActionData;
   1333    }
   1334    EditSubActionData& EditSubActionDataRef() { return mEditSubActionData; }
   1335 
   1336    SelectionState& SavedSelectionRef() {
   1337      return mParentData ? mParentData->SavedSelectionRef() : mSavedSelection;
   1338    }
   1339    const SelectionState& SavedSelectionRef() const {
   1340      return mParentData ? mParentData->SavedSelectionRef() : mSavedSelection;
   1341    }
   1342 
   1343    RangeUpdater& RangeUpdaterRef() {
   1344      return mParentData ? mParentData->RangeUpdaterRef() : mRangeUpdater;
   1345    }
   1346    const RangeUpdater& RangeUpdaterRef() const {
   1347      return mParentData ? mParentData->RangeUpdaterRef() : mRangeUpdater;
   1348    }
   1349 
   1350    MOZ_CAN_RUN_SCRIPT void UpdateSelectionCache(Selection& aSelection);
   1351 
   1352    bool IsDispatchingInputEvent() const {
   1353      return mDispatchingInputEvent ||
   1354             (mParentData && mParentData->IsDispatchingInputEvent());
   1355    }
   1356    void WillDispatchInputEvent() {
   1357      MOZ_ASSERT(!mDispatchingInputEvent);
   1358      mDispatchingInputEvent = true;
   1359    }
   1360    void DidDispatchInputEvent() {
   1361      MOZ_ASSERT(mDispatchingInputEvent);
   1362      mDispatchingInputEvent = false;
   1363    }
   1364 
   1365   private:
   1366    bool IsBeforeInputEventEnabled() const;
   1367 
   1368    [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1369    MaybeFlushPendingNotifications() const;
   1370 
   1371    static bool NeedsBeforeInputEventHandling(EditAction aEditAction) {
   1372      MOZ_ASSERT(aEditAction != EditAction::eNone);
   1373      switch (aEditAction) {
   1374        case EditAction::eNone:
   1375        // If we're not handling edit action, we don't need to handle
   1376        // "beforeinput" event.
   1377        case EditAction::eNotEditing:
   1378        // If we're being initialized, we may need to create a padding <br>
   1379        // element, but it shouldn't cause `beforeinput` event.
   1380        case EditAction::eInitializing:
   1381        // If we're just selecting or getting table cells, we shouldn't
   1382        // dispatch `beforeinput` event.
   1383        case NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING:
   1384        // If raw level transaction API is used, the API user needs to handle
   1385        // both "beforeinput" event and "input" event if it's necessary.
   1386        case EditAction::eUnknown:
   1387        // Hiding/showing password affects only layout so that we don't need
   1388        // to handle beforeinput event for it.
   1389        case EditAction::eHidePassword:
   1390        // We don't need to dispatch "beforeinput" event before
   1391        // "compositionstart".
   1392        case EditAction::eStartComposition:
   1393        // We don't need to let web apps know the mode change.
   1394        case EditAction::eEnableOrDisableCSS:
   1395        case EditAction::eEnableOrDisableAbsolutePositionEditor:
   1396        case EditAction::eEnableOrDisableResizer:
   1397        case EditAction::eEnableOrDisableInlineTableEditingUI:
   1398        // We don't need to let contents in chrome's editor to know the size
   1399        // change.
   1400        case EditAction::eSetWrapWidth:
   1401        // While resizing or moving element, we update only shadow, i.e.,
   1402        // don't touch to the DOM in content.  Therefore, we don't need to
   1403        // dispatch "beforeinput" event.
   1404        case EditAction::eResizingElement:
   1405        case EditAction::eMovingElement:
   1406        // Perhaps, we don't need to dispatch "beforeinput" event for
   1407        // padding `<br>` element for empty editor because it's internal
   1408        // handling and it should be occurred by another change.
   1409        case EditAction::eCreatePaddingBRElementForEmptyEditor:
   1410          return false;
   1411        default:
   1412          return true;
   1413      }
   1414    }
   1415 
   1416    bool NeedsToDispatchClipboardEvent() const {
   1417      if (mHasTriedToDispatchClipboardEvent) {
   1418        return false;
   1419      }
   1420      switch (mEditAction) {
   1421        case EditAction::ePaste:
   1422        case EditAction::ePasteAsQuotation:
   1423        case EditAction::eCut:
   1424        case EditAction::eCopy:
   1425          return true;
   1426        default:
   1427          return false;
   1428      }
   1429    }
   1430 
   1431    void MarkEditActionCanceled();
   1432 
   1433    EditorBase& mEditorBase;
   1434    RefPtr<Selection> mSelection;
   1435    nsTArray<OwningNonNull<Selection>> mRetiredSelections;
   1436 
   1437    // mTextNode is the text node if and only if the instance is TextEditor.
   1438    // This is set when the instance is created and updated when the TextEditor
   1439    // is reinitialized with the new native anonymous subtree.
   1440    RefPtr<Text> mTextNode;
   1441 
   1442    // True if the selection was created by doubleclicking a word.
   1443    bool mSelectionCreatedByDoubleclick{false};
   1444 
   1445    nsCOMPtr<nsIPrincipal> mPrincipal;
   1446    // EditAction may be nested, for example, a command may be executed
   1447    // from mutation event listener which is run while editor changes
   1448    // the DOM tree.  In such case, we need to handle edit action separately.
   1449    AutoEditActionDataSetter* mParentData;
   1450 
   1451    // Cached selection for AutoSelectionRestorer.
   1452    SelectionState mSavedSelection;
   1453 
   1454    // Utility class object for maintaining preserved ranges.
   1455    RangeUpdater mRangeUpdater;
   1456 
   1457    // The data should be set to InputEvent.data.
   1458    nsString mData;
   1459 
   1460    // The dataTransfer should be set to InputEvent.dataTransfer.
   1461    RefPtr<DataTransfer> mDataTransfer;
   1462 
   1463    // They are used for result of InputEvent.getTargetRanges() of beforeinput.
   1464    OwningNonNullStaticRangeArray mTargetRanges;
   1465 
   1466    // Start point where spell checker should check from.  This is used only
   1467    // by TextEditor.
   1468    EditorDOMPoint mSpellCheckRestartPoint;
   1469 
   1470    // Different from mTopLevelEditSubAction, its data should be stored only
   1471    // in the most ancestor AutoEditActionDataSetter instance since we don't
   1472    // want to pay the copying cost and sync cost.
   1473    TopLevelEditSubActionData mTopLevelEditSubActionData;
   1474 
   1475    // Different from mTopLevelEditSubActionData, this stores temporaly data
   1476    // for current edit sub action.
   1477    EditSubActionData mEditSubActionData;
   1478 
   1479    // mEditAction and mRawEditActions stores edit action.  The difference of
   1480    // them is, if and only if edit actions are nested and parent edit action
   1481    // is one of trying to edit something, but nested one is not so, it's
   1482    // overwritten by the parent edit action.
   1483    EditAction mEditAction;
   1484    EditAction mRawEditAction;
   1485 
   1486    // Different from its data, you can refer "current" AutoEditActionDataSetter
   1487    // instance's mTopLevelEditSubAction member since it's copied from the
   1488    // parent instance at construction and it's always cleared before this
   1489    // won't be overwritten and cleared before destruction.
   1490    EditSubAction mTopLevelEditSubAction = EditSubAction::eNone;
   1491 
   1492    EDirection mDirectionOfTopLevelEditSubAction = nsIEditor::eNone;
   1493 
   1494    bool mAborted = false;
   1495 
   1496    // Set to true when this handles "beforeinput" event dispatching.  Note
   1497    // that even if "beforeinput" event shouldn't be dispatched for this,
   1498    // instance, this is set to true when it's considered.
   1499    bool mHasTriedToDispatchBeforeInputEvent = false;
   1500    // Set to true if "beforeinput" event was dispatched and it's canceled.
   1501    bool mBeforeInputEventCanceled = false;
   1502    // Set to true if `beforeinput` event must not be cancelable even if
   1503    // its inputType is defined as cancelable by the standards.
   1504    bool mMakeBeforeInputEventNonCancelable = false;
   1505    // Set to true when the edit action handler tries to dispatch a clipboard
   1506    // event.
   1507    bool mHasTriedToDispatchClipboardEvent = false;
   1508    // The editor instance may be destroyed once temporarily if `document.write`
   1509    // etc runs.  In such case, we should mark this flag of being handled
   1510    // edit action.
   1511    bool mEditorWasDestroyedDuringHandlingEditAction;
   1512    // This is set to `true` if the editor was destroyed but now, it's
   1513    // initialized again.
   1514    bool mEditorWasReinitialized;
   1515    // This is set before dispatching `input` event and notifying editor
   1516    // observers.
   1517    bool mHandled = false;
   1518    // Whether the editor is dispatching a `beforeinput` or `input` event.
   1519    bool mDispatchingInputEvent = false;
   1520 
   1521 #ifdef DEBUG
   1522    mutable bool mHasCanHandleChecked = false;
   1523 #endif  // #ifdef DEBUG
   1524  };
   1525 
   1526  void UpdateEditActionData(const nsAString& aData) {
   1527    mEditActionData->SetData(aData);
   1528  }
   1529 
   1530  void NotifyOfDispatchingClipboardEvent() {
   1531    MOZ_ASSERT(mEditActionData);
   1532    mEditActionData->NotifyOfDispatchingClipboardEvent();
   1533  }
   1534 
   1535 protected:  // May be called by friends.
   1536  /****************************************************************************
   1537   * Some friend classes are allowed to call the following protected methods.
   1538   * However, those methods won't prepare caches of some objects which are
   1539   * necessary for them.  So, if you call them from friend classes, you need
   1540   * to make sure that AutoEditActionDataSetter is created.
   1541   ****************************************************************************/
   1542 
   1543  bool IsEditActionCanceled() const {
   1544    MOZ_ASSERT(mEditActionData);
   1545    return mEditActionData->IsCanceled();
   1546  }
   1547 
   1548  bool ShouldAlreadyHaveHandledBeforeInputEventDispatching() const {
   1549    MOZ_ASSERT(mEditActionData);
   1550    return mEditActionData
   1551        ->ShouldAlreadyHaveHandledBeforeInputEventDispatching();
   1552  }
   1553 
   1554  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult MaybeDispatchBeforeInputEvent() {
   1555    MOZ_ASSERT(mEditActionData);
   1556    return mEditActionData->MaybeDispatchBeforeInputEvent();
   1557  }
   1558 
   1559  void MarkAsBeforeInputHasBeenDispatched() {
   1560    MOZ_ASSERT(mEditActionData);
   1561    return mEditActionData->MarkAsBeforeInputHasBeenDispatched();
   1562  }
   1563 
   1564  bool HasTriedToDispatchBeforeInputEvent() const {
   1565    return mEditActionData &&
   1566           mEditActionData->HasTriedToDispatchBeforeInputEvent();
   1567  }
   1568 
   1569  bool IsEditActionDataAvailable() const {
   1570    return mEditActionData && mEditActionData->IsDataAvailable();
   1571  }
   1572 
   1573  bool IsTopLevelEditSubActionDataAvailable() const {
   1574    return mEditActionData && !!GetTopLevelEditSubAction();
   1575  }
   1576 
   1577  bool IsEditActionAborted() const {
   1578    MOZ_ASSERT(mEditActionData);
   1579    return mEditActionData->IsAborted();
   1580  }
   1581 
   1582  nsresult GetDataFromDataTransferOrClipboard(
   1583      DataTransfer* aDataTransfer, nsITransferable* aTransferable,
   1584      nsIClipboard::ClipboardType aClipboardType) const;
   1585 
   1586  /**
   1587   * SelectionRef() returns cached normal Selection.  This is pretty faster than
   1588   * EditorBase::GetSelection() if available.
   1589   * Note that this never crash unless public methods ignore the result of
   1590   * AutoEditActionDataSetter::CanHandle() and keep handling edit action but any
   1591   * methods should stop handling edit action if it returns false.
   1592   */
   1593  MOZ_KNOWN_LIVE Selection& SelectionRef() const {
   1594    MOZ_ASSERT(mEditActionData);
   1595    MOZ_ASSERT(mEditActionData->SelectionRef().GetType() ==
   1596               SelectionType::eNormal);
   1597    return mEditActionData->SelectionRef();
   1598  }
   1599 
   1600  // Return the Text if and only if we're a TextEditor instance.  It's cached
   1601  // while we're handling an edit action, so, this stores the latest value even
   1602  // after we have been destroyed.
   1603  Text* GetCachedTextNode() {
   1604    MOZ_ASSERT(IsTextEditor());
   1605    return mEditActionData ? mEditActionData->GetCachedTextNode() : nullptr;
   1606  }
   1607 
   1608  // Return the Text if and only if we're a TextEditor instance.  It's cached
   1609  // while we're handling an edit action, so, this stores the latest value even
   1610  // after we have been destroyed.
   1611  const Text* GetCachedTextNode() const {
   1612    MOZ_ASSERT(IsTextEditor());
   1613    return const_cast<EditorBase*>(this)->GetCachedTextNode();
   1614  }
   1615 
   1616  nsIPrincipal* GetEditActionPrincipal() const {
   1617    MOZ_ASSERT(mEditActionData);
   1618    return mEditActionData->GetPrincipal();
   1619  }
   1620 
   1621  /**
   1622   * GetEditAction() returns EditAction which is being handled.  If some
   1623   * edit actions are nested, this returns the innermost edit action.
   1624   */
   1625  EditAction GetEditAction() const {
   1626    return mEditActionData ? mEditActionData->GetEditAction()
   1627                           : EditAction::eNone;
   1628  }
   1629 
   1630  /**
   1631   * GetInputEventData() returns inserting or inserted text value with
   1632   * current edit action.  The result is proper for InputEvent.data value.
   1633   */
   1634  const nsString& GetInputEventData() const {
   1635    return mEditActionData ? mEditActionData->GetData() : VoidString();
   1636  }
   1637 
   1638  /**
   1639   * GetInputEventDataTransfer() returns inserting or inserted transferable
   1640   * content with current edit action.  The result is proper for
   1641   * InputEvent.dataTransfer value.
   1642   */
   1643  DataTransfer* GetInputEventDataTransfer() const {
   1644    return mEditActionData ? mEditActionData->GetDataTransfer() : nullptr;
   1645  }
   1646 
   1647  /**
   1648   * GetTopLevelEditSubAction() returns the top level edit sub-action.
   1649   * For example, if selected content is being replaced with inserted text,
   1650   * while removing selected content, the top level edit sub-action may be
   1651   * EditSubAction::eDeleteSelectedContent.  However, while inserting new
   1652   * text, the top level edit sub-action may be EditSubAction::eInsertText.
   1653   * So, this result means what we are doing right now unless you're looking
   1654   * for a case which the method is called via mutation event listener or
   1655   * selectionchange event listener which are fired while handling the edit
   1656   * sub-action.
   1657   */
   1658  EditSubAction GetTopLevelEditSubAction() const {
   1659    return mEditActionData ? mEditActionData->GetTopLevelEditSubAction()
   1660                           : EditSubAction::eNone;
   1661  }
   1662 
   1663  /**
   1664   * GetDirectionOfTopLevelEditSubAction() returns direction which user
   1665   * intended for doing the edit sub-action.
   1666   */
   1667  EDirection GetDirectionOfTopLevelEditSubAction() const {
   1668    return mEditActionData
   1669               ? mEditActionData->GetDirectionOfTopLevelEditSubAction()
   1670               : eNone;
   1671  }
   1672 
   1673  /**
   1674   * SavedSelection() returns reference to saved selection which are
   1675   * stored by AutoSelectionRestorer.
   1676   */
   1677  SelectionState& SavedSelectionRef() {
   1678    MOZ_ASSERT(IsEditActionDataAvailable());
   1679    return mEditActionData->SavedSelectionRef();
   1680  }
   1681  const SelectionState& SavedSelectionRef() const {
   1682    MOZ_ASSERT(IsEditActionDataAvailable());
   1683    return mEditActionData->SavedSelectionRef();
   1684  }
   1685 
   1686  RangeUpdater& RangeUpdaterRef() {
   1687    MOZ_ASSERT(IsEditActionDataAvailable());
   1688    return mEditActionData->RangeUpdaterRef();
   1689  }
   1690  const RangeUpdater& RangeUpdaterRef() const {
   1691    MOZ_ASSERT(IsEditActionDataAvailable());
   1692    return mEditActionData->RangeUpdaterRef();
   1693  }
   1694 
   1695  template <typename PT, typename CT>
   1696  void SetSpellCheckRestartPoint(const EditorDOMPointBase<PT, CT>& aPoint) {
   1697    MOZ_ASSERT(IsEditActionDataAvailable());
   1698    return mEditActionData->SetSpellCheckRestartPoint(aPoint);
   1699  }
   1700 
   1701  void ClearSpellCheckRestartPoint() {
   1702    MOZ_ASSERT(IsEditActionDataAvailable());
   1703    return mEditActionData->ClearSpellCheckRestartPoint();
   1704  }
   1705 
   1706  const EditorDOMPoint& GetSpellCheckRestartPoint() const {
   1707    MOZ_ASSERT(IsEditActionDataAvailable());
   1708    return mEditActionData->GetSpellCheckRestartPoint();
   1709  }
   1710 
   1711  const TopLevelEditSubActionData& TopLevelEditSubActionDataRef() const {
   1712    MOZ_ASSERT(IsEditActionDataAvailable());
   1713    return mEditActionData->TopLevelEditSubActionDataRef();
   1714  }
   1715  TopLevelEditSubActionData& TopLevelEditSubActionDataRef() {
   1716    MOZ_ASSERT(IsEditActionDataAvailable());
   1717    return mEditActionData->TopLevelEditSubActionDataRef();
   1718  }
   1719 
   1720  const EditSubActionData& EditSubActionDataRef() const {
   1721    MOZ_ASSERT(IsEditActionDataAvailable());
   1722    return mEditActionData->EditSubActionDataRef();
   1723  }
   1724  EditSubActionData& EditSubActionDataRef() {
   1725    MOZ_ASSERT(IsEditActionDataAvailable());
   1726    return mEditActionData->EditSubActionDataRef();
   1727  }
   1728 
   1729  /**
   1730   * GetFirstIMESelectionStartPoint() and GetLastIMESelectionEndPoint() returns
   1731   * start of first IME selection range or end of last IME selection range if
   1732   * there is.  Otherwise, returns non-set DOM point.
   1733   */
   1734  template <typename EditorDOMPointType>
   1735  EditorDOMPointType GetFirstIMESelectionStartPoint() const;
   1736  template <typename EditorDOMPointType>
   1737  EditorDOMPointType GetLastIMESelectionEndPoint() const;
   1738 
   1739  /**
   1740   * IsSelectionRangeContainerNotContent() returns true if one of container
   1741   * of selection ranges is not a content node, i.e., a Document node.
   1742   */
   1743  bool IsSelectionRangeContainerNotContent() const;
   1744 
   1745  /**
   1746   * OnInputText() is called when user inputs text with keyboard or something.
   1747   *
   1748   * @param aStringToInsert     The string to insert.
   1749   */
   1750  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1751  OnInputText(const nsAString& aStringToInsert);
   1752 
   1753  enum class InsertTextFor {
   1754    NormalText,
   1755    CompositionStart,
   1756    CompositionUpdate,
   1757    CompositionEnd,
   1758    CompositionStartAndEnd,
   1759  };
   1760  friend inline std::ostream& operator<<(std::ostream& aStream,
   1761                                         const InsertTextFor& aPurpose) {
   1762    switch (aPurpose) {
   1763      case InsertTextFor::NormalText:
   1764        return aStream << "InsertTextFor::NormalText";
   1765      case InsertTextFor::CompositionStart:
   1766        return aStream << "InsertTextFor::CompositionStart";
   1767      case InsertTextFor::CompositionUpdate:
   1768        return aStream << "InsertTextFor::CompositionUpdate";
   1769      case InsertTextFor::CompositionEnd:
   1770        return aStream << "InsertTextFor::CompositionEnd";
   1771      case InsertTextFor::CompositionStartAndEnd:
   1772        return aStream << "InsertTextFor::CompositionStartAndEnd";
   1773    }
   1774    return aStream << "<illegal value>";
   1775  }
   1776  [[nodiscard]] static bool InsertingTextForComposition(
   1777      InsertTextFor aPurpose) {
   1778    return aPurpose != InsertTextFor::NormalText;
   1779  }
   1780  [[nodiscard]] static bool InsertingTextForExtantComposition(
   1781      InsertTextFor aPurpose) {
   1782    return aPurpose == InsertTextFor::CompositionUpdate ||
   1783           aPurpose == InsertTextFor::CompositionEnd;
   1784  }
   1785  [[nodiscard]] static bool InsertingTextForStartingComposition(
   1786      InsertTextFor aPurpose) {
   1787    return aPurpose == InsertTextFor::CompositionStart ||
   1788           aPurpose == InsertTextFor::CompositionStartAndEnd;
   1789  }
   1790  [[nodiscard]] static bool InsertingTextForCommittingComposition(
   1791      InsertTextFor aPurpose) {
   1792    return aPurpose == InsertTextFor::CompositionEnd ||
   1793           aPurpose == InsertTextFor::CompositionStartAndEnd;
   1794  }
   1795  [[nodiscard]] static bool NothingToDoIfInsertingEmptyText(
   1796      InsertTextFor aPurpose) {
   1797    return aPurpose == InsertTextFor::NormalText ||
   1798           aPurpose == InsertTextFor::CompositionStartAndEnd;
   1799  }
   1800 
   1801  /**
   1802   * InsertTextAsSubAction() inserts aStringToInsert at selection.  This
   1803   * should be used for handling it as an edit sub-action.
   1804   *
   1805   * @param aStringToInsert     The string to insert.
   1806   * @param aPurpose            Specify the purpose to insert text.
   1807   */
   1808  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InsertTextAsSubAction(
   1809      const nsAString& aStringToInsert, InsertTextFor aPurpose);
   1810 
   1811  /**
   1812   * Insert aStringToInsert to aPointToInsert or better insertion point around
   1813   * it.  If aPointToInsert isn't in a text node, this method looks for the
   1814   * nearest point in a text node with TextEditor::FindBetterInsertionPoint()
   1815   * or EditorDOMPoint::GetPointInTextNodeIfPointingAroundTextNode().
   1816   * If there is no text node, this creates new text node and put
   1817   * aStringToInsert to it.
   1818   *
   1819   * @param aStringToInsert The string to insert.
   1820   * @param aPointToInsert  The point to insert aStringToInsert.
   1821   *                        Must be valid DOM point.
   1822   * @param aInsertTextTo   Whether forcibly creates a new `Text` node in
   1823   *                        specific condition or use existing `Text` if
   1824   *                        available.
   1825   */
   1826  enum class InsertTextTo {
   1827    SpecifiedPoint,
   1828    ExistingTextNodeIfAvailable,
   1829    ExistingTextNodeIfAvailableAndNotStart,
   1830    AlwaysCreateNewTextNode
   1831  };
   1832  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual Result<InsertTextResult, nsresult>
   1833  InsertTextWithTransaction(const nsAString& aStringToInsert,
   1834                            const EditorDOMPoint& aPointToInsert,
   1835                            InsertTextTo aInsertTextTo);
   1836 
   1837  /**
   1838   * Compute insertion point from aPoint and aInsertTextTo.
   1839   */
   1840  [[nodiscard]] EditorDOMPoint ComputePointToInsertText(
   1841      const EditorDOMPoint& aPoint, InsertTextTo aInsertTextTo) const;
   1842 
   1843  /**
   1844   * Insert aStringToInsert to aPointToInsert.
   1845   */
   1846  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<InsertTextResult, nsresult>
   1847  InsertTextIntoTextNodeWithTransaction(
   1848      const nsAString& aStringToInsert,
   1849      const EditorDOMPointInText& aPointToInsert);
   1850 
   1851  /**
   1852   * SetTextNodeWithoutTransaction() is optimized path to set new value to
   1853   * the text node directly and without transaction.  This is used when
   1854   * setting `<input>.value` and `<textarea>.value`.
   1855   */
   1856  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1857  SetTextNodeWithoutTransaction(const nsAString& aString, Text& aTextNode);
   1858 
   1859  /**
   1860   * DeleteNodeWithTransaction() removes aContent from the DOM tree.
   1861   *
   1862   * @param aContent    The node which will be removed form the DOM tree.
   1863   */
   1864  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1865  DeleteNodeWithTransaction(nsIContent& aContent);
   1866 
   1867  /**
   1868   * InsertNodeWithTransaction() inserts aContentToInsert before the child
   1869   * specified by aPointToInsert.
   1870   *
   1871   * @param aContentToInsert    The node to be inserted.
   1872   * @param aPointToInsert      The insertion point of aContentToInsert.
   1873   *                            If this refers end of the container, the
   1874   *                            transaction will append the node to the
   1875   *                            container.  Otherwise, will insert the node
   1876   *                            before child node referred by this.
   1877   * @return                    If succeeded, returns the new content node and
   1878   *                            point to put caret.
   1879   */
   1880  template <typename ContentNodeType>
   1881  [[nodiscard]] MOZ_CAN_RUN_SCRIPT
   1882      Result<CreateNodeResultBase<ContentNodeType>, nsresult>
   1883      InsertNodeWithTransaction(ContentNodeType& aContentToInsert,
   1884                                const EditorDOMPoint& aPointToInsert);
   1885 
   1886  /**
   1887   * InsertPaddingBRElementForEmptyLastLineWithTransaction() creates a padding
   1888   * <br> element with setting flags to NS_PADDING_FOR_EMPTY_LAST_LINE and
   1889   * inserts it around aPointToInsert.
   1890   *
   1891   * @param aPointToInsert      The DOM point where should be <br> node inserted
   1892   *                            before.
   1893   * @return                    If succeeded, returns the new <br> element and
   1894   *                            point to put caret around it.
   1895   */
   1896  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
   1897  InsertPaddingBRElementForEmptyLastLineWithTransaction(
   1898      const EditorDOMPoint& aPointToInsert);
   1899 
   1900  enum class BRElementType {
   1901    Normal,
   1902    PaddingForEmptyEditor,
   1903    PaddingForEmptyLastLine
   1904  };
   1905  /**
   1906   * Updates the type of aBRElement.  If it will be hidden or shown from
   1907   * IMEContentObserver and ContentEventHandler points of view, this temporarily
   1908   * removes the node and reconnect to the same position.
   1909   */
   1910  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1911  UpdateBRElementType(dom::HTMLBRElement& aBRElement, BRElementType aNewType);
   1912 
   1913  /**
   1914   * Create and insert a line break to aPointToInsert.
   1915   */
   1916  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
   1917  InsertBRElement(WithTransaction aWithTransaction,
   1918                  BRElementType aBRElementType,
   1919                  const EditorDOMPoint& aPointToInsert);
   1920 
   1921  /**
   1922   * CloneAttributesWithTransaction() clones all attributes from
   1923   * aSourceElement to aDestElement after removing all attributes in
   1924   * aDestElement.
   1925   */
   1926  MOZ_CAN_RUN_SCRIPT void CloneAttributesWithTransaction(
   1927      Element& aDestElement, Element& aSourceElement);
   1928 
   1929  /**
   1930   * CloneAttributeWithTransaction() copies aAttribute of aSourceElement to
   1931   * aDestElement.  If aSourceElement doesn't have aAttribute, this removes
   1932   * aAttribute from aDestElement.
   1933   *
   1934   * @param aAttribute          Attribute name to be cloned.
   1935   * @param aDestElement        Element node which will be set aAttribute or
   1936   *                            whose aAttribute will be removed.
   1937   * @param aSourceElement      Element node which provides the value of
   1938   *                            aAttribute in aDestElement.
   1939   */
   1940  MOZ_CAN_RUN_SCRIPT nsresult CloneAttributeWithTransaction(
   1941      nsAtom& aAttribute, Element& aDestElement, Element& aSourceElement);
   1942 
   1943  /**
   1944   * RemoveAttributeWithTransaction() removes aAttribute from aElement.
   1945   *
   1946   * @param aElement        Element node which will lose aAttribute.
   1947   * @param aAttribute      Attribute name to be removed from aElement.
   1948   */
   1949  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   1950  RemoveAttributeWithTransaction(Element& aElement, nsAtom& aAttribute);
   1951 
   1952  MOZ_CAN_RUN_SCRIPT virtual nsresult RemoveAttributeOrEquivalent(
   1953      Element* aElement, nsAtom* aAttribute, bool aSuppressTransaction) = 0;
   1954 
   1955  /**
   1956   * SetAttributeWithTransaction() sets aAttribute of aElement to aValue.
   1957   *
   1958   * @param aElement        Element node which will have aAttribute.
   1959   * @param aAttribute      Attribute name to be set.
   1960   * @param aValue          Attribute value be set to aAttribute.
   1961   */
   1962  MOZ_CAN_RUN_SCRIPT nsresult SetAttributeWithTransaction(
   1963      Element& aElement, nsAtom& aAttribute, const nsAString& aValue);
   1964 
   1965  MOZ_CAN_RUN_SCRIPT virtual nsresult SetAttributeOrEquivalent(
   1966      Element* aElement, nsAtom* aAttribute, const nsAString& aValue,
   1967      bool aSuppressTransaction) = 0;
   1968 
   1969  /**
   1970   * Method to replace certain CreateElementNS() calls.
   1971   *
   1972   * @param aTag        Tag you want.
   1973   */
   1974  already_AddRefed<Element> CreateHTMLContent(const nsAtom* aTag) const;
   1975 
   1976  /**
   1977   * Creates text node which is marked as "maybe modified frequently" and
   1978   * "maybe masked" if this is a password editor.
   1979   */
   1980  already_AddRefed<nsTextNode> CreateTextNode(const nsAString& aData) const;
   1981 
   1982  /**
   1983   * DoInsertText(), DoDeleteText(), DoReplaceText() and DoSetText() are
   1984   * wrapper of `CharacterData::InsertData()`, `CharacterData::DeleteData()`,
   1985   * `CharacterData::ReplaceData()` and `CharacterData::SetData()`.
   1986   */
   1987  MOZ_CAN_RUN_SCRIPT void DoInsertText(dom::Text& aText, uint32_t aOffset,
   1988                                       const nsAString& aStringToInsert,
   1989                                       ErrorResult& aRv);
   1990  MOZ_CAN_RUN_SCRIPT void DoDeleteText(dom::Text& aText, uint32_t aOffset,
   1991                                       uint32_t aCount, ErrorResult& aRv);
   1992  MOZ_CAN_RUN_SCRIPT void DoReplaceText(dom::Text& aText, uint32_t aOffset,
   1993                                        uint32_t aCount,
   1994                                        const nsAString& aStringToInsert,
   1995                                        ErrorResult& aRv);
   1996  MOZ_CAN_RUN_SCRIPT void DoSetText(dom::Text& aText,
   1997                                    const nsAString& aStringToSet,
   1998                                    ErrorResult& aRv);
   1999 
   2000  /**
   2001   * Delete text in the range in aTextNode.  Use
   2002   * `HTMLEditor::ReplaceTextWithTransaction` if you'll insert text there (and
   2003   * if you want to use it in `TextEditor`, move it into `EditorBase`).
   2004   *
   2005   * @param aTextNode           The text node which should be modified.
   2006   * @param aOffset             Start offset of removing text in aTextNode.
   2007   * @param aLength             Length of removing text.
   2008   */
   2009  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
   2010  DeleteTextWithTransaction(dom::Text& aTextNode, uint32_t aOffset,
   2011                            uint32_t aLength);
   2012 
   2013  /**
   2014   * MarkElementDirty() sets a special dirty attribute on the element.
   2015   * Usually this will be called immediately after creating a new node.
   2016   *
   2017   * @param aElement    The element for which to insert formatting.
   2018   */
   2019  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult MarkElementDirty(Element& aElement);
   2020 
   2021  MOZ_CAN_RUN_SCRIPT nsresult
   2022  DoTransactionInternal(nsITransaction* aTransaction);
   2023 
   2024  /**
   2025   * Returns true if aNode is our root node.  The root is:
   2026   * If TextEditor, the anonymous <div> element.
   2027   * If HTMLEditor, a <body> element or the document element which may not be
   2028   * editable if it's not in the design mode.
   2029   */
   2030  bool IsRoot(const nsINode* inNode) const;
   2031 
   2032  /**
   2033   * Returns true if aNode is a descendant of our root node.
   2034   * See the comment for IsRoot() for what the root node means.
   2035   */
   2036  bool IsDescendantOfRoot(const nsINode* inNode) const;
   2037 
   2038  /**
   2039   * Returns true when inserting text should be a part of current composition.
   2040   */
   2041  bool ShouldHandleIMEComposition() const;
   2042 
   2043  template <typename EditorDOMPointType>
   2044  EditorDOMPointType GetFirstSelectionStartPoint() const;
   2045  template <typename EditorDOMPointType>
   2046  EditorDOMPointType GetFirstSelectionEndPoint() const;
   2047 
   2048  static nsresult GetEndChildNode(const Selection& aSelection,
   2049                                  nsIContent** aEndNode);
   2050 
   2051  template <typename PT, typename CT>
   2052  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2053  CollapseSelectionTo(const EditorDOMPointBase<PT, CT>& aPoint) const {
   2054    // We don't need to throw exception directly for a failure of updating
   2055    // selection.  Therefore, let's use IgnoredErrorResult for the performance.
   2056    IgnoredErrorResult error;
   2057    CollapseSelectionTo(aPoint, error);
   2058    return error.StealNSResult();
   2059  }
   2060 
   2061  template <typename PT, typename CT>
   2062  MOZ_CAN_RUN_SCRIPT void CollapseSelectionTo(
   2063      const EditorDOMPointBase<PT, CT>& aPoint, ErrorResult& aRv) const {
   2064    MOZ_ASSERT(IsEditActionDataAvailable());
   2065    MOZ_ASSERT(!aRv.Failed());
   2066 
   2067    if (aPoint.GetInterlinePosition() != InterlinePosition::Undefined) {
   2068      if (MOZ_UNLIKELY(NS_FAILED(SelectionRef().SetInterlinePosition(
   2069              aPoint.GetInterlinePosition())))) {
   2070        NS_WARNING("Selection::SetInterlinePosition() failed");
   2071        aRv.Throw(NS_ERROR_FAILURE);
   2072        return;
   2073      }
   2074    }
   2075 
   2076    SelectionRef().CollapseInLimiter(aPoint, aRv);
   2077    if (MOZ_UNLIKELY(Destroyed())) {
   2078      NS_WARNING("Selection::CollapseInLimiter() caused destroying the editor");
   2079      aRv.Throw(NS_ERROR_EDITOR_DESTROYED);
   2080      return;
   2081    }
   2082    NS_WARNING_ASSERTION(!aRv.Failed(),
   2083                         "Selection::CollapseInLimiter() failed");
   2084  }
   2085 
   2086  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2087  CollapseSelectionToStartOf(nsINode& aNode) const {
   2088    return CollapseSelectionTo(EditorRawDOMPoint(&aNode, 0u));
   2089  }
   2090 
   2091  MOZ_CAN_RUN_SCRIPT void CollapseSelectionToStartOf(nsINode& aNode,
   2092                                                     ErrorResult& aRv) const {
   2093    CollapseSelectionTo(EditorRawDOMPoint(&aNode, 0u), aRv);
   2094  }
   2095 
   2096  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2097  CollapseSelectionToEndOf(nsINode& aNode) const {
   2098    return CollapseSelectionTo(EditorRawDOMPoint::AtEndOf(aNode));
   2099  }
   2100 
   2101  MOZ_CAN_RUN_SCRIPT void CollapseSelectionToEndOf(nsINode& aNode,
   2102                                                   ErrorResult& aRv) const {
   2103    CollapseSelectionTo(EditorRawDOMPoint::AtEndOf(aNode), aRv);
   2104  }
   2105 
   2106  /**
   2107   * AllowsTransactionsToChangeSelection() returns true if editor allows any
   2108   * transactions to change Selection.  Otherwise, transactions shouldn't
   2109   * change Selection.
   2110   */
   2111  inline bool AllowsTransactionsToChangeSelection() const {
   2112    return mAllowsTransactionsToChangeSelection;
   2113  }
   2114 
   2115  /**
   2116   * MakeThisAllowTransactionsToChangeSelection() with true makes this editor
   2117   * allow transactions to change Selection.  Otherwise, i.e., with false,
   2118   * makes this editor not allow transactions to change Selection.
   2119   */
   2120  inline void MakeThisAllowTransactionsToChangeSelection(bool aAllow) {
   2121    mAllowsTransactionsToChangeSelection = aAllow;
   2122  }
   2123 
   2124  nsresult HandleInlineSpellCheck(
   2125      const EditorDOMPoint& aPreviouslySelectedStart,
   2126      const dom::AbstractRange* aRange = nullptr);
   2127 
   2128  /**
   2129   * Whether the editor is active on the DOM window.  Note that when this
   2130   * returns true but GetFocusedElement() returns null, it means that this
   2131   * editor was focused when the DOM window was active.
   2132   */
   2133  virtual bool IsActiveInDOMWindow() const;
   2134 
   2135  /**
   2136   * HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
   2137   * with nsCaret::RemoveForceHide().  This does NOT set visibility of
   2138   * nsCaret.  Therefore, this is stateless.
   2139   */
   2140  void HideCaret(bool aHide);
   2141 
   2142 protected:  // Edit sub-action handler
   2143  /**
   2144   * AutoCaretBidiLevelManager() computes bidi level of caret, deleting
   2145   * character(s) from aPointAtCaret at construction.  Then, if you'll
   2146   * need to extend the selection, you should calls `UpdateCaretBidiLevel()`,
   2147   * then, this class may update caret bidi level for you if it's required.
   2148   */
   2149  class MOZ_RAII AutoCaretBidiLevelManager final {
   2150   public:
   2151    /**
   2152     * @param aEditorBase         The editor.
   2153     * @param aPointAtCaret       Collapsed `Selection` point.
   2154     * @param aDirectionAndAmount The direction and amount to delete.
   2155     */
   2156    template <typename PT, typename CT>
   2157    AutoCaretBidiLevelManager(const EditorBase& aEditorBase,
   2158                              nsIEditor::EDirection aDirectionAndAmount,
   2159                              const EditorDOMPointBase<PT, CT>& aPointAtCaret);
   2160 
   2161    /**
   2162     * Failed() returns true if the constructor failed to handle the bidi
   2163     * information.
   2164     */
   2165    bool Failed() const { return mFailed; }
   2166 
   2167    /**
   2168     * Canceled() returns true if when the caller should stop deleting
   2169     * characters since caret position is not visually adjacent the deleting
   2170     * characters and user does not wand to delete them in that case.
   2171     */
   2172    bool Canceled() const { return mCanceled; }
   2173 
   2174    /**
   2175     * MaybeUpdateCaretBidiLevel() may update caret bidi level and schedule to
   2176     * paint it if they are necessary.
   2177     */
   2178    void MaybeUpdateCaretBidiLevel(const EditorBase& aEditorBase) const;
   2179 
   2180   private:
   2181    Maybe<mozilla::intl::BidiEmbeddingLevel> mNewCaretBidiLevel;
   2182    bool mFailed = false;
   2183    bool mCanceled = false;
   2184  };
   2185 
   2186  /**
   2187   * UndefineCaretBidiLevel() resets bidi level of the caret.
   2188   */
   2189  void UndefineCaretBidiLevel() const;
   2190 
   2191  /**
   2192   * Flushing pending notifications if nsFrameSelection requires the latest
   2193   * layout information to compute deletion range.  This may destroy the
   2194   * editor instance itself.  When this returns false, don't keep doing
   2195   * anything.
   2196   */
   2197  [[nodiscard]] MOZ_CAN_RUN_SCRIPT bool
   2198  FlushPendingNotificationsIfToHandleDeletionWithFrameSelection(
   2199      nsIEditor::EDirection aDirectionAndAmount) const;
   2200 
   2201  /**
   2202   * DeleteSelectionAsSubAction() removes selection content or content around
   2203   * caret with transactions.  This should be used for handling it as an
   2204   * edit sub-action.
   2205   *
   2206   * @param aDirectionAndAmount How much range should be removed.
   2207   * @param aStripWrappers      Whether the parent blocks should be removed
   2208   *                            when they become empty.  If this instance is
   2209   *                            a TextEditor, Must be nsIEditor::eNoStrip.
   2210   */
   2211  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2212  DeleteSelectionAsSubAction(nsIEditor::EDirection aDirectionAndAmount,
   2213                             nsIEditor::EStripWrappers aStripWrappers);
   2214 
   2215  /**
   2216   * This method handles "delete selection" commands.
   2217   *
   2218   * @param aDirectionAndAmount Direction of the deletion.
   2219   * @param aStripWrappers      Must be nsIEditor::eNoStrip if this is a
   2220   *                            TextEditor instance.  Otherwise,
   2221   *                            nsIEditor::eStrip is also valid.
   2222   */
   2223  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual Result<EditActionResult, nsresult>
   2224  HandleDeleteSelection(nsIEditor::EDirection aDirectionAndAmount,
   2225                        nsIEditor::EStripWrappers aStripWrappers) = 0;
   2226 
   2227  /**
   2228   * ReplaceSelectionAsSubAction() replaces selection with aString.
   2229   *
   2230   * @param aString    The string to replace.
   2231   */
   2232  MOZ_CAN_RUN_SCRIPT nsresult
   2233  ReplaceSelectionAsSubAction(const nsAString& aString);
   2234 
   2235  /**
   2236   * HandleInsertText() handles inserting text at selection.
   2237   *
   2238   * @param aInsertionString    String to be inserted at selection.
   2239   * @param aPurpose            Specify the purpose of inserting text.
   2240   */
   2241  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual Result<EditActionResult, nsresult>
   2242  HandleInsertText(const nsAString& aInsertionString,
   2243                   InsertTextFor aPurpose) = 0;
   2244 
   2245  /**
   2246   * InsertWithQuotationsAsSubAction() inserts aQuotedText with appending ">"
   2247   * to start of every line.
   2248   *
   2249   * @param aQuotedText         String to insert.  This will be quoted by ">"
   2250   *                            automatically.
   2251   */
   2252  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual nsresult
   2253  InsertWithQuotationsAsSubAction(const nsAString& aQuotedText) = 0;
   2254 
   2255  /**
   2256   * PrepareInsertContent() is a helper method of InsertTextAt(),
   2257   * HTMLEditor::HTMLWithContextInserter::Run().  They insert content coming
   2258   * from clipboard or drag and drop.  Before that, they may need to remove
   2259   * selected contents and adjust selection.  This does them instead.
   2260   *
   2261   * @param aPointToInsert      Point to insert.  Must be set.  Callers
   2262   *                            shouldn't use this instance after calling this
   2263   *                            method because this method may cause changing
   2264   *                            the DOM tree and Selection.
   2265   */
   2266  enum class DeleteSelectedContent : bool {
   2267    No,   // Don't delete selection
   2268    Yes,  // Delete selected content
   2269  };
   2270  MOZ_CAN_RUN_SCRIPT nsresult
   2271  PrepareToInsertContent(const EditorDOMPoint& aPointToInsert,
   2272                         DeleteSelectedContent aDeleteSelectedContent);
   2273 
   2274  /**
   2275   * InsertTextAt() inserts aStringToInsert at aPointToInsert.
   2276   *
   2277   * @param aStringToInsert     The string which you want to insert.
   2278   * @param aPointToInsert      The insertion point.
   2279   */
   2280  MOZ_CAN_RUN_SCRIPT nsresult InsertTextAt(
   2281      const nsAString& aStringToInsert, const EditorDOMPoint& aPointToInsert,
   2282      DeleteSelectedContent aDeleteSelectedContent);
   2283 
   2284  /**
   2285   * Return whether the data is safe to insert as the source and destination
   2286   * principals match, or we are in a editor context where this doesn't matter.
   2287   * Otherwise, the data must be sanitized first.
   2288   */
   2289  enum class SafeToInsertData : bool { No, Yes };
   2290  SafeToInsertData IsSafeToInsertData(nsIPrincipal* aSourcePrincipal) const;
   2291 
   2292  /**
   2293   * Routines for managing the preservation of selection across
   2294   * various editor actions.
   2295   */
   2296  bool ArePreservingSelection() const;
   2297  void PreserveSelectionAcrossActions();
   2298  MOZ_CAN_RUN_SCRIPT nsresult RestorePreservedSelection();
   2299  void StopPreservingSelection();
   2300 
   2301 protected:  // Called by helper classes.
   2302  /**
   2303   * OnStartToHandleTopLevelEditSubAction() is called when
   2304   * GetTopLevelEditSubAction() is EditSubAction::eNone and somebody starts to
   2305   * handle aEditSubAction.
   2306   *
   2307   * @param aTopLevelEditSubAction              Top level edit sub action which
   2308   *                                            will be handled soon.
   2309   * @param aDirectionOfTopLevelEditSubAction   Direction of aEditSubAction.
   2310   */
   2311  MOZ_CAN_RUN_SCRIPT virtual void OnStartToHandleTopLevelEditSubAction(
   2312      EditSubAction aTopLevelEditSubAction,
   2313      nsIEditor::EDirection aDirectionOfTopLevelEditSubAction,
   2314      ErrorResult& aRv);
   2315 
   2316  /**
   2317   * OnEndHandlingTopLevelEditSubAction() is called after
   2318   * SetTopLevelEditSubAction() is handled.
   2319   */
   2320  MOZ_CAN_RUN_SCRIPT virtual nsresult OnEndHandlingTopLevelEditSubAction();
   2321 
   2322  /**
   2323   * OnStartToHandleEditSubAction() and OnEndHandlingEditSubAction() are called
   2324   * when starting to handle an edit sub action and ending handling an edit
   2325   * sub action.
   2326   */
   2327  void OnStartToHandleEditSubAction() { EditSubActionDataRef().Clear(); }
   2328  void OnEndHandlingEditSubAction() { EditSubActionDataRef().Clear(); }
   2329 
   2330  /**
   2331   * (Begin|End)PlaceholderTransaction() are called by AutoPlaceholderBatch.
   2332   * This set of methods are similar to the (Begin|End)Transaction(), but do
   2333   * not use the transaction managers batching feature.  Instead we use a
   2334   * placeholder transaction to wrap up any further transaction while the
   2335   * batch is open.  The advantage of this is that placeholder transactions
   2336   * can later merge, if needed.  Merging is unavailable between transaction
   2337   * manager batches.
   2338   */
   2339  MOZ_CAN_RUN_SCRIPT_BOUNDARY void BeginPlaceholderTransaction(
   2340      nsStaticAtom& aTransactionName, const char* aRequesterFuncName);
   2341  enum class ScrollSelectionIntoView { No, Yes };
   2342  MOZ_CAN_RUN_SCRIPT_BOUNDARY void EndPlaceholderTransaction(
   2343      ScrollSelectionIntoView aScrollSelectionIntoView,
   2344      const char* aRequesterFuncName);
   2345 
   2346  void BeginUpdateViewBatch(const char* aRequesterFuncName);
   2347  MOZ_CAN_RUN_SCRIPT void EndUpdateViewBatch(const char* aRequesterFuncName);
   2348 
   2349  /**
   2350   * Used by HTMLEditor::AutoTransactionBatch, nsIEditor::BeginTransaction
   2351   * and nsIEditor::EndTransation.  After calling BeginTransactionInternal(),
   2352   * all transactions will be treated as an atomic transaction.  I.e., two or
   2353   * more transactions are undid once.
   2354   * XXX What's the difference with PlaceholderTransaction? Should we always
   2355   *     use it instead?
   2356   */
   2357  MOZ_CAN_RUN_SCRIPT void BeginTransactionInternal(
   2358      const char* aRequesterFuncName);
   2359  MOZ_CAN_RUN_SCRIPT void EndTransactionInternal(
   2360      const char* aRequesterFuncName);
   2361 
   2362 protected:  // Shouldn't be used by friend classes
   2363  /**
   2364   * The default destructor. This should suffice. Should this be pure virtual
   2365   * for someone to derive from the EditorBase later? I don't believe so.
   2366   */
   2367  virtual ~EditorBase();
   2368 
   2369  /**
   2370   * @param aDocument   The dom document interface being observed
   2371   * @param aRootElement
   2372   *                    This is the root of the editable section of this
   2373   *                    document. If it is null then we get root from document
   2374   *                    body.
   2375   * @param aSelectionController
   2376   *                    The selection controller of selections which will be
   2377   *                    used in this editor.
   2378   * @param aFlags      Some of nsIEditor::eEditor*Mask flags.
   2379   */
   2380  MOZ_CAN_RUN_SCRIPT nsresult
   2381  InitInternal(Document& aDocument, Element* aRootElement,
   2382               nsISelectionController& aSelectionController, uint32_t aFlags);
   2383 
   2384  /**
   2385   * PostCreateInternal() should be called after InitInternal(), and is the time
   2386   * that the editor tells its documentStateObservers that the document has been
   2387   * created.
   2388   */
   2389  MOZ_CAN_RUN_SCRIPT nsresult PostCreateInternal();
   2390 
   2391  /**
   2392   * PreDestroyInternal() is called before the editor goes away, and gives the
   2393   * editor a chance to tell its documentStateObservers that the document is
   2394   * going away.
   2395   */
   2396  MOZ_CAN_RUN_SCRIPT virtual void PreDestroyInternal();
   2397 
   2398  MOZ_ALWAYS_INLINE EditorType GetEditorType() const {
   2399    return mIsHTMLEditorClass ? EditorType::HTML : EditorType::Text;
   2400  }
   2401 
   2402  /**
   2403   * Check whether the caller can keep handling focus event.
   2404   *
   2405   * @param aOriginalEventTargetNode    The original event target of the focus
   2406   *                                    event.
   2407   */
   2408  [[nodiscard]] bool CanKeepHandlingFocusEvent(
   2409      const nsINode& aOriginalEventTargetNode) const;
   2410 
   2411  /**
   2412   * If this editor has skipped spell checking and not yet flushed, this runs
   2413   * the spell checker.
   2414   */
   2415  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult FlushPendingSpellCheck();
   2416 
   2417  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult EnsureEmptyTextFirstChild();
   2418 
   2419  int32_t WrapWidth() const { return mWrapColumn; }
   2420 
   2421  /**
   2422   * ToGenericNSResult() computes proper nsresult value for the editor users.
   2423   * This should be used only when public methods return result of internal
   2424   * methods.
   2425   */
   2426  static inline nsresult ToGenericNSResult(nsresult aRv) {
   2427    switch (aRv) {
   2428      // If the editor is destroyed while handling an edit action, editor needs
   2429      // to stop handling it.  However, editor throw exception in this case
   2430      // because Chrome does not throw exception even in this case.
   2431      case NS_ERROR_EDITOR_DESTROYED:
   2432        return NS_OK;
   2433      // If editor meets unexpected DOM tree due to modified by mutation event
   2434      // listener, editor needs to stop handling it.  However, editor shouldn't
   2435      // return error for the users because Chrome does not throw exception in
   2436      // this case.
   2437      case NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE:
   2438        return NS_OK;
   2439      // If the editing action is canceled by event listeners, editor needs
   2440      // to stop handling it.  However, editor shouldn't return error for
   2441      // the callers but they should be able to distinguish whether it's
   2442      // canceled or not.  Although it's DOM specific code, let's return
   2443      // DOM_SUCCESS_DOM_NO_OPERATION here.
   2444      case NS_ERROR_EDITOR_ACTION_CANCELED:
   2445        return NS_SUCCESS_DOM_NO_OPERATION;
   2446      // If there is no selection range or editable selection ranges, editor
   2447      // needs to stop handling it.  However, editor shouldn't return error for
   2448      // the callers to avoid throwing exception.  However, they may want to
   2449      // check whether it works or not.  Therefore, we should return
   2450      // NS_SUCCESS_DOM_NO_OPERATION instead.
   2451      case NS_ERROR_EDITOR_NO_EDITABLE_RANGE:
   2452        return NS_SUCCESS_DOM_NO_OPERATION;
   2453      // If CreateNodeResultBase::SuggestCaretPointTo etc is called with
   2454      // SuggestCaret::AndIgnoreTrivialErrors and CollapseSelectionTo returns
   2455      // non-critical error e.g., not NS_ERROR_EDITOR_DESTROYED, it returns
   2456      // this success code instead of actual error code for making the caller
   2457      // handle the case easier.  Therefore, this should be mapped to NS_OK
   2458      // for the users of editor.
   2459      case NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR:
   2460        return NS_OK;
   2461      default:
   2462        return aRv;
   2463    }
   2464  }
   2465 
   2466  /**
   2467   * GetDocumentCharsetInternal() returns charset of the document.
   2468   */
   2469  nsresult GetDocumentCharsetInternal(nsACString& aCharset) const;
   2470 
   2471  /**
   2472   * ComputeValueInternal() computes string value of this editor for given
   2473   * format.  This may be too expensive if it's in hot path.
   2474   *
   2475   * @param aFormatType             MIME type like "text/plain".
   2476   * @param aDocumentEncoderFlags   Flags of nsIDocumentEncoder.
   2477   * @param aCharset                Encoding of the document.
   2478   */
   2479  nsresult ComputeValueInternal(const nsAString& aFormatType,
   2480                                uint32_t aDocumentEncoderFlags,
   2481                                nsAString& aOutputString) const;
   2482 
   2483  /**
   2484   * GetAndInitDocEncoder() returns a document encoder instance for aFormatType
   2485   * after initializing it.  The result may be cached for saving recreation
   2486   * cost.
   2487   *
   2488   * @param aFormatType             MIME type like "text/plain".
   2489   * @param aDocumentEncoderFlags   Flags of nsIDocumentEncoder.
   2490   * @param aCharset                Encoding of the document.
   2491   */
   2492  already_AddRefed<nsIDocumentEncoder> GetAndInitDocEncoder(
   2493      const nsAString& aFormatType, uint32_t aDocumentEncoderFlags,
   2494      const nsACString& aCharset) const;
   2495 
   2496  /**
   2497   * EnsurePaddingBRElementInMultilineEditor() creates a padding `<br>` element
   2498   * at end of multiline text editor.
   2499   */
   2500  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2501  EnsurePaddingBRElementInMultilineEditor();
   2502 
   2503  /**
   2504   * SelectAllInternal() should be used instead of SelectAll() in editor
   2505   * because SelectAll() creates AutoEditActionSetter but we should avoid
   2506   * to create it as far as possible.
   2507   */
   2508  MOZ_CAN_RUN_SCRIPT virtual nsresult SelectAllInternal();
   2509 
   2510  nsresult DetermineCurrentDirection();
   2511 
   2512  /**
   2513   * DispatchInputEvent() dispatches an "input" event synchronously or
   2514   * asynchronously if it's not safe to dispatch.
   2515   */
   2516  MOZ_CAN_RUN_SCRIPT void DispatchInputEvent();
   2517 
   2518  /**
   2519   * Called after a transaction is done successfully.
   2520   */
   2521  MOZ_CAN_RUN_SCRIPT void DoAfterDoTransaction(nsITransaction* aTransaction);
   2522 
   2523  /**
   2524   * Called after a transaction is undone successfully.
   2525   */
   2526 
   2527  MOZ_CAN_RUN_SCRIPT void DoAfterUndoTransaction();
   2528 
   2529  /**
   2530   * Called after a transaction is redone successfully.
   2531   */
   2532  MOZ_CAN_RUN_SCRIPT void DoAfterRedoTransaction();
   2533 
   2534  /**
   2535   * Tell the doc state listeners that the doc state has changed.
   2536   */
   2537  enum TDocumentListenerNotification {
   2538    eDocumentCreated,
   2539    eDocumentToBeDestroyed,
   2540    eDocumentStateChanged
   2541  };
   2542  MOZ_CAN_RUN_SCRIPT nsresult
   2543  NotifyDocumentListeners(TDocumentListenerNotification aNotificationType);
   2544 
   2545  /**
   2546   * Make the given selection span the entire document.
   2547   */
   2548  MOZ_CAN_RUN_SCRIPT virtual nsresult SelectEntireDocument() = 0;
   2549 
   2550  /**
   2551   * Helper method for scrolling the selection into view after
   2552   * an edit operation.
   2553   *
   2554   * Editor methods *should* call this method instead of the versions
   2555   * in the various selection interfaces, since this makes sure that
   2556   * the editor's sync/async settings for reflowing, painting, and scrolling
   2557   * match.
   2558   */
   2559  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2560  ScrollSelectionFocusIntoView() const;
   2561 
   2562  virtual nsresult InstallEventListeners();
   2563  virtual void CreateEventListeners();
   2564  void RemoveEventListeners();
   2565  [[nodiscard]] bool IsListeningToEvents() const;
   2566 
   2567  /**
   2568   * Called if and only if this editor is in readonly mode.
   2569   */
   2570  void HandleKeyPressEventInReadOnlyMode(
   2571      WidgetKeyboardEvent& aKeyboardEvent) const;
   2572 
   2573  /**
   2574   * Get the input event target. This might return null.
   2575   */
   2576  virtual already_AddRefed<Element> GetInputEventTargetElement() const = 0;
   2577 
   2578  /**
   2579   * Return true if spellchecking should be enabled for this editor.
   2580   */
   2581  [[nodiscard]] bool GetDesiredSpellCheckState();
   2582 
   2583  [[nodiscard]] bool CanEnableSpellCheck() const {
   2584    // Check for password/readonly/disabled, which are not spellchecked
   2585    // regardless of DOM. Also, check to see if spell check should be skipped
   2586    // or not.
   2587    return !IsPasswordEditor() && !IsReadonly() && !ShouldSkipSpellCheck();
   2588  }
   2589 
   2590  /**
   2591   * InitializeSelectionAncestorLimit() is called by InitializeSelection().
   2592   * When this is called, each implementation has to call
   2593   * Selection::SetAncestorLimiter() with aAnotherLimit.
   2594   *
   2595   * @param aAncestorLimit      New ancestor limit of Selection.  This always
   2596   *                            has parent node.  So, it's always safe to
   2597   *                            call SetAncestorLimit() with this node.
   2598   */
   2599  MOZ_CAN_RUN_SCRIPT virtual void InitializeSelectionAncestorLimit(
   2600      Element& aAncestorLimit) const;
   2601 
   2602  /**
   2603   * Initializes selection and caret for the editor at getting focus.  If
   2604   * aOriginalEventTargetNode isn't a host of the editor, i.e., the editor
   2605   * doesn't get focus, this does nothing.
   2606   *
   2607   * @param aOriginalEventTargetNode    The original event target node of the
   2608   *                                    focus event.
   2609   */
   2610  MOZ_CAN_RUN_SCRIPT nsresult
   2611  InitializeSelection(const nsINode& aOriginalEventTargetNode);
   2612 
   2613  enum NotificationForEditorObservers {
   2614    eNotifyEditorObserversOfEnd,
   2615    eNotifyEditorObserversOfBefore,
   2616    eNotifyEditorObserversOfCancel
   2617  };
   2618  MOZ_CAN_RUN_SCRIPT void NotifyEditorObservers(
   2619      NotificationForEditorObservers aNotification);
   2620 
   2621  /**
   2622   * HowToHandleCollapsedRange indicates how collapsed range should be treated.
   2623   */
   2624  enum class HowToHandleCollapsedRange {
   2625    // Ignore collapsed range.
   2626    Ignore,
   2627    // Extend collapsed range for removing previous content.
   2628    ExtendBackward,
   2629    // Extend collapsed range for removing next content.
   2630    ExtendForward,
   2631  };
   2632 
   2633  static HowToHandleCollapsedRange HowToHandleCollapsedRangeFor(
   2634      nsIEditor::EDirection aDirectionAndAmount) {
   2635    switch (aDirectionAndAmount) {
   2636      case nsIEditor::eNone:
   2637        return HowToHandleCollapsedRange::Ignore;
   2638      case nsIEditor::ePrevious:
   2639        return HowToHandleCollapsedRange::ExtendBackward;
   2640      case nsIEditor::eNext:
   2641        return HowToHandleCollapsedRange::ExtendForward;
   2642      case nsIEditor::ePreviousWord:
   2643      case nsIEditor::eNextWord:
   2644      case nsIEditor::eToBeginningOfLine:
   2645      case nsIEditor::eToEndOfLine:
   2646        // If the amount is word or
   2647        // line,`AutoClonedSelectionRangeArray::ExtendAnchorFocusRangeFor()`
   2648        // must have already been extended collapsed ranges before.
   2649        return HowToHandleCollapsedRange::Ignore;
   2650    }
   2651    MOZ_ASSERT_UNREACHABLE("Invalid nsIEditor::EDirection value");
   2652    return HowToHandleCollapsedRange::Ignore;
   2653  }
   2654 
   2655  /**
   2656   * InsertDroppedDataTransferAsAction() inserts all data items in aDataTransfer
   2657   * at aDroppedAt unless the editor is destroyed.
   2658   *
   2659   * @param aEditActionData     The edit action data whose edit action must be
   2660   *                            EditAction::eDrop.
   2661   * @param aDataTransfer       The data transfer object which is dropped.
   2662   * @param aDroppedAt          The DOM tree position whether aDataTransfer
   2663   *                            is dropped.
   2664   * @param aSourcePrincipal    Principal of the source of the drag.
   2665   *                            May be nullptr if it comes from another app
   2666   *                            or process.
   2667   */
   2668  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual nsresult
   2669  InsertDroppedDataTransferAsAction(AutoEditActionDataSetter& aEditActionData,
   2670                                    DataTransfer& aDataTransfer,
   2671                                    const EditorDOMPoint& aDroppedAt,
   2672                                    nsIPrincipal* aSourcePrincipal) = 0;
   2673 
   2674  /**
   2675   * DeleteSelectionByDragAsAction() removes selection and dispatch "input"
   2676   * event whose inputType is "deleteByDrag".
   2677   */
   2678  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
   2679  DeleteSelectionByDragAsAction(bool aDispatchInputEvent);
   2680 
   2681  /**
   2682   * DeleteRangeWithTransaction() removes content in aRangeToDelete or content
   2683   * around collapsed aRangeToDelete with transactions and remove empty
   2684   * inclusive ancestor inline elements of the collapsed range after removing
   2685   * the contents.
   2686   *
   2687   * @param aDirectionAndAmount How much range should be removed.
   2688   * @param aStripWrappers      Whether the parent blocks should be removed
   2689   *                            when they become empty.
   2690   *                            Note that this must be `nsIEditor::eNoStrip`
   2691   *                            if this is a TextEditor because anyway it'll
   2692   *                            be ignored.
   2693   * @param aRangeToDelete     The range to delete content.
   2694   */
   2695  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
   2696  DeleteRangeWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
   2697                             nsIEditor::EStripWrappers aStripWrappers,
   2698                             nsRange& aRangeToDelete);
   2699 
   2700  /**
   2701   * DeleteRangesWithTransaction() removes content in aRangesToDelete or content
   2702   * around collapsed ranges in aRangesToDelete with transactions and remove
   2703   * empty inclusive ancestor inline elements of collapsed ranges after
   2704   * removing the contents.
   2705   *
   2706   * @param aDirectionAndAmount How much range should be removed.
   2707   * @param aStripWrappers      Whether the parent blocks should be removed
   2708   *                            when they become empty.
   2709   *                            Note that this must be `nsIEditor::eNoStrip`
   2710   *                            if this is a TextEditor because anyway it'll
   2711   *                            be ignored.
   2712   * @param aRangesToDelete     The ranges to delete content.
   2713   */
   2714  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual Result<CaretPoint, nsresult>
   2715  DeleteRangesWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
   2716                              nsIEditor::EStripWrappers aStripWrappers,
   2717                              AutoClonedRangeArray& aRangesToDelete);
   2718 
   2719  /**
   2720   * Create a transaction for delete the content in aRangesToDelete.
   2721   * The result may include DeleteRangeTransaction (for deleting non-collapsed
   2722   * range), DeleteNodeTransactions and DeleteTextTransactions (for deleting
   2723   * collapsed range) as its children.
   2724   *
   2725   * @param aHowToHandleCollapsedRange
   2726   *                            How to handle collapsed ranges.
   2727   * @param aRangesToDelete     The ranges to delete content.
   2728   */
   2729  already_AddRefed<DeleteMultipleRangesTransaction>
   2730  CreateTransactionForDeleteSelection(
   2731      HowToHandleCollapsedRange aHowToHandleCollapsedRange,
   2732      const AutoClonedRangeArray& aRangesToDelete);
   2733 
   2734  /**
   2735   * Create a DeleteNodeTransaction or DeleteTextTransaction for removing a
   2736   * nodes or some text around aRangeToDelete.
   2737   *
   2738   * @param aCollapsedRange     The range to be removed.  This must be
   2739   *                            collapsed.
   2740   * @param aHowToHandleCollapsedRange
   2741   *                            How to handle aCollapsedRange.  Must
   2742   *                            be HowToHandleCollapsedRange::ExtendBackward or
   2743   *                            HowToHandleCollapsedRange::ExtendForward.
   2744   */
   2745  already_AddRefed<DeleteContentTransactionBase>
   2746  CreateTransactionForCollapsedRange(
   2747      const nsRange& aCollapsedRange,
   2748      HowToHandleCollapsedRange aHowToHandleCollapsedRange);
   2749 
   2750  /**
   2751   * ComputeInsertedRange() returns actual range modified by inserting string
   2752   * in a text node.  If mutation event listener changed the text data, this
   2753   * returns a range which covers all over the text data.
   2754   */
   2755  std::tuple<EditorDOMPointInText, EditorDOMPointInText> ComputeInsertedRange(
   2756      const EditorDOMPointInText& aInsertedPoint,
   2757      const nsAString& aInsertedString) const;
   2758 
   2759  /**
   2760   * EnsureComposition() should be called by composition event handlers.  This
   2761   * tries to get the composition for the event and set it to mComposition.
   2762   * However, this may fail because the composition may be committed before
   2763   * the event comes to the editor.
   2764   *
   2765   * @return            true if there is a composition.  Otherwise, for example,
   2766   *                    a composition event handler in web contents moved focus
   2767   *                    for committing the composition, returns false.
   2768   */
   2769  bool EnsureComposition(WidgetCompositionEvent& aCompositionEvent);
   2770 
   2771  /**
   2772   * See comment of IsCopyToClipboardAllowed() for the detail.
   2773   */
   2774  virtual bool IsCopyToClipboardAllowedInternal() const {
   2775    MOZ_ASSERT(IsEditActionDataAvailable());
   2776    return !SelectionRef().IsCollapsed();
   2777  }
   2778 
   2779  /**
   2780   * Helper for Is{Cut|Copy}CommandEnabled.
   2781   * Look for a listener for the given command, including up the target chain.
   2782   */
   2783  MOZ_CAN_RUN_SCRIPT bool CheckForClipboardCommandListener(
   2784      nsAtom* aCommand, EventMessage aEventMessage) const;
   2785 
   2786  /**
   2787   * DispatchClipboardEventAndUpdateClipboard() may dispatch a clipboard event
   2788   * and update clipboard if aEventMessage is eCopy or eCut.
   2789   *
   2790   * @param aEventMessage       The event message which may be set to the
   2791   *                            dispatching event.
   2792   * @param aClipboardType      Working with global clipboard or selection.
   2793   */
   2794  enum class ClipboardEventResult {
   2795    // We have met an error in nsCopySupport::FireClipboardEvent,
   2796    // or, default of dispatched event is NOT prevented, the event is "cut"
   2797    // and the event target is not editable.
   2798    IgnoredOrError,
   2799    // A "paste" event is dispatched and prevented its default.
   2800    DefaultPreventedOfPaste,
   2801    // Default of a "copy" or "cut" event is prevented but the clipboard is
   2802    // updated unless the dataTransfer of the event is cleared by the listener.
   2803    // Or, default of the event is NOT prevented but selection is collapsed
   2804    // when the event target is editable or the event is "copy".
   2805    CopyOrCutHandled,
   2806    // A clipboard event is maybe dispatched and not canceled by the web app.
   2807    // In this case, the clipboard has been updated if aEventMessage is eCopy
   2808    // or eCut.
   2809    DoDefault,
   2810  };
   2811  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<ClipboardEventResult, nsresult>
   2812  DispatchClipboardEventAndUpdateClipboard(
   2813      EventMessage aEventMessage,
   2814      mozilla::Maybe<nsIClipboard::ClipboardType> aClipboardType,
   2815      DataTransfer* aDataTransfer = nullptr);
   2816 
   2817  /**
   2818   * Called after PasteAsAction() dispatches "paste" event and it's not
   2819   * canceled.
   2820   */
   2821  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual nsresult HandlePaste(
   2822      AutoEditActionDataSetter& aEditActionData,
   2823      nsIClipboard::ClipboardType aClipboardType,
   2824      DataTransfer* aDataTransfer) = 0;
   2825 
   2826  /**
   2827   * Called after PasteAsQuotationAsAction() dispatches "paste" event and it's
   2828   * not canceled.
   2829   */
   2830  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual nsresult HandlePasteAsQuotation(
   2831      AutoEditActionDataSetter& aEditActionData,
   2832      nsIClipboard::ClipboardType aClipboardType,
   2833      DataTransfer* aDataTransfer) = 0;
   2834 
   2835  /**
   2836   * Called after PasteTransferableAsAction() dispatches "paste" event and
   2837   * it's not canceled.
   2838   */
   2839  [[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual nsresult HandlePasteTransferable(
   2840      AutoEditActionDataSetter& aEditActionData,
   2841      nsITransferable& aTransferable) = 0;
   2842 
   2843 private:
   2844  nsCOMPtr<nsISelectionController> mSelectionController;
   2845  RefPtr<Document> mDocument;
   2846 
   2847  AutoEditActionDataSetter* mEditActionData;
   2848 
   2849  /**
   2850   * SetTextDirectionTo() sets text-direction of the root element.
   2851   * Should use SwitchTextDirectionTo() or ToggleTextDirection() instead.
   2852   * This is a helper class of them.
   2853   */
   2854  MOZ_CAN_RUN_SCRIPT nsresult SetTextDirectionTo(TextDirection aTextDirection);
   2855 
   2856 protected:  // helper classes which may be used by friends
   2857  /**
   2858   * Stack based helper class for batching a collection of transactions
   2859   * inside a placeholder transaction.  Different from AutoTransactionBatch,
   2860   * this notifies editor observers of before/end edit action handling, and
   2861   * dispatches "input" event if it's necessary.
   2862   */
   2863  class MOZ_RAII AutoPlaceholderBatch final {
   2864   public:
   2865    /**
   2866     * @param aRequesterFuncName function name which wants to end the batch.
   2867     * This won't be stored nor exposed to selection listeners etc, used
   2868     * only for logging. This MUST be alive when the destructor runs.
   2869     */
   2870    AutoPlaceholderBatch(EditorBase& aEditorBase,
   2871                         ScrollSelectionIntoView aScrollSelectionIntoView,
   2872                         const char* aRequesterFuncName)
   2873        : mEditorBase(aEditorBase),
   2874          mScrollSelectionIntoView(aScrollSelectionIntoView),
   2875          mRequesterFuncName(aRequesterFuncName) {
   2876      mEditorBase->BeginPlaceholderTransaction(*nsGkAtoms::_empty,
   2877                                               mRequesterFuncName);
   2878    }
   2879 
   2880    AutoPlaceholderBatch(EditorBase& aEditorBase,
   2881                         nsStaticAtom& aTransactionName,
   2882                         ScrollSelectionIntoView aScrollSelectionIntoView,
   2883                         const char* aRequesterFuncName)
   2884        : mEditorBase(aEditorBase),
   2885          mScrollSelectionIntoView(aScrollSelectionIntoView),
   2886          mRequesterFuncName(aRequesterFuncName) {
   2887      mEditorBase->BeginPlaceholderTransaction(aTransactionName,
   2888                                               mRequesterFuncName);
   2889    }
   2890 
   2891    ~AutoPlaceholderBatch() {
   2892      mEditorBase->EndPlaceholderTransaction(mScrollSelectionIntoView,
   2893                                             mRequesterFuncName);
   2894    }
   2895 
   2896   protected:
   2897    const OwningNonNull<EditorBase> mEditorBase;
   2898    const ScrollSelectionIntoView mScrollSelectionIntoView;
   2899    const char* const mRequesterFuncName;
   2900  };
   2901 
   2902  /**
   2903   * AutoEditSubActionNotifier notifies editor of start to handle
   2904   * top level edit sub-action and end handling top level edit sub-action.
   2905   */
   2906  class MOZ_RAII AutoEditSubActionNotifier final {
   2907   public:
   2908    MOZ_CAN_RUN_SCRIPT AutoEditSubActionNotifier(
   2909        EditorBase& aEditorBase, EditSubAction aEditSubAction,
   2910        nsIEditor::EDirection aDirection, ErrorResult& aRv)
   2911        : mEditorBase(aEditorBase), mIsTopLevel(true) {
   2912      // The top level edit sub action has already be set if this is nested
   2913      // call
   2914      // XXX Looks like that this is not aware of unexpected nested edit
   2915      // action
   2916      //     handling via selectionchange event listener or mutation event
   2917      //     listener.
   2918      if (!mEditorBase.GetTopLevelEditSubAction()) {
   2919        MOZ_KnownLive(mEditorBase)
   2920            .OnStartToHandleTopLevelEditSubAction(aEditSubAction, aDirection,
   2921                                                  aRv);
   2922      } else {
   2923        mIsTopLevel = false;
   2924      }
   2925      mEditorBase.OnStartToHandleEditSubAction();
   2926    }
   2927 
   2928    MOZ_CAN_RUN_SCRIPT ~AutoEditSubActionNotifier() {
   2929      mEditorBase.OnEndHandlingEditSubAction();
   2930      if (mIsTopLevel) {
   2931        MOZ_KnownLive(mEditorBase).OnEndHandlingTopLevelEditSubAction();
   2932      }
   2933    }
   2934 
   2935   protected:
   2936    EditorBase& mEditorBase;
   2937    bool mIsTopLevel;
   2938  };
   2939 
   2940  /**
   2941   * Stack based helper class for turning off active selection adjustment
   2942   * by low level transactions
   2943   */
   2944  class MOZ_RAII AutoTransactionsConserveSelection final {
   2945   public:
   2946    explicit AutoTransactionsConserveSelection(EditorBase& aEditorBase)
   2947        : mEditorBase(aEditorBase),
   2948          mAllowedTransactionsToChangeSelection(
   2949              aEditorBase.AllowsTransactionsToChangeSelection()) {
   2950      mEditorBase.MakeThisAllowTransactionsToChangeSelection(false);
   2951    }
   2952 
   2953    ~AutoTransactionsConserveSelection() {
   2954      mEditorBase.MakeThisAllowTransactionsToChangeSelection(
   2955          mAllowedTransactionsToChangeSelection);
   2956    }
   2957 
   2958   protected:
   2959    EditorBase& mEditorBase;
   2960    bool mAllowedTransactionsToChangeSelection;
   2961  };
   2962 
   2963  /***************************************************************************
   2964   * stack based helper class for batching reflow and paint requests.
   2965   */
   2966  class MOZ_RAII AutoUpdateViewBatch final {
   2967   public:
   2968    /**
   2969     * @param aRequesterFuncName function name which wants to end the batch.
   2970     * This won't be stored nor exposed to selection listeners etc, used
   2971     * only for logging. This MUST be alive when the destructor runs.
   2972     */
   2973    MOZ_CAN_RUN_SCRIPT explicit AutoUpdateViewBatch(
   2974        EditorBase& aEditorBase, const char* aRequesterFuncName)
   2975        : mEditorBase(aEditorBase), mRequesterFuncName(aRequesterFuncName) {
   2976      mEditorBase.BeginUpdateViewBatch(mRequesterFuncName);
   2977    }
   2978 
   2979    MOZ_CAN_RUN_SCRIPT ~AutoUpdateViewBatch() {
   2980      MOZ_KnownLive(mEditorBase).EndUpdateViewBatch(mRequesterFuncName);
   2981    }
   2982 
   2983   protected:
   2984    EditorBase& mEditorBase;
   2985    const char* const mRequesterFuncName;
   2986  };
   2987 
   2988 protected:
   2989  enum Tristate { eTriUnset, eTriFalse, eTriTrue };
   2990 
   2991  // MIME type of the doc we are editing.
   2992  nsString mContentMIMEType;
   2993 
   2994  RefPtr<mozInlineSpellChecker> mInlineSpellChecker;
   2995  // Reference to text services document for mInlineSpellChecker.
   2996  RefPtr<TextServicesDocument> mTextServicesDocument;
   2997 
   2998  RefPtr<TransactionManager> mTransactionManager;
   2999  // Cached root node.
   3000  RefPtr<Element> mRootElement;
   3001 
   3002  // The form field as an event receiver.
   3003  nsCOMPtr<dom::EventTarget> mEventTarget;
   3004  RefPtr<EditorEventListener> mEventListener;
   3005  // Strong reference to placeholder for begin/end batch purposes.
   3006  RefPtr<PlaceholderTransaction> mPlaceholderTransaction;
   3007  // Name of placeholder transaction.
   3008  nsStaticAtom* mPlaceholderName;
   3009  // Saved selection state for placeholder transaction batching.
   3010  mozilla::Maybe<SelectionState> mSelState;
   3011  // IME composition this is not null between compositionstart and
   3012  // compositionend.
   3013  RefPtr<TextComposition> mComposition;
   3014 
   3015  RefPtr<TextInputListener> mTextInputListener;
   3016 
   3017  RefPtr<IMEContentObserver> mIMEContentObserver;
   3018 
   3019  // These members cache last encoder and its type for the performance in
   3020  // TextEditor::ComputeTextValue() which is the implementation of
   3021  // `<input>.value` and `<textarea>.value`.  See `GetAndInitDocEncoder()`.
   3022  mutable nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
   3023  mutable nsString mCachedDocumentEncoderType;
   3024 
   3025  // Listens to all low level actions on the doc.
   3026  // Edit action listener is currently used by highlighter of the findbar
   3027  // and the spellchecker.  So, we should reserve only 2 items.
   3028  using AutoActionListenerArray =
   3029      AutoTArray<OwningNonNull<nsIEditActionListener>, 2>;
   3030  AutoActionListenerArray mActionListeners;
   3031  // Listen to overall doc state (dirty or not, just created, etc.).
   3032  // Document state listener is currently used by FinderHighlighter and
   3033  // BlueGriffon so that reserving only one is enough.
   3034  using AutoDocumentStateListenerArray =
   3035      AutoTArray<OwningNonNull<nsIDocumentStateListener>, 1>;
   3036  AutoDocumentStateListenerArray mDocStateListeners;
   3037 
   3038  // Number of modifications (for undo/redo stack).
   3039  uint32_t mModCount;
   3040  // Behavior flags. See nsIEditor.idl for the flags we use.
   3041  uint32_t mFlags;
   3042 
   3043  int32_t mUpdateCount;
   3044 
   3045  // Nesting count for batching.
   3046  int32_t mPlaceholderBatch;
   3047 
   3048  int32_t mWrapColumn = 0;
   3049  int32_t mNewlineHandling;
   3050  int32_t mCaretStyle;
   3051 
   3052  // -1 = not initialized
   3053  int8_t mDocDirtyState;
   3054  // A Tristate value.
   3055  uint8_t mSpellcheckCheckboxState;
   3056 
   3057  // If true, initialization was succeeded.
   3058  bool mInitSucceeded;
   3059  // If false, transactions should not change Selection even after modifying
   3060  // the DOM tree.
   3061  bool mAllowsTransactionsToChangeSelection;
   3062  // Whether PreDestroy has been called.
   3063  bool mDidPreDestroy;
   3064  // Whether PostCreate has been called.
   3065  bool mDidPostCreate;
   3066  bool mDispatchInputEvent;
   3067  // True while the instance is handling an edit sub-action.
   3068  bool mIsInEditSubAction;
   3069  // Whether caret is hidden forcibly.
   3070  bool mHidingCaret;
   3071  // Whether spellchecker dictionary is initialized after focused.
   3072  bool mSpellCheckerDictionaryUpdated;
   3073  // Whether we are an HTML editor class.
   3074  bool mIsHTMLEditorClass;
   3075 
   3076  friend class AlignStateAtSelection;          // AutoEditActionDataSetter,
   3077                                               // ToGenericNSResult
   3078  friend class AutoClonedRangeArray;           // IsSEditActionDataAvailable,
   3079                                               // RangeUpdaterRef
   3080  friend class AutoClonedSelectionRangeArray;  // RangeUpdaterRef, SelectionRef
   3081  friend class AutoSelectionRestorer;   // RangeUpdaterRef, SavedSelectionRef
   3082  friend class CaretPoint;              // AllowsTransactionsToChangeSelection,
   3083                                        // CollapseSelectionTo
   3084  friend class CompositionTransaction;  // CollapseSelectionTo,
   3085                                        // DoDeleteText, DoInsertText,
   3086                                        // DoReplaceText, HideCaret,
   3087                                        // RangeUpdaterRef
   3088  friend class DeleteNodeTransaction;   // RangeUpdaterRef
   3089  friend class DeleteRangeTransaction;  // AllowsTransactionsToChangeSelection,
   3090                                        // CollapseSelectionTo
   3091  friend class DeleteTextTransaction;   // AllowsTransactionsToChangeSelection,
   3092                                        // DoDeleteText, DoInsertText,
   3093                                        // RangeUpdaterRef
   3094  friend class InsertNodeTransaction;   // AllowsTransactionsToChangeSelection,
   3095                                        // CollapseSelectionTo,
   3096                                        //  MarkElementDirty, ToGenericNSResult
   3097  friend class InsertTextTransaction;   // AllowsTransactionsToChangeSelection,
   3098                                        // CollapseSelectionTo, DoDeleteText,
   3099                                        // DoInsertText, RangeUpdaterRef
   3100  friend class ListElementSelectionState;      // AutoEditActionDataSetter,
   3101                                               // ToGenericNSResult
   3102  friend class ListItemElementSelectionState;  // AutoEditActionDataSetter,
   3103                                               // ToGenericNSResult
   3104  friend class MoveNodeTransaction;      // MarkElementDirty, ToGenericNSResult
   3105  friend class MoveSiblingsTransaction;  // MarkElementDirty, ToGenericNSResult
   3106  friend class ParagraphStateAtSelection;  // AutoEditActionDataSetter,
   3107                                           // ToGenericNSResult
   3108  friend class PendingStyles;              // GetEditAction,
   3109                                           // GetFirstSelectionStartPoint,
   3110                                           // SelectionRef
   3111  friend class ReplaceTextTransaction;  // AllowsTransactionsToChangeSelection,
   3112                                        // CollapseSelectionTo, DoReplaceText,
   3113                                        // RangeUpdaterRef
   3114  friend class SplitNodeTransaction;    // ToGenericNSResult
   3115  friend class
   3116      WhiteSpaceVisibilityKeeper;  // AutoTransactionsConserveSelection,
   3117                                   // ComputePointToInsertText
   3118  friend class nsIEditor;          // mIsHTMLEditorClass
   3119 };
   3120 
   3121 }  // namespace mozilla
   3122 
   3123 bool nsIEditor::IsTextEditor() const {
   3124  return !AsEditorBase()->mIsHTMLEditorClass;
   3125 }
   3126 
   3127 bool nsIEditor::IsHTMLEditor() const {
   3128  return AsEditorBase()->mIsHTMLEditorClass;
   3129 }
   3130 
   3131 mozilla::EditorBase* nsIEditor::AsEditorBase() {
   3132  return static_cast<mozilla::EditorBase*>(this);
   3133 }
   3134 
   3135 const mozilla::EditorBase* nsIEditor::AsEditorBase() const {
   3136  return static_cast<const mozilla::EditorBase*>(this);
   3137 }
   3138 
   3139 #endif  // #ifndef mozilla_EditorBase_h