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