tor-browser

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

TextEditor.h (25170B)


      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_TextEditor_h
      7 #define mozilla_TextEditor_h
      8 
      9 #include "mozilla/EditorBase.h"
     10 #include "mozilla/EditorForwards.h"
     11 #include "mozilla/TextControlState.h"
     12 #include "mozilla/UniquePtr.h"
     13 
     14 #include "nsCOMPtr.h"
     15 #include "nsCycleCollectionParticipant.h"
     16 #include "nsIClipboard.h"
     17 #include "nsINamed.h"
     18 #include "nsISupportsImpl.h"
     19 #include "nsITimer.h"
     20 #include "nscore.h"
     21 
     22 class nsIContent;
     23 class nsIDocumentEncoder;
     24 class nsIOutputStream;
     25 class nsIPrincipal;
     26 class nsISelectionController;
     27 class nsITransferable;
     28 
     29 namespace mozilla {
     30 namespace dom {
     31 class Selection;
     32 }  // namespace dom
     33 
     34 /**
     35 * The text editor implementation.
     36 * Use to edit text document represented as a DOM tree.
     37 */
     38 class TextEditor final : public EditorBase,
     39                         public nsITimerCallback,
     40                         public nsINamed {
     41 public:
     42  /****************************************************************************
     43   * NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other
     44   *       classes under libeditor except EditorEventListener and
     45   *       HTMLEditorEventListener because each public method which may fire
     46   *       eEditorInput event will need to instantiate new stack class for
     47   *       managing input type value of eEditorInput and cache some objects
     48   *       for smarter handling.  In other words, when you add new root
     49   *       method to edit the DOM tree, you can make your new method public.
     50   ****************************************************************************/
     51 
     52  NS_DECL_ISUPPORTS_INHERITED
     53  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextEditor, EditorBase)
     54 
     55  TextEditor();
     56 
     57  /**
     58   * Note that TextEditor::Init() shouldn't cause running script synchronously.
     59   * So, `MOZ_CAN_RUN_SCRIPT_BOUNDARY` is safe here.
     60   *
     61   * @param aDocument   The document which aAnonymousDivElement belongs to.
     62   * @param aAnonymousDivElement
     63   *                    The root editable element for this editor.
     64   * @param aSelectionController
     65   *                    The selection controller for independent selections
     66   *                    in the `<input>` or `<textarea>` element.
     67   * @param aFlags      Some of nsIEditor::eEditor*Mask flags.
     68   * @param aPasswordMaskData
     69   *                    Set to an instance only when aFlags includes
     70   *                    `nsIEditor::eEditorPasswordMask`.  Otherwise, must be
     71   *                    `nullptr`.
     72   */
     73  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
     74  Init(Document& aDocument, Element& aAnonymousDivElement,
     75       nsISelectionController& aSelectionController, uint32_t aFlags,
     76       UniquePtr<PasswordMaskData>&& aPasswordMaskData);
     77 
     78  /**
     79   * PostCreate() should be called after Init, and is the time that the editor
     80   * tells its documentStateObservers that the document has been created.
     81   * Note that TextEditor::PostCreate() shouldn't cause running script
     82   * synchronously. So, `MOZ_CAN_RUN_SCRIPT_BOUNDARY` is safe here.
     83   */
     84  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult PostCreate();
     85 
     86  /**
     87   * This method re-initializes the selection and caret state that are for
     88   * current editor state. When editor session is destroyed, it always reset
     89   * selection state even if this has no focus.  So if destroying editor,
     90   * we have to call this method for focused editor to set selection state.
     91   */
     92  MOZ_CAN_RUN_SCRIPT void ReinitializeSelection(Element& aElement);
     93 
     94  /**
     95   * PreDestroy() is called before the editor goes away, and gives the editor a
     96   * chance to tell its documentStateObservers that the document is going away.
     97   * Note that TextEditor::PreDestroy() shouldn't cause running script
     98   * synchronously. So, `MOZ_CAN_RUN_SCRIPT_BOUNDARY` is safe here.
     99   */
    100  [[nodiscard]] MOZ_CAN_RUN_SCRIPT_BOUNDARY UniquePtr<PasswordMaskData>
    101  PreDestroy();
    102 
    103  static TextEditor* GetFrom(nsIEditor* aEditor) {
    104    return aEditor ? aEditor->GetAsTextEditor() : nullptr;
    105  }
    106  static const TextEditor* GetFrom(const nsIEditor* aEditor) {
    107    return aEditor ? aEditor->GetAsTextEditor() : nullptr;
    108  }
    109 
    110  /**
    111   * Helper method for `AppendString()` and `AppendSubString()`.  This should
    112   * be called only when `aText` is in a password field.  This method masks
    113   * A part of or all of `aText` (`aStartOffsetInText` and later) should've
    114   * been copied (appended) to `aString`.  `aStartOffsetInString` is where
    115   * the password was appended into `aString`.
    116   */
    117  static void MaskString(nsString& aString, const dom::Text& aTextNode,
    118                         uint32_t aStartOffsetInString,
    119                         uint32_t aStartOffsetInText);
    120 
    121  NS_DECL_NSITIMERCALLBACK
    122  NS_DECL_NSINAMED
    123 
    124  // Overrides of nsIEditor
    125  MOZ_CAN_RUN_SCRIPT NS_IMETHOD EndOfDocument() final;
    126  MOZ_CAN_RUN_SCRIPT NS_IMETHOD InsertLineBreak() final;
    127  NS_IMETHOD GetTextLength(uint32_t* aCount) final;
    128 
    129  // Shouldn't be used internally, but we need these using declarations for
    130  // avoiding warnings of clang.
    131  using EditorBase::CanCopy;
    132  using EditorBase::CanCut;
    133  using EditorBase::CanPaste;
    134 
    135  // Overrides of EditorBase
    136  bool IsEmpty() const final;
    137 
    138  bool CanPaste(nsIClipboard::ClipboardType aClipboardType) const final;
    139 
    140  bool CanPasteTransferable(nsITransferable* aTransferable) final;
    141 
    142  MOZ_CAN_RUN_SCRIPT nsresult
    143  HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent) final;
    144 
    145  dom::EventTarget* GetDOMEventTarget() const final;
    146 
    147  MOZ_CAN_RUN_SCRIPT nsresult
    148  OnFocus(const nsINode& aOriginalEventTargetNode) final;
    149 
    150  nsresult OnBlur(const dom::EventTarget* aEventTarget) final;
    151 
    152  [[nodiscard]] Result<widget::IMEState, nsresult> GetPreferredIMEState()
    153      const final;
    154 
    155  /**
    156   * The maximum number of characters allowed.
    157   *   default: -1 (unlimited).
    158   */
    159  int32_t MaxTextLength() const { return mMaxTextLength; }
    160  void SetMaxTextLength(int32_t aLength) { mMaxTextLength = aLength; }
    161 
    162  /**
    163   * This updates the wrap width used for initializing a document encoder within
    164   * a call of EditorBase::GetAndInitDocEncoder().
    165   */
    166  void SetWrapColumn(int32_t aWrapColumn) { mWrapColumn = aWrapColumn; }
    167 
    168  /**
    169   * Replace existed string with a string.
    170   * This is fast path to replace all string when using single line control.
    171   *
    172   * @param aString             The string to be set
    173   * @param aAllowBeforeInputEventCancelable
    174   *                            Whether `beforeinput` event which will be
    175   *                            dispatched for this can be cancelable or not.
    176   * @param aPrincipal          Set subject principal if it may be called by
    177   *                            JS.  If set to nullptr, will be treated as
    178   *                            called by system.
    179   */
    180  MOZ_CAN_RUN_SCRIPT nsresult SetTextAsAction(
    181      const nsAString& aString,
    182      AllowBeforeInputEventCancelable aAllowBeforeInputEventCancelable,
    183      nsIPrincipal* aPrincipal = nullptr);
    184 
    185  MOZ_CAN_RUN_SCRIPT nsresult
    186  InsertLineBreakAsAction(nsIPrincipal* aPrincipal = nullptr) final;
    187 
    188  /**
    189   * ComputeTextValue() computes plaintext value of this editor.
    190   */
    191  nsresult ComputeTextValue(nsAString&) const;
    192 
    193  /**
    194   * The following methods are available only when the instance is a password
    195   * editor.  They return whether there is unmasked range or not and range
    196   * start and length.
    197   */
    198  MOZ_ALWAYS_INLINE bool IsAllMasked() const {
    199    MOZ_ASSERT(IsPasswordEditor());
    200    return !mPasswordMaskData || mPasswordMaskData->IsAllMasked();
    201  }
    202  MOZ_ALWAYS_INLINE uint32_t UnmaskedStart() const {
    203    MOZ_ASSERT(IsPasswordEditor());
    204    return mPasswordMaskData ? mPasswordMaskData->mUnmaskedStart : UINT32_MAX;
    205  }
    206  MOZ_ALWAYS_INLINE uint32_t UnmaskedLength() const {
    207    MOZ_ASSERT(IsPasswordEditor());
    208    return mPasswordMaskData ? mPasswordMaskData->mUnmaskedLength : 0;
    209  }
    210  MOZ_ALWAYS_INLINE uint32_t UnmaskedEnd() const {
    211    MOZ_ASSERT(IsPasswordEditor());
    212    return mPasswordMaskData ? mPasswordMaskData->UnmaskedEnd() : UINT32_MAX;
    213  }
    214 
    215  /**
    216   * IsMaskingPassword() returns false when the last caller of `Unmask()`
    217   * didn't want to mask again automatically.  When this returns true, user
    218   * input causes masking the password even before timed-out.
    219   */
    220  bool IsMaskingPassword() const {
    221    MOZ_ASSERT(IsPasswordEditor());
    222    return mPasswordMaskData && mPasswordMaskData->mIsMaskingPassword;
    223  }
    224 
    225  /**
    226   * PasswordMask() returns a character which masks each character in password
    227   * fields.
    228   */
    229  static char16_t PasswordMask();
    230 
    231  /**
    232   * If you want to prevent to echo password temporarily, use the following
    233   * methods.
    234   */
    235  bool EchoingPasswordPrevented() const {
    236    return mPasswordMaskData && mPasswordMaskData->mEchoingPasswordPrevented;
    237  }
    238  void PreventToEchoPassword() {
    239    if (mPasswordMaskData) {
    240      mPasswordMaskData->mEchoingPasswordPrevented = true;
    241    }
    242  }
    243  void AllowToEchoPassword() {
    244    if (mPasswordMaskData) {
    245      mPasswordMaskData->mEchoingPasswordPrevented = false;
    246    }
    247  }
    248 
    249  /**
    250   * Return the `Text` node in the anonymous <div>.  Note that the anonymous
    251   * <div> can have only one `Text` for the storage of the value of this editor.
    252   */
    253  enum class IgnoreTextNodeCache : bool { No, Yes };
    254  dom::Text* GetTextNode(
    255      IgnoreTextNodeCache aIgnoreTextNodeCache = IgnoreTextNodeCache::No) {
    256    if (aIgnoreTextNodeCache == IgnoreTextNodeCache::No) {
    257      if (Text* const cachedTextNode = GetCachedTextNode()) {
    258        return cachedTextNode;
    259      }
    260    }
    261    MOZ_DIAGNOSTIC_ASSERT(GetRoot());
    262    MOZ_DIAGNOSTIC_ASSERT(GetRoot()->GetFirstChild());
    263    MOZ_DIAGNOSTIC_ASSERT(GetRoot()->GetFirstChild()->IsText());
    264    if (MOZ_UNLIKELY(!GetRoot() || !GetRoot()->GetFirstChild())) {
    265      return nullptr;
    266    }
    267    return GetRoot()->GetFirstChild()->GetAsText();
    268  }
    269  const dom::Text* GetTextNode(IgnoreTextNodeCache aIgnoreTextNodeCache =
    270                                   IgnoreTextNodeCache::No) const {
    271    return const_cast<TextEditor*>(this)->GetTextNode(aIgnoreTextNodeCache);
    272  }
    273 
    274 protected:  // May be called by friends.
    275  /****************************************************************************
    276   * Some friend classes are allowed to call the following protected methods.
    277   * However, those methods won't prepare caches of some objects which are
    278   * necessary for them.  So, if you call them from friend classes, you need
    279   * to make sure that AutoEditActionDataSetter is created.
    280   ****************************************************************************/
    281 
    282  // Overrides of EditorBase
    283  MOZ_CAN_RUN_SCRIPT nsresult RemoveAttributeOrEquivalent(
    284      Element* aElement, nsAtom* aAttribute, bool aSuppressTransaction) final;
    285  MOZ_CAN_RUN_SCRIPT nsresult SetAttributeOrEquivalent(
    286      Element* aElement, nsAtom* aAttribute, const nsAString& aValue,
    287      bool aSuppressTransaction) final;
    288  using EditorBase::RemoveAttributeOrEquivalent;
    289  using EditorBase::SetAttributeOrEquivalent;
    290 
    291  /**
    292   * FindBetterInsertionPoint() tries to look for better insertion point which
    293   * is typically the nearest text node and offset in it.
    294   *
    295   * @param aPoint      Insertion point which the callers found.
    296   * @return            Better insertion point if there is.  If not returns
    297   *                    same point as aPoint.
    298   */
    299  template <typename EditorDOMPointType>
    300  EditorDOMPointType FindBetterInsertionPoint(
    301      const EditorDOMPointType& aPoint) const;
    302 
    303  /**
    304   * InsertLineBreakAsSubAction() inserts a line break.
    305   */
    306  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InsertLineBreakAsSubAction();
    307 
    308  /**
    309   * Replace existed string with aString.  Caller must guarantee that there
    310   * is a placeholder transaction which will have the transaction.
    311   *
    312   * @ param aString   The string to be set.
    313   */
    314  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
    315  SetTextAsSubAction(const nsAString& aString);
    316 
    317  /**
    318   * MaybeDoAutoPasswordMasking() may mask password if we're doing auto-masking.
    319   */
    320  void MaybeDoAutoPasswordMasking() {
    321    if (IsPasswordEditor() && IsMaskingPassword()) {
    322      MaskAllCharacters();
    323    }
    324  }
    325 
    326  /**
    327   * SetUnmaskRange() is available only when the instance is a password
    328   * editor.  This just updates unmask range.  I.e., caller needs to
    329   * guarantee to update the layout.
    330   *
    331   * @param aStart      First index to show the character.
    332   *                    If aLength is 0, this value is ignored.
    333   * @param aLength     Optional, Length to show characters.
    334   *                    If UINT32_MAX, it means unmasking all characters after
    335   *                    aStart.
    336   *                    If 0, it means that masking all characters.
    337   * @param aTimeout    Optional, specify milliseconds to hide the unmasked
    338   *                    characters after this call.
    339   *                    If 0, it means this won't mask the characters
    340   *                    automatically.
    341   *                    If aLength is 0, this value is ignored.
    342   */
    343  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult SetUnmaskRange(
    344      uint32_t aStart, uint32_t aLength = UINT32_MAX, uint32_t aTimeout = 0) {
    345    return SetUnmaskRangeInternal(aStart, aLength, aTimeout, false, false);
    346  }
    347 
    348  /**
    349   * SetUnmaskRangeAndNotify() is available only when the instance is a
    350   * password editor.  This updates unmask range and notifying the text frame
    351   * to update the visible characters.
    352   *
    353   * @param aStart      First index to show the character.
    354   *                    If UINT32_MAX, it means masking all.
    355   * @param aLength     Optional, Length to show characters.
    356   *                    If UINT32_MAX, it means unmasking all characters after
    357   *                    aStart.
    358   * @param aTimeout    Optional, specify milliseconds to hide the unmasked
    359   *                    characters after this call.
    360   *                    If 0, it means this won't mask the characters
    361   *                    automatically.
    362   *                    If aLength is 0, this value is ignored.
    363   */
    364  MOZ_CAN_RUN_SCRIPT nsresult SetUnmaskRangeAndNotify(
    365      uint32_t aStart, uint32_t aLength = UINT32_MAX, uint32_t aTimeout = 0) {
    366    return SetUnmaskRangeInternal(aStart, aLength, aTimeout, true, false);
    367  }
    368 
    369  /**
    370   * MaskAllCharacters() is an alias of SetUnmaskRange() to mask all characters.
    371   * In other words, this removes existing unmask range.
    372   * After this is called, TextEditor starts masking password automatically.
    373   */
    374  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult MaskAllCharacters() {
    375    if (!mPasswordMaskData) {
    376      return NS_OK;  // Already we don't have masked range data.
    377    }
    378    return SetUnmaskRangeInternal(UINT32_MAX, 0, 0, false, true);
    379  }
    380 
    381  /**
    382   * MaskAllCharactersAndNotify() is an alias of SetUnmaskRangeAndNotify() to
    383   * mask all characters and notifies the text frame.  In other words, this
    384   * removes existing unmask range.
    385   * After this is called, TextEditor starts masking password automatically.
    386   */
    387  MOZ_CAN_RUN_SCRIPT nsresult MaskAllCharactersAndNotify() {
    388    return SetUnmaskRangeInternal(UINT32_MAX, 0, 0, true, true);
    389  }
    390 
    391  /**
    392   * WillDeleteText() is called before `DeleteTextTransaction` or something
    393   * removes text in a text node.  Note that this won't be called if the
    394   * instance is `HTMLEditor` since supporting it makes the code complicated
    395   * due to mutation events.
    396   *
    397   * @param aCurrentLength      Current text length of the node.
    398   * @param aRemoveStartOffset  Start offset of the range to be removed.
    399   * @param aRemoveLength       Length of the range to be removed.
    400   */
    401  void WillDeleteText(uint32_t aCurrentLength, uint32_t aRemoveStartOffset,
    402                      uint32_t aRemoveLength);
    403 
    404  /**
    405   * DidInsertText() is called after `InsertTextTransaction` or something
    406   * inserts text into a text node.  Note that this won't be called if the
    407   * instance is `HTMLEditor` since supporting it makes the code complicated
    408   * due to mutatione events.
    409   *
    410   * @param aNewLength          New text length after the insertion.
    411   * @param aInsertedOffset     Start offset of the inserted text.
    412   * @param aInsertedLength     Length of the inserted text.
    413   * @return                    NS_OK or NS_ERROR_EDITOR_DESTROYED.
    414   */
    415  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult DidInsertText(
    416      uint32_t aNewLength, uint32_t aInsertedOffset, uint32_t aInsertedLength);
    417 
    418 protected:  // edit sub-action handler
    419  /**
    420   * MaybeTruncateInsertionStringForMaxLength() truncates aInsertionString to
    421   * `maxlength` if it was not pasted in by the user.
    422   *
    423   * @param aInsertionString    [in/out] New insertion string.  This is
    424   *                            truncated to `maxlength` if it was not pasted in
    425   *                            by the user.
    426   * @return                    If aInsertionString is truncated, it returns "as
    427   *                            handled", else "as ignored."
    428   */
    429  Result<EditActionResult, nsresult> MaybeTruncateInsertionStringForMaxLength(
    430      nsAString& aInsertionString);
    431 
    432  /**
    433   * InsertLineFeedCharacterAtSelection() inserts a linefeed character at
    434   * selection.
    435   */
    436  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
    437  InsertLineFeedCharacterAtSelection();
    438 
    439  /**
    440   * Handles the newline characters according to the default system prefs
    441   * (editor.singleLine.pasteNewlines).
    442   * Each value means:
    443   *   nsIEditor::eNewlinesReplaceWithSpaces (2, Firefox default):
    444   *     replace newlines with spaces.
    445   *   nsIEditor::eNewlinesStrip (3):
    446   *     remove newlines from the string.
    447   *   nsIEditor::eNewlinesReplaceWithCommas (4, Thunderbird default):
    448   *     replace newlines with commas.
    449   *   nsIEditor::eNewlinesStripSurroundingWhitespace (5):
    450   *     collapse newlines and surrounding white-space characters and
    451   *     remove them from the string.
    452   *   nsIEditor::eNewlinesPasteIntact (0):
    453   *     only remove the leading and trailing newlines.
    454   *   nsIEditor::eNewlinesPasteToFirst (1) or any other value:
    455   *     remove the first newline and all characters following it.
    456   *
    457   * @param aString the string to be modified in place.
    458   */
    459  void HandleNewLinesInStringForSingleLineEditor(nsString& aString) const;
    460 
    461  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
    462  HandleInsertText(const nsAString& aInsertionString,
    463                   InsertTextFor aPurpose) final;
    464 
    465  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InsertDroppedDataTransferAsAction(
    466      AutoEditActionDataSetter& aEditActionData, DataTransfer& aDataTransfer,
    467      const EditorDOMPoint& aDroppedAt, nsIPrincipal* aSourcePrincipal) final;
    468 
    469  /**
    470   * HandleDeleteSelectionInternal() is a helper method of
    471   * HandleDeleteSelection().  Must be called only when the instance is
    472   * TextEditor.
    473   * NOTE: This method creates SelectionBatcher.  Therefore, each caller
    474   *       needs to check if the editor is still available even if this returns
    475   *       NS_OK.
    476   */
    477  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
    478  HandleDeleteSelectionInternal(nsIEditor::EDirection aDirectionAndAmount,
    479                                nsIEditor::EStripWrappers aStripWrappers);
    480 
    481  /**
    482   * This method handles "delete selection" commands.
    483   *
    484   * @param aDirectionAndAmount Direction of the deletion.
    485   * @param aStripWrappers      Must be nsIEditor::eNoStrip.
    486   */
    487  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
    488  HandleDeleteSelection(nsIEditor::EDirection aDirectionAndAmount,
    489                        nsIEditor::EStripWrappers aStripWrappers) final;
    490 
    491  /**
    492   * ComputeValueFromTextNodeAndBRElement() tries to compute "value" of
    493   * this editor content only with text nodes and `<br>` elements.
    494   * If this succeeds to compute the value, it's returned with aValue and
    495   * the result is marked as "handled".  Otherwise, the caller needs to
    496   * compute it with another way.
    497   */
    498  Result<EditActionResult, nsresult> ComputeValueFromTextNodeAndBRElement(
    499      nsAString& aValue) const;
    500 
    501  /**
    502   * SetTextWithoutTransaction() is optimized method to set `<input>.value`
    503   * and `<textarea>.value` to aValue without transaction.  This must be
    504   * called only when it's not `HTMLEditor` and undo/redo is disabled.
    505   */
    506  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
    507  SetTextWithoutTransaction(const nsAString& aValue);
    508 
    509  /**
    510   * EnsureCaretNotAtEndOfTextNode() collapses selection at the padding `<br>`
    511   * element (i.e., container becomes the anonymous `<div>` element) if
    512   * `Selection` is at end of the text node.
    513   */
    514  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult EnsureCaretNotAtEndOfTextNode();
    515 
    516 protected:  // Called by helper classes.
    517  MOZ_CAN_RUN_SCRIPT void OnStartToHandleTopLevelEditSubAction(
    518      EditSubAction aTopLevelEditSubAction,
    519      nsIEditor::EDirection aDirectionOfTopLevelEditSubAction,
    520      ErrorResult& aRv) final;
    521  MOZ_CAN_RUN_SCRIPT nsresult OnEndHandlingTopLevelEditSubAction() final;
    522 
    523  /**
    524   * HandleInlineSpellCheckAfterEdit() does spell-check after handling top level
    525   * edit subaction.
    526   */
    527  nsresult HandleInlineSpellCheckAfterEdit() {
    528    MOZ_ASSERT(IsEditActionDataAvailable());
    529    if (!GetSpellCheckRestartPoint().IsSet()) {
    530      return NS_OK;  // Maybe being initialized.
    531    }
    532    nsresult rv = HandleInlineSpellCheck(GetSpellCheckRestartPoint());
    533    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to spellcheck");
    534    ClearSpellCheckRestartPoint();
    535    return rv;
    536  }
    537 
    538 protected:  // Shouldn't be used by friend classes
    539  virtual ~TextEditor();
    540 
    541  /**
    542   * CanEchoPasswordNow() returns true if currently we can echo password.
    543   * If it's direct user input such as pasting or dropping text, this
    544   * returns false even if we may echo password.
    545   */
    546  bool CanEchoPasswordNow() const;
    547 
    548  /**
    549   * InitEditorContentAndSelection() may insert a padding `<br>` element for
    550   * if it's required in the anonymous `<div>` element or `<body>` element and
    551   * collapse selection at the end if there is no selection ranges.
    552   */
    553  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InitEditorContentAndSelection();
    554 
    555  /**
    556   * Collapse `Selection` to end of the text node in the anonymous <div>
    557   * element.
    558   */
    559  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult CollapseSelectionToEndOfTextNode();
    560 
    561  /**
    562   * Make the given selection span the entire document.
    563   */
    564  MOZ_CAN_RUN_SCRIPT nsresult SelectEntireDocument() final;
    565 
    566  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
    567  HandlePaste(AutoEditActionDataSetter& aEditActionData,
    568              nsIClipboard::ClipboardType aClipboardType,
    569              DataTransfer* aDataTransfer) final;
    570  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
    571  HandlePasteAsQuotation(AutoEditActionDataSetter& aEditActionData,
    572                         nsIClipboard::ClipboardType aClipboardType,
    573                         DataTransfer* aDataTransfer) final;
    574  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
    575  HandlePasteTransferable(AutoEditActionDataSetter& aEditActionData,
    576                          nsITransferable& aTransferable) final;
    577 
    578  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
    579  InsertWithQuotationsAsSubAction(const nsAString& aQuotedText) final;
    580 
    581  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
    582  InsertTextFromTransferable(nsITransferable* transferable);
    583 
    584  bool IsCopyToClipboardAllowedInternal() const final;
    585 
    586  already_AddRefed<Element> GetInputEventTargetElement() const final;
    587 
    588  /**
    589   * See SetUnmaskRange() and SetUnmaskRangeAndNotify() for the detail.
    590   *
    591   * @param aForceStartMasking  If true, forcibly starts masking.  This should
    592   *                            be used only when `nsIEditor::Mask()` is called.
    593   */
    594  MOZ_CAN_RUN_SCRIPT nsresult SetUnmaskRangeInternal(uint32_t aStart,
    595                                                     uint32_t aLength,
    596                                                     uint32_t aTimeout,
    597                                                     bool aNotify,
    598                                                     bool aForceStartMasking);
    599 
    600  MOZ_ALWAYS_INLINE bool HasAutoMaskingTimer() const {
    601    return mPasswordMaskData && mPasswordMaskData->mTimer;
    602  }
    603 
    604 protected:
    605  UniquePtr<PasswordMaskData> mPasswordMaskData;
    606 
    607  int32_t mMaxTextLength = -1;
    608 
    609  friend class AutoClonedSelectionRangeArray;  // FindBetterInsertionPoint
    610  friend class DeleteNodeTransaction;
    611  friend class EditorBase;
    612  friend class InsertNodeTransaction;
    613 };
    614 
    615 }  // namespace mozilla
    616 
    617 mozilla::TextEditor* nsIEditor::AsTextEditor() {
    618  MOZ_DIAGNOSTIC_ASSERT(IsTextEditor());
    619  return static_cast<mozilla::TextEditor*>(this);
    620 }
    621 
    622 const mozilla::TextEditor* nsIEditor::AsTextEditor() const {
    623  MOZ_DIAGNOSTIC_ASSERT(IsTextEditor());
    624  return static_cast<const mozilla::TextEditor*>(this);
    625 }
    626 
    627 mozilla::TextEditor* nsIEditor::GetAsTextEditor() {
    628  return AsEditorBase()->IsTextEditor() ? AsTextEditor() : nullptr;
    629 }
    630 
    631 const mozilla::TextEditor* nsIEditor::GetAsTextEditor() const {
    632  return AsEditorBase()->IsTextEditor() ? AsTextEditor() : nullptr;
    633 }
    634 
    635 #endif  // #ifndef mozilla_TextEditor_h