summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/TextEditor.h
diff options
context:
space:
mode:
Diffstat (limited to 'editor/libeditor/TextEditor.h')
-rw-r--r--editor/libeditor/TextEditor.h623
1 files changed, 623 insertions, 0 deletions
diff --git a/editor/libeditor/TextEditor.h b/editor/libeditor/TextEditor.h
new file mode 100644
index 0000000000..c64740e573
--- /dev/null
+++ b/editor/libeditor/TextEditor.h
@@ -0,0 +1,623 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_TextEditor_h
+#define mozilla_TextEditor_h
+
+#include "mozilla/EditorBase.h"
+#include "mozilla/EditorForwards.h"
+#include "mozilla/TextControlState.h"
+#include "mozilla/UniquePtr.h"
+
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsINamed.h"
+#include "nsISupportsImpl.h"
+#include "nsITimer.h"
+#include "nscore.h"
+
+class nsIContent;
+class nsIDocumentEncoder;
+class nsIOutputStream;
+class nsIPrincipal;
+class nsISelectionController;
+class nsITransferable;
+
+namespace mozilla {
+namespace dom {
+class Selection;
+} // namespace dom
+
+/**
+ * The text editor implementation.
+ * Use to edit text document represented as a DOM tree.
+ */
+class TextEditor final : public EditorBase,
+ public nsITimerCallback,
+ public nsINamed {
+ public:
+ /****************************************************************************
+ * NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other
+ * classes under libeditor except EditorEventListener and
+ * HTMLEditorEventListener because each public method which may fire
+ * eEditorInput event will need to instantiate new stack class for
+ * managing input type value of eEditorInput and cache some objects
+ * for smarter handling. In other words, when you add new root
+ * method to edit the DOM tree, you can make your new method public.
+ ****************************************************************************/
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextEditor, EditorBase)
+
+ TextEditor();
+
+ /**
+ * Note that TextEditor::Init() shouldn't cause running script synchronously.
+ * So, `MOZ_CAN_RUN_SCRIPT_BOUNDARY` is safe here.
+ *
+ * @param aDocument The document which aAnonymousDivElement belongs to.
+ * @param aAnonymousDivElement
+ * The root editable element for this editor.
+ * @param aSelectionController
+ * The selection controller for independent selections
+ * in the `<input>` or `<textarea>` element.
+ * @param aFlags Some of nsIEditor::eEditor*Mask flags.
+ * @param aPasswordMaskData
+ * Set to an instance only when aFlags includes
+ * `nsIEditor::eEditorPasswordMask`. Otherwise, must be
+ * `nullptr`.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
+ Init(Document& aDocument, Element& aAnonymousDivElement,
+ nsISelectionController& aSelectionController, uint32_t aFlags,
+ UniquePtr<PasswordMaskData>&& aPasswordMaskData);
+
+ /**
+ * PostCreate() should be called after Init, and is the time that the editor
+ * tells its documentStateObservers that the document has been created.
+ * Note that TextEditor::PostCreate() shouldn't cause running script
+ * synchronously. So, `MOZ_CAN_RUN_SCRIPT_BOUNDARY` is safe here.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult PostCreate();
+
+ /**
+ * This method re-initializes the selection and caret state that are for
+ * current editor state. When editor session is destroyed, it always reset
+ * selection state even if this has no focus. So if destroying editor,
+ * we have to call this method for focused editor to set selection state.
+ */
+ MOZ_CAN_RUN_SCRIPT void ReinitializeSelection(Element& aElement);
+
+ /**
+ * PreDestroy() is called before the editor goes away, and gives the editor a
+ * chance to tell its documentStateObservers that the document is going away.
+ * Note that TextEditor::PreDestroy() shouldn't cause running script
+ * synchronously. So, `MOZ_CAN_RUN_SCRIPT_BOUNDARY` is safe here.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT_BOUNDARY UniquePtr<PasswordMaskData>
+ PreDestroy();
+
+ static TextEditor* GetFrom(nsIEditor* aEditor) {
+ return aEditor ? aEditor->GetAsTextEditor() : nullptr;
+ }
+ static const TextEditor* GetFrom(const nsIEditor* aEditor) {
+ return aEditor ? aEditor->GetAsTextEditor() : nullptr;
+ }
+
+ /**
+ * Helper method for `AppendString()` and `AppendSubString()`. This should
+ * be called only when `aText` is in a password field. This method masks
+ * A part of or all of `aText` (`aStartOffsetInText` and later) should've
+ * been copied (appended) to `aString`. `aStartOffsetInString` is where
+ * the password was appended into `aString`.
+ */
+ static void MaskString(nsString& aString, const dom::Text& aTextNode,
+ uint32_t aStartOffsetInString,
+ uint32_t aStartOffsetInText);
+
+ NS_DECL_NSITIMERCALLBACK
+ NS_DECL_NSINAMED
+
+ // Overrides of nsIEditor
+ MOZ_CAN_RUN_SCRIPT NS_IMETHOD EndOfDocument() final;
+ MOZ_CAN_RUN_SCRIPT NS_IMETHOD InsertLineBreak() final;
+ NS_IMETHOD GetTextLength(uint32_t* aCount) final;
+ MOZ_CAN_RUN_SCRIPT NS_IMETHOD Paste(int32_t aClipboardType) final {
+ const nsresult rv = TextEditor::PasteAsAction(aClipboardType, true);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "HTMLEditor::PasteAsAction() failed");
+ return rv;
+ }
+
+ // Shouldn't be used internally, but we need these using declarations for
+ // avoiding warnings of clang.
+ using EditorBase::CanCopy;
+ using EditorBase::CanCut;
+ using EditorBase::CanPaste;
+
+ // Overrides of EditorBase
+ bool IsEmpty() const final;
+
+ bool CanPaste(int32_t aClipboardType) const final;
+
+ MOZ_CAN_RUN_SCRIPT nsresult PasteTransferableAsAction(
+ nsITransferable* aTransferable, nsIPrincipal* aPrincipal = nullptr) final;
+
+ bool CanPasteTransferable(nsITransferable* aTransferable) final;
+
+ MOZ_CAN_RUN_SCRIPT nsresult
+ HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent) final;
+
+ dom::EventTarget* GetDOMEventTarget() const final;
+
+ MOZ_CAN_RUN_SCRIPT nsresult
+ PasteAsAction(int32_t aClipboardType, bool aDispatchPasteEvent,
+ nsIPrincipal* aPrincipal = nullptr) final;
+
+ MOZ_CAN_RUN_SCRIPT nsresult
+ PasteAsQuotationAsAction(int32_t aClipboardType, bool aDispatchPasteEvent,
+ nsIPrincipal* aPrincipal = nullptr) final;
+
+ MOZ_CAN_RUN_SCRIPT nsresult
+ OnFocus(const nsINode& aOriginalEventTargetNode) final;
+
+ nsresult OnBlur(const dom::EventTarget* aEventTarget) final;
+
+ /**
+ * The maximum number of characters allowed.
+ * default: -1 (unlimited).
+ */
+ int32_t MaxTextLength() const { return mMaxTextLength; }
+ void SetMaxTextLength(int32_t aLength) { mMaxTextLength = aLength; }
+
+ /**
+ * Replace existed string with a string.
+ * This is fast path to replace all string when using single line control.
+ *
+ * @param aString The string to be set
+ * @param aAllowBeforeInputEventCancelable
+ * Whether `beforeinput` event which will be
+ * dispatched for this can be cancelable or not.
+ * @param aPrincipal Set subject principal if it may be called by
+ * JS. If set to nullptr, will be treated as
+ * called by system.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult SetTextAsAction(
+ const nsAString& aString,
+ AllowBeforeInputEventCancelable aAllowBeforeInputEventCancelable,
+ nsIPrincipal* aPrincipal = nullptr);
+
+ MOZ_CAN_RUN_SCRIPT nsresult
+ InsertLineBreakAsAction(nsIPrincipal* aPrincipal = nullptr) final;
+
+ /**
+ * ComputeTextValue() computes plaintext value of this editor. This may be
+ * too expensive if it's in hot path.
+ *
+ * @param aDocumentEncoderFlags Flags of nsIDocumentEncoder.
+ * @param aCharset Encoding of the document.
+ */
+ nsresult ComputeTextValue(uint32_t aDocumentEncoderFlags,
+ nsAString& aOutputString) const {
+ AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
+ if (NS_WARN_IF(!editActionData.CanHandle())) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsresult rv = ComputeValueInternal(u"text/plain"_ns, aDocumentEncoderFlags,
+ aOutputString);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return EditorBase::ToGenericNSResult(rv);
+ }
+ return NS_OK;
+ }
+
+ /**
+ * The following methods are available only when the instance is a password
+ * editor. They return whether there is unmasked range or not and range
+ * start and length.
+ */
+ MOZ_ALWAYS_INLINE bool IsAllMasked() const {
+ MOZ_ASSERT(IsPasswordEditor());
+ return !mPasswordMaskData || mPasswordMaskData->IsAllMasked();
+ }
+ MOZ_ALWAYS_INLINE uint32_t UnmaskedStart() const {
+ MOZ_ASSERT(IsPasswordEditor());
+ return mPasswordMaskData ? mPasswordMaskData->mUnmaskedStart : UINT32_MAX;
+ }
+ MOZ_ALWAYS_INLINE uint32_t UnmaskedLength() const {
+ MOZ_ASSERT(IsPasswordEditor());
+ return mPasswordMaskData ? mPasswordMaskData->mUnmaskedLength : 0;
+ }
+ MOZ_ALWAYS_INLINE uint32_t UnmaskedEnd() const {
+ MOZ_ASSERT(IsPasswordEditor());
+ return mPasswordMaskData ? mPasswordMaskData->UnmaskedEnd() : UINT32_MAX;
+ }
+
+ /**
+ * IsMaskingPassword() returns false when the last caller of `Unmask()`
+ * didn't want to mask again automatically. When this returns true, user
+ * input causes masking the password even before timed-out.
+ */
+ bool IsMaskingPassword() const {
+ MOZ_ASSERT(IsPasswordEditor());
+ return mPasswordMaskData && mPasswordMaskData->mIsMaskingPassword;
+ }
+
+ /**
+ * PasswordMask() returns a character which masks each character in password
+ * fields.
+ */
+ static char16_t PasswordMask();
+
+ /**
+ * If you want to prevent to echo password temporarily, use the following
+ * methods.
+ */
+ bool EchoingPasswordPrevented() const {
+ return mPasswordMaskData && mPasswordMaskData->mEchoingPasswordPrevented;
+ }
+ void PreventToEchoPassword() {
+ if (mPasswordMaskData) {
+ mPasswordMaskData->mEchoingPasswordPrevented = true;
+ }
+ }
+ void AllowToEchoPassword() {
+ if (mPasswordMaskData) {
+ mPasswordMaskData->mEchoingPasswordPrevented = false;
+ }
+ }
+
+ dom::Text* GetTextNode() {
+ MOZ_DIAGNOSTIC_ASSERT(GetRoot());
+ MOZ_DIAGNOSTIC_ASSERT(GetRoot()->GetFirstChild());
+ MOZ_DIAGNOSTIC_ASSERT(GetRoot()->GetFirstChild()->IsText());
+ if (MOZ_UNLIKELY(!GetRoot() || !GetRoot()->GetFirstChild())) {
+ return nullptr;
+ }
+ return GetRoot()->GetFirstChild()->GetAsText();
+ }
+ const dom::Text* GetTextNode() const {
+ return const_cast<TextEditor*>(this)->GetTextNode();
+ }
+
+ protected: // May be called by friends.
+ /****************************************************************************
+ * Some friend classes are allowed to call the following protected methods.
+ * However, those methods won't prepare caches of some objects which are
+ * necessary for them. So, if you call them from friend classes, you need
+ * to make sure that AutoEditActionDataSetter is created.
+ ****************************************************************************/
+
+ // Overrides of EditorBase
+ MOZ_CAN_RUN_SCRIPT nsresult RemoveAttributeOrEquivalent(
+ Element* aElement, nsAtom* aAttribute, bool aSuppressTransaction) final;
+ MOZ_CAN_RUN_SCRIPT nsresult SetAttributeOrEquivalent(
+ Element* aElement, nsAtom* aAttribute, const nsAString& aValue,
+ bool aSuppressTransaction) final;
+ using EditorBase::RemoveAttributeOrEquivalent;
+ using EditorBase::SetAttributeOrEquivalent;
+
+ /**
+ * InsertLineBreakAsSubAction() inserts a line break.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InsertLineBreakAsSubAction();
+
+ /**
+ * Replace existed string with aString. Caller must guarantee that there
+ * is a placeholder transaction which will have the transaction.
+ *
+ * @ param aString The string to be set.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
+ SetTextAsSubAction(const nsAString& aString);
+
+ /**
+ * MaybeDoAutoPasswordMasking() may mask password if we're doing auto-masking.
+ */
+ void MaybeDoAutoPasswordMasking() {
+ if (IsPasswordEditor() && IsMaskingPassword()) {
+ MaskAllCharacters();
+ }
+ }
+
+ /**
+ * SetUnmaskRange() is available only when the instance is a password
+ * editor. This just updates unmask range. I.e., caller needs to
+ * guarantee to update the layout.
+ *
+ * @param aStart First index to show the character.
+ * If aLength is 0, this value is ignored.
+ * @param aLength Optional, Length to show characters.
+ * If UINT32_MAX, it means unmasking all characters after
+ * aStart.
+ * If 0, it means that masking all characters.
+ * @param aTimeout Optional, specify milliseconds to hide the unmasked
+ * characters after this call.
+ * If 0, it means this won't mask the characters
+ * automatically.
+ * If aLength is 0, this value is ignored.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult SetUnmaskRange(
+ uint32_t aStart, uint32_t aLength = UINT32_MAX, uint32_t aTimeout = 0) {
+ return SetUnmaskRangeInternal(aStart, aLength, aTimeout, false, false);
+ }
+
+ /**
+ * SetUnmaskRangeAndNotify() is available only when the instance is a
+ * password editor. This updates unmask range and notifying the text frame
+ * to update the visible characters.
+ *
+ * @param aStart First index to show the character.
+ * If UINT32_MAX, it means masking all.
+ * @param aLength Optional, Length to show characters.
+ * If UINT32_MAX, it means unmasking all characters after
+ * aStart.
+ * @param aTimeout Optional, specify milliseconds to hide the unmasked
+ * characters after this call.
+ * If 0, it means this won't mask the characters
+ * automatically.
+ * If aLength is 0, this value is ignored.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult SetUnmaskRangeAndNotify(
+ uint32_t aStart, uint32_t aLength = UINT32_MAX, uint32_t aTimeout = 0) {
+ return SetUnmaskRangeInternal(aStart, aLength, aTimeout, true, false);
+ }
+
+ /**
+ * MaskAllCharacters() is an alias of SetUnmaskRange() to mask all characters.
+ * In other words, this removes existing unmask range.
+ * After this is called, TextEditor starts masking password automatically.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult MaskAllCharacters() {
+ if (!mPasswordMaskData) {
+ return NS_OK; // Already we don't have masked range data.
+ }
+ return SetUnmaskRangeInternal(UINT32_MAX, 0, 0, false, true);
+ }
+
+ /**
+ * MaskAllCharactersAndNotify() is an alias of SetUnmaskRangeAndNotify() to
+ * mask all characters and notifies the text frame. In other words, this
+ * removes existing unmask range.
+ * After this is called, TextEditor starts masking password automatically.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult MaskAllCharactersAndNotify() {
+ return SetUnmaskRangeInternal(UINT32_MAX, 0, 0, true, true);
+ }
+
+ /**
+ * WillDeleteText() is called before `DeleteTextTransaction` or something
+ * removes text in a text node. Note that this won't be called if the
+ * instance is `HTMLEditor` since supporting it makes the code complicated
+ * due to mutation events.
+ *
+ * @param aCurrentLength Current text length of the node.
+ * @param aRemoveStartOffset Start offset of the range to be removed.
+ * @param aRemoveLength Length of the range to be removed.
+ */
+ void WillDeleteText(uint32_t aCurrentLength, uint32_t aRemoveStartOffset,
+ uint32_t aRemoveLength);
+
+ /**
+ * DidInsertText() is called after `InsertTextTransaction` or something
+ * inserts text into a text node. Note that this won't be called if the
+ * instance is `HTMLEditor` since supporting it makes the code complicated
+ * due to mutatione events.
+ *
+ * @param aNewLength New text length after the insertion.
+ * @param aInsertedOffset Start offset of the inserted text.
+ * @param aInsertedLength Length of the inserted text.
+ * @return NS_OK or NS_ERROR_EDITOR_DESTROYED.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult DidInsertText(
+ uint32_t aNewLength, uint32_t aInsertedOffset, uint32_t aInsertedLength);
+
+ protected: // edit sub-action handler
+ /**
+ * MaybeTruncateInsertionStringForMaxLength() truncates aInsertionString to
+ * `maxlength` if it was not pasted in by the user.
+ *
+ * @param aInsertionString [in/out] New insertion string. This is
+ * truncated to `maxlength` if it was not pasted in
+ * by the user.
+ * @return If aInsertionString is truncated, it returns "as
+ * handled", else "as ignored."
+ */
+ Result<EditActionResult, nsresult> MaybeTruncateInsertionStringForMaxLength(
+ nsAString& aInsertionString);
+
+ /**
+ * InsertLineFeedCharacterAtSelection() inserts a linefeed character at
+ * selection.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
+ InsertLineFeedCharacterAtSelection();
+
+ /**
+ * Handles the newline characters according to the default system prefs
+ * (editor.singleLine.pasteNewlines).
+ * Each value means:
+ * nsIEditor::eNewlinesReplaceWithSpaces (2, Firefox default):
+ * replace newlines with spaces.
+ * nsIEditor::eNewlinesStrip (3):
+ * remove newlines from the string.
+ * nsIEditor::eNewlinesReplaceWithCommas (4, Thunderbird default):
+ * replace newlines with commas.
+ * nsIEditor::eNewlinesStripSurroundingWhitespace (5):
+ * collapse newlines and surrounding white-space characters and
+ * remove them from the string.
+ * nsIEditor::eNewlinesPasteIntact (0):
+ * only remove the leading and trailing newlines.
+ * nsIEditor::eNewlinesPasteToFirst (1) or any other value:
+ * remove the first newline and all characters following it.
+ *
+ * @param aString the string to be modified in place.
+ */
+ void HandleNewLinesInStringForSingleLineEditor(nsString& aString) const;
+
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
+ HandleInsertText(EditSubAction aEditSubAction,
+ const nsAString& aInsertionString,
+ SelectionHandling aSelectionHandling) final;
+
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InsertDroppedDataTransferAsAction(
+ AutoEditActionDataSetter& aEditActionData,
+ dom::DataTransfer& aDataTransfer, const EditorDOMPoint& aDroppedAt,
+ nsIPrincipal* aSourcePrincipal) final;
+
+ /**
+ * HandleDeleteSelectionInternal() is a helper method of
+ * HandleDeleteSelection(). Must be called only when the instance is
+ * TextEditor.
+ * NOTE: This method creates SelectionBatcher. Therefore, each caller
+ * needs to check if the editor is still available even if this returns
+ * NS_OK.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
+ HandleDeleteSelectionInternal(nsIEditor::EDirection aDirectionAndAmount,
+ nsIEditor::EStripWrappers aStripWrappers);
+
+ /**
+ * This method handles "delete selection" commands.
+ *
+ * @param aDirectionAndAmount Direction of the deletion.
+ * @param aStripWrappers Must be nsIEditor::eNoStrip.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
+ HandleDeleteSelection(nsIEditor::EDirection aDirectionAndAmount,
+ nsIEditor::EStripWrappers aStripWrappers) final;
+
+ /**
+ * ComputeValueFromTextNodeAndBRElement() tries to compute "value" of
+ * this editor content only with text nodes and `<br>` elements.
+ * If this succeeds to compute the value, it's returned with aValue and
+ * the result is marked as "handled". Otherwise, the caller needs to
+ * compute it with another way.
+ */
+ Result<EditActionResult, nsresult> ComputeValueFromTextNodeAndBRElement(
+ nsAString& aValue) const;
+
+ /**
+ * SetTextWithoutTransaction() is optimized method to set `<input>.value`
+ * and `<textarea>.value` to aValue without transaction. This must be
+ * called only when it's not `HTMLEditor` and undo/redo is disabled.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
+ SetTextWithoutTransaction(const nsAString& aValue);
+
+ /**
+ * EnsureCaretNotAtEndOfTextNode() collapses selection at the padding `<br>`
+ * element (i.e., container becomes the anonymous `<div>` element) if
+ * `Selection` is at end of the text node.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult EnsureCaretNotAtEndOfTextNode();
+
+ protected: // Called by helper classes.
+ MOZ_CAN_RUN_SCRIPT void OnStartToHandleTopLevelEditSubAction(
+ EditSubAction aTopLevelEditSubAction,
+ nsIEditor::EDirection aDirectionOfTopLevelEditSubAction,
+ ErrorResult& aRv) final;
+ MOZ_CAN_RUN_SCRIPT nsresult OnEndHandlingTopLevelEditSubAction() final;
+
+ /**
+ * HandleInlineSpellCheckAfterEdit() does spell-check after handling top level
+ * edit subaction.
+ */
+ nsresult HandleInlineSpellCheckAfterEdit() {
+ MOZ_ASSERT(IsEditActionDataAvailable());
+ if (!GetSpellCheckRestartPoint().IsSet()) {
+ return NS_OK; // Maybe being initialized.
+ }
+ nsresult rv = HandleInlineSpellCheck(GetSpellCheckRestartPoint());
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to spellcheck");
+ ClearSpellCheckRestartPoint();
+ return rv;
+ }
+
+ protected: // Shouldn't be used by friend classes
+ virtual ~TextEditor();
+
+ /**
+ * CanEchoPasswordNow() returns true if currently we can echo password.
+ * If it's direct user input such as pasting or dropping text, this
+ * returns false even if we may echo password.
+ */
+ bool CanEchoPasswordNow() const;
+
+ /**
+ * InitEditorContentAndSelection() may insert a padding `<br>` element for
+ * if it's required in the anonymous `<div>` element or `<body>` element and
+ * collapse selection at the end if there is no selection ranges.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InitEditorContentAndSelection();
+
+ /**
+ * Collapse `Selection` to end of the text node in the anonymous <div>
+ * element.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult CollapseSelectionToEndOfTextNode();
+
+ /**
+ * Make the given selection span the entire document.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult SelectEntireDocument() final;
+
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
+ InsertWithQuotationsAsSubAction(const nsAString& aQuotedText) final;
+
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
+ InsertTextFromTransferable(nsITransferable* transferable);
+
+ bool IsCopyToClipboardAllowedInternal() const final;
+
+ already_AddRefed<Element> GetInputEventTargetElement() const final;
+
+ /**
+ * See SetUnmaskRange() and SetUnmaskRangeAndNotify() for the detail.
+ *
+ * @param aForceStartMasking If true, forcibly starts masking. This should
+ * be used only when `nsIEditor::Mask()` is called.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult SetUnmaskRangeInternal(uint32_t aStart,
+ uint32_t aLength,
+ uint32_t aTimeout,
+ bool aNotify,
+ bool aForceStartMasking);
+
+ MOZ_ALWAYS_INLINE bool HasAutoMaskingTimer() const {
+ return mPasswordMaskData && mPasswordMaskData->mTimer;
+ }
+
+ protected:
+ UniquePtr<PasswordMaskData> mPasswordMaskData;
+
+ int32_t mMaxTextLength = -1;
+
+ friend class DeleteNodeTransaction;
+ friend class EditorBase;
+ friend class InsertNodeTransaction;
+};
+
+} // namespace mozilla
+
+mozilla::TextEditor* nsIEditor::AsTextEditor() {
+ MOZ_DIAGNOSTIC_ASSERT(IsTextEditor());
+ return static_cast<mozilla::TextEditor*>(this);
+}
+
+const mozilla::TextEditor* nsIEditor::AsTextEditor() const {
+ MOZ_DIAGNOSTIC_ASSERT(IsTextEditor());
+ return static_cast<const mozilla::TextEditor*>(this);
+}
+
+mozilla::TextEditor* nsIEditor::GetAsTextEditor() {
+ return AsEditorBase()->IsTextEditor() ? AsTextEditor() : nullptr;
+}
+
+const mozilla::TextEditor* nsIEditor::GetAsTextEditor() const {
+ return AsEditorBase()->IsTextEditor() ? AsTextEditor() : nullptr;
+}
+
+#endif // #ifndef mozilla_TextEditor_h