tor-browser

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

TextControlState.h (22930B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_TextControlState_h
      8 #define mozilla_TextControlState_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/Attributes.h"
     12 #include "mozilla/EnumSet.h"
     13 #include "mozilla/Maybe.h"
     14 #include "mozilla/TextControlElement.h"
     15 #include "mozilla/UniquePtr.h"
     16 #include "mozilla/WeakPtr.h"
     17 #include "mozilla/dom/Nullable.h"
     18 #include "nsCycleCollectionParticipant.h"
     19 #include "nsITimer.h"
     20 
     21 class nsTextControlFrame;
     22 class nsISelectionController;
     23 class nsFrameSelection;
     24 class nsFrame;
     25 
     26 namespace mozilla {
     27 
     28 class AutoTextControlHandlingState;
     29 class ErrorResult;
     30 class IMEContentObserver;
     31 class TextEditor;
     32 class TextInputListener;
     33 class TextInputSelectionController;
     34 
     35 enum class SelectionDirection : uint8_t {
     36  None,
     37  Forward,
     38  Backward,
     39 };
     40 
     41 namespace dom {
     42 enum class SelectionMode : uint8_t;
     43 class Element;
     44 class HTMLInputElement;
     45 }  // namespace dom
     46 
     47 /**
     48 * PasswordMaskData stores making information and necessary timer for
     49 * `TextEditor` instances.
     50 */
     51 struct PasswordMaskData final {
     52  // Timer to mask unmasked characters automatically.  Used only when it's
     53  // a password field.
     54  nsCOMPtr<nsITimer> mTimer;
     55 
     56  // Unmasked character range.  Used only when it's a password field.
     57  // If mUnmaskedLength is 0, it means there is no unmasked characters.
     58  uint32_t mUnmaskedStart = UINT32_MAX;
     59  uint32_t mUnmaskedLength = 0;
     60 
     61  // Set to true if all characters are masked or waiting notification from
     62  // `mTimer`.  Otherwise, i.e., part of or all of password is unmasked
     63  // without setting `mTimer`, set to false.
     64  bool mIsMaskingPassword = true;
     65 
     66  // Set to true if a manager of the instance wants to disable echoing
     67  // password temporarily.
     68  bool mEchoingPasswordPrevented = false;
     69 
     70  MOZ_ALWAYS_INLINE bool IsAllMasked() const {
     71    return mUnmaskedStart == UINT32_MAX && mUnmaskedLength == 0;
     72  }
     73  MOZ_ALWAYS_INLINE uint32_t UnmaskedEnd() const {
     74    return mUnmaskedStart + mUnmaskedLength;
     75  }
     76  MOZ_ALWAYS_INLINE void MaskAll() {
     77    mUnmaskedStart = UINT32_MAX;
     78    mUnmaskedLength = 0;
     79  }
     80  MOZ_ALWAYS_INLINE void Reset() {
     81    MaskAll();
     82    mIsMaskingPassword = true;
     83  }
     84  enum class ReleaseTimer { No, Yes };
     85  MOZ_ALWAYS_INLINE void CancelTimer(ReleaseTimer aReleaseTimer) {
     86    if (mTimer) {
     87      mTimer->Cancel();
     88      if (aReleaseTimer == ReleaseTimer::Yes) {
     89        mTimer = nullptr;
     90      }
     91    }
     92    if (mIsMaskingPassword) {
     93      MaskAll();
     94    }
     95  }
     96 };
     97 
     98 /**
     99 * TextControlState is a class which is responsible for managing the state of
    100 * plaintext controls.  This currently includes the following HTML elements:
    101 *   <input type=text>
    102 *   <input type=search>
    103 *   <input type=url>
    104 *   <input type=telephone>
    105 *   <input type=email>
    106 *   <input type=password>
    107 *   <textarea>
    108 *
    109 * This class is held as a member of HTMLInputElement and HTMLTextAreaElement.
    110 * The public functions in this class include the public APIs which dom/
    111 * uses. Layout code uses the TextControlElement interface to invoke
    112 * functions on this class.
    113 *
    114 * The design motivation behind this class is maintaining all of the things
    115 * which collectively are considered the "state" of the text control in a single
    116 * location. This state includes several things:
    117 *
    118 *  * The control's value.  This value is stored in the mValue member, and is
    119 * only used when there is no frame for the control, or when the editor object
    120 * has not been initialized yet.
    121 *
    122 *  * The control's associated frame.  This value is stored in the mBoundFrame
    123 * member. A text control might never have an associated frame during its life
    124 * cycle, or might have several different ones, but at any given moment in time
    125 * there is a maximum of 1 bound frame to each text control.
    126 *
    127 *  * The control's associated editor.  This value is stored in the mTextEditor
    128 * member. An editor is initialized for the control only when necessary (that
    129 * is, when either the user is about to interact with the text control, or when
    130 * some other code needs to access the editor object.  Without a frame bound to
    131 * the control, an editor is never initialized.  Once initialized, the editor
    132 * might outlive the frame, in which case the same editor will be used if a new
    133 * frame gets bound to the text control.
    134 *
    135 *  * The anonymous content associated with the text control's frame, including
    136 * the value div (the DIV element responsible for holding the value of the text
    137 * control) and the placeholder div (the DIV element responsible for holding the
    138 * placeholder value of the text control.)  These values are stored in the
    139 * mRootNode and mPlaceholderDiv members, respectively.  They will be created
    140 * when a frame is bound to the text control.  They will be destroyed when the
    141 * frame is unbound from the object.  We could try and hold on to the anonymous
    142 * content between different frames, but unfortunately that is not currently
    143 * possible because they are not unbound from the document in time.
    144 *
    145 *  * The frame selection controller.  This value is stored in the mSelCon
    146 * member. The frame selection controller is responsible for maintaining the
    147 * selection state on a frame.  It is created when a frame is bound to the text
    148 * control element, and will be destroy when the frame is being unbound from the
    149 * text control element. It is created alongside with the frame selection object
    150 * which is stored in the mFrameSel member.
    151 *
    152 *  * The editor text listener.  This value is stored in the mTextListener
    153 * member. Its job is to listen to selection and keyboard events, and act
    154 * accordingly. It is created when an a frame is first bound to the control, and
    155 * will be destroyed when the frame is unbound from the text control element.
    156 *
    157 *  * The editor's cached value.  This value is stored in the mCachedValue
    158 * member. It is used to improve the performance of append operations to the
    159 * text control.  A mutation observer stored in the mMutationObserver has the
    160 * job of invalidating this cache when the anonymous contect containing the
    161 * value is changed.
    162 *
    163 *  * The editor's cached selection properties.  These vales are stored in the
    164 *    mSelectionProperties member, and include the selection's start, end and
    165 *    direction. They are only used when there is no frame available for the
    166 *    text field.
    167 *
    168 *
    169 * As a general rule, TextControlState objects own the value of the text
    170 * control, and any attempt to retrieve or set the value must be made through
    171 * those objects.  Internally, the value can be represented in several different
    172 * ways, based on the state the control is in.
    173 *
    174 *   * When the control is first initialized, its value is equal to the default
    175 * value of the DOM node.  For <input> text controls, this default value is the
    176 * value of the value attribute.  For <textarea> elements, this default value is
    177 * the value of the text node children of the element.
    178 *
    179 *   * If the value has been changed through the DOM node (before the editor for
    180 * the object is initialized), the value is stored as a simple string inside the
    181 * mValue member of the TextControlState object.
    182 *
    183 *   * If an editor has been initialized for the control, the value is set and
    184 * retrievd via the nsIEditor interface, and is internally managed by the
    185 * editor as the native anonymous content tree attached to the control's frame.
    186 *
    187 *   * If the text control state object is unbound from the control's frame, the
    188 * value is transferred to the mValue member variable, and will be managed there
    189 * until a new frame is bound to the text editor state object.
    190 */
    191 
    192 class RestoreSelectionState;
    193 
    194 class TextControlState final : public SupportsWeakPtr {
    195 public:
    196  using Element = dom::Element;
    197  using HTMLInputElement = dom::HTMLInputElement;
    198 
    199  static TextControlState* Construct(TextControlElement* aOwningElement);
    200 
    201  // Note that this does not run script actually because of `sHasShutDown`
    202  // is set to true before calling `DeleteOrCacheForReuse()`.
    203  MOZ_CAN_RUN_SCRIPT_BOUNDARY static void Shutdown();
    204 
    205  /**
    206   * Destroy() deletes the instance immediately or later.
    207   */
    208  MOZ_CAN_RUN_SCRIPT void Destroy();
    209 
    210  TextControlState() = delete;
    211  explicit TextControlState(const TextControlState&) = delete;
    212  TextControlState(TextControlState&&) = delete;
    213 
    214  void operator=(const TextControlState&) = delete;
    215  void operator=(TextControlState&&) = delete;
    216 
    217  void Traverse(nsCycleCollectionTraversalCallback& cb);
    218  MOZ_CAN_RUN_SCRIPT_BOUNDARY void Unlink();
    219 
    220  bool IsBusy() const { return !!mHandlingState || mValueTransferInProgress; }
    221 
    222  MOZ_CAN_RUN_SCRIPT TextEditor* GetTextEditor();
    223  TextEditor* GetExtantTextEditor() const;
    224  nsISelectionController* GetSelectionController() const;
    225  nsFrameSelection* GetIndependentFrameSelection() const;
    226  nsresult BindToFrame(nsTextControlFrame* aFrame);
    227  MOZ_CAN_RUN_SCRIPT void UnbindFromFrame(nsTextControlFrame* aFrame);
    228  [[nodiscard]] nsTextControlFrame* GetBoundFrame() const {
    229    return mBoundFrame;
    230  }
    231  MOZ_CAN_RUN_SCRIPT nsresult PrepareEditor(const nsAString* aValue = nullptr);
    232  void InitializeKeyboardEventListeners();
    233 
    234  /**
    235   * OnEditActionHandled() is called when mTextEditor handles something
    236   * and immediately before dispatching "input" event.
    237   */
    238  [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult OnEditActionHandled();
    239 
    240  enum class ValueSetterOption {
    241    // The call is for setting value to initial one, computed one, etc.
    242    ByInternalAPI,
    243    // The value is changed by a call of setUserInput() API from chrome.
    244    BySetUserInputAPI,
    245    // The value is changed by changing value attribute of the element or
    246    // something like setRangeText().
    247    ByContentAPI,
    248    // The value is changed by setRangeText(). Intended to prevent silent
    249    // selection range change.
    250    BySetRangeTextAPI,
    251    // Whether SetValueChanged should be called as a result of this value
    252    // change.
    253    SetValueChanged,
    254    // Whether to move the cursor to end of the value (in the case when we have
    255    // cached selection offsets), in the case when the value has changed.  If
    256    // this is not set and MoveCursorToBeginSetSelectionDirectionForward
    257    // is not set, the cached selection offsets will simply be clamped to
    258    // be within the length of the new value. In either case, if the value has
    259    // not changed the cursor won't move.
    260    // TODO(mbrodesser): update comment and enumerator identifier to reflect
    261    // that also the direction is set to forward.
    262    MoveCursorToEndIfValueChanged,
    263 
    264    // The value change should preserve undo history.
    265    PreserveUndoHistory,
    266 
    267    // Whether it should be tried to move the cursor to the beginning of the
    268    // text control and set the selection direction to "forward".
    269    // TODO(mbrodesser): As soon as "none" is supported
    270    // (https://bugzilla.mozilla.org/show_bug.cgi?id=1541454), it should be set
    271    // to "none" and only fall back to "forward" if the platform doesn't support
    272    // it.
    273    MoveCursorToBeginSetSelectionDirectionForward,
    274  };
    275  using ValueSetterOptions = EnumSet<ValueSetterOption, uint32_t>;
    276 
    277  /**
    278   * SetValue() sets the value to aValue with replacing \r\n and \r with \n.
    279   *
    280   * @param aValue      The new value.  Can contain \r.
    281   * @param aOldValue   Optional.  If you have already know current value,
    282   *                    set this to it.  However, this must not contain \r
    283   *                    for the performance.
    284   * @param aOptions    See ValueSetterOption.
    285   */
    286  [[nodiscard]] MOZ_CAN_RUN_SCRIPT bool SetValue(
    287      const nsAString& aValue, const nsAString* aOldValue,
    288      const ValueSetterOptions& aOptions);
    289  [[nodiscard]] MOZ_CAN_RUN_SCRIPT bool SetValue(
    290      const nsAString& aValue, const ValueSetterOptions& aOptions) {
    291    return SetValue(aValue, nullptr, aOptions);
    292  }
    293 
    294  /**
    295   * GetValue() returns current value either with or without TextEditor.
    296   * The result never includes \r.
    297   */
    298  void GetValue(nsAString& aValue, bool aForDisplay) const;
    299 
    300  /**
    301   * ValueEquals() is designed for internal use so that aValue shouldn't
    302   * include \r character.  It should be handled before calling this with
    303   * nsContentUtils::PlatformToDOMLineBreaks().
    304   */
    305  bool ValueEquals(const nsAString& aValue) const;
    306  // The following methods are for textarea element to use whether default
    307  // value or not.
    308  // XXX We might have to add assertion when it is into editable,
    309  // or reconsider fixing bug 597525 to remove these.
    310  void EmptyValue() {
    311    if (!mValue.IsVoid()) {
    312      mValue.Truncate();
    313    }
    314  }
    315  bool IsEmpty() const { return mValue.IsEmpty(); }
    316 
    317  const nsAString& LastInteractiveValueIfLastChangeWasNonInteractive() const {
    318    return mLastInteractiveValue;
    319  }
    320  // When an interactive value change happens, we clear mLastInteractiveValue
    321  // because it's not needed (mValue is the new interactive value).
    322  void ClearLastInteractiveValue() { mLastInteractiveValue.SetIsVoid(true); }
    323 
    324  Element* GetRootNode();
    325  Element* GetPreviewNode();
    326 
    327  bool IsSingleLineTextControl() const {
    328    return mTextCtrlElement->IsSingleLineTextControl();
    329  }
    330  bool IsTextArea() const { return mTextCtrlElement->IsTextArea(); }
    331  bool IsPasswordTextControl() const {
    332    return mTextCtrlElement->IsPasswordTextControl();
    333  }
    334  int32_t GetColsOrDefault() { return mTextCtrlElement->GetColsOrDefault(); }
    335  int32_t GetWrapCols() {
    336    int32_t wrapCols = mTextCtrlElement->GetWrapCols();
    337    MOZ_ASSERT(wrapCols >= 0);
    338    return wrapCols;
    339  }
    340  int32_t GetRows() { return mTextCtrlElement->GetRows(); }
    341 
    342  // preview methods
    343  void SetPreviewText(const nsAString& aValue, bool aNotify);
    344  void GetPreviewText(nsAString& aValue);
    345 
    346  struct SelectionProperties {
    347   public:
    348    bool IsDefault() const {
    349      return mStart == 0 && mEnd == 0 &&
    350             mDirection == SelectionDirection::Forward;
    351    }
    352    uint32_t GetStart() const { return mStart; }
    353    bool SetStart(uint32_t value) {
    354      uint32_t newValue = std::min(value, *mMaxLength);
    355      return SetStartInternal(newValue);
    356    }
    357    uint32_t GetEnd() const { return mEnd; }
    358    bool SetEnd(uint32_t value) {
    359      uint32_t newValue = std::min(value, *mMaxLength);
    360      return SetEndInternal(newValue);
    361    }
    362    void CollapseToStart() {
    363      // 0 is always a fine value regardless of max length.
    364      SetStartInternal(0);
    365      SetEndInternal(0);
    366    }
    367    SelectionDirection GetDirection() const { return mDirection; }
    368    bool SetDirection(SelectionDirection value) {
    369      bool changed = mDirection != value;
    370      mDirection = value;
    371      mIsDirty |= changed;
    372      return changed;
    373    }
    374    void SetMaxLength(uint32_t aMax) {
    375      mMaxLength = Some(aMax);
    376      // recompute against the new max length
    377      SetStart(GetStart());
    378      SetEnd(GetEnd());
    379    }
    380    bool HasMaxLength() { return mMaxLength.isSome(); }
    381 
    382    // return true only if mStart, mEnd, or mDirection have been modified,
    383    // or if SetIsDirty() was explicitly called.
    384    bool IsDirty() const { return mIsDirty; }
    385    void SetIsDirty() { mIsDirty = true; }
    386 
    387   private:
    388    bool SetStartInternal(uint32_t aNewValue) {
    389      bool changed = mStart != aNewValue;
    390      mStart = aNewValue;
    391      mIsDirty |= changed;
    392      return changed;
    393    }
    394 
    395    bool SetEndInternal(uint32_t aNewValue) {
    396      bool changed = mEnd != aNewValue;
    397      mEnd = aNewValue;
    398      mIsDirty |= changed;
    399      return changed;
    400    }
    401 
    402    uint32_t mStart = 0;
    403    uint32_t mEnd = 0;
    404    Maybe<uint32_t> mMaxLength;
    405    bool mIsDirty = false;
    406    SelectionDirection mDirection = SelectionDirection::Forward;
    407  };
    408 
    409  bool IsSelectionCached() const { return mSelectionCached; }
    410  SelectionProperties& GetSelectionProperties() { return mSelectionProperties; }
    411  MOZ_CAN_RUN_SCRIPT void SetSelectionProperties(SelectionProperties& aProps);
    412  bool HasNeverInitializedBefore() const { return !mEverInited; }
    413  // Sync up our selection properties with our editor prior to being destroyed.
    414  // This will invoke UnbindFromFrame() to ensure that we grab whatever
    415  // selection state may be at the moment.
    416  MOZ_CAN_RUN_SCRIPT void SyncUpSelectionPropertiesBeforeDestruction();
    417 
    418  // Get the selection range start and end points in our text.
    419  void GetSelectionRange(uint32_t* aSelectionStart, uint32_t* aSelectionEnd,
    420                         ErrorResult& aRv);
    421 
    422  // Get the selection direction
    423  SelectionDirection GetSelectionDirection(ErrorResult& aRv);
    424 
    425  enum class ScrollAfterSelection { No, Yes };
    426 
    427  // Set the selection range (start, end, direction).  aEnd is allowed to be
    428  // smaller than aStart; in that case aStart will be reset to the same value as
    429  // aEnd.  This basically implements
    430  // https://html.spec.whatwg.org/multipage/forms.html#set-the-selection-range
    431  // but with the start/end already coerced to zero if null (and without the
    432  // special infinity value), and the direction already converted to a
    433  // SelectionDirection.
    434  //
    435  // If we have a frame, this method will scroll the selection into view.
    436  MOZ_CAN_RUN_SCRIPT void SetSelectionRange(
    437      uint32_t aStart, uint32_t aEnd, SelectionDirection aDirection,
    438      ErrorResult& aRv,
    439      ScrollAfterSelection aScroll = ScrollAfterSelection::Yes);
    440 
    441  // Set the selection range, but with an optional string for the direction.
    442  // This will convert aDirection to an nsITextControlFrame::SelectionDirection
    443  // and then call our other SetSelectionRange overload.
    444  MOZ_CAN_RUN_SCRIPT void SetSelectionRange(
    445      uint32_t aSelectionStart, uint32_t aSelectionEnd,
    446      const dom::Optional<nsAString>& aDirection, ErrorResult& aRv,
    447      ScrollAfterSelection aScroll = ScrollAfterSelection::Yes);
    448 
    449  // Set the selection start.  This basically implements the
    450  // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-selectionstart
    451  // setter.
    452  MOZ_CAN_RUN_SCRIPT void SetSelectionStart(
    453      const dom::Nullable<uint32_t>& aStart, ErrorResult& aRv);
    454 
    455  // Set the selection end.  This basically implements the
    456  // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-selectionend
    457  // setter.
    458  MOZ_CAN_RUN_SCRIPT void SetSelectionEnd(const dom::Nullable<uint32_t>& aEnd,
    459                                          ErrorResult& aRv);
    460 
    461  // Get the selection direction as a string.  This implements the
    462  // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-selectiondirection
    463  // getter.
    464  void GetSelectionDirectionString(nsAString& aDirection, ErrorResult& aRv);
    465 
    466  // Set the selection direction.  This basically implements the
    467  // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-selectiondirection
    468  // setter.
    469  MOZ_CAN_RUN_SCRIPT void SetSelectionDirection(const nsAString& aDirection,
    470                                                ErrorResult& aRv);
    471 
    472  // Set the range text.  This basically implements
    473  // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-setrangetext
    474  MOZ_CAN_RUN_SCRIPT void SetRangeText(const nsAString& aReplacement,
    475                                       ErrorResult& aRv);
    476  // The last two arguments are -1 if we don't know our selection range;
    477  // otherwise they're the start and end of our selection range.
    478  MOZ_CAN_RUN_SCRIPT void SetRangeText(
    479      const nsAString& aReplacement, uint32_t aStart, uint32_t aEnd,
    480      dom::SelectionMode aSelectMode, ErrorResult& aRv,
    481      const Maybe<uint32_t>& aSelectionStart = Nothing(),
    482      const Maybe<uint32_t>& aSelectionEnd = Nothing());
    483 
    484 private:
    485  explicit TextControlState(TextControlElement* aOwningElement);
    486  MOZ_CAN_RUN_SCRIPT ~TextControlState();
    487 
    488  /**
    489   * Delete the instance or cache to reuse it if possible.
    490   */
    491  MOZ_CAN_RUN_SCRIPT void DeleteOrCacheForReuse();
    492 
    493  MOZ_CAN_RUN_SCRIPT void UnlinkInternal();
    494 
    495  MOZ_CAN_RUN_SCRIPT void DestroyEditor();
    496  MOZ_CAN_RUN_SCRIPT void Clear();
    497 
    498  nsresult InitializeRootNode();
    499 
    500  void FinishedRestoringSelection();
    501 
    502  bool EditorHasComposition();
    503 
    504  /**
    505   * SetValueWithTextEditor() modifies the editor value with mTextEditor.
    506   * This may cause destroying mTextEditor, mBoundFrame, the TextControlState
    507   * itself.  Must be called when both mTextEditor and mBoundFrame are not
    508   * nullptr.
    509   *
    510   * @param aHandlingSetValue   Must be inner-most handling state for SetValue.
    511   * @return                    false if fallible allocation failed.  Otherwise,
    512   *                            true.
    513   */
    514  MOZ_CAN_RUN_SCRIPT bool SetValueWithTextEditor(
    515      AutoTextControlHandlingState& aHandlingSetValue);
    516 
    517  /**
    518   * SetValueWithoutTextEditor() modifies the value without editor.  I.e.,
    519   * modifying the value in this instance and mBoundFrame.  Must be called
    520   * when at least mTextEditor or mBoundFrame is nullptr.
    521   *
    522   * @param aHandlingSetValue   Must be inner-most handling state for SetValue.
    523   * @return                    false if fallible allocation failed.  Otherwise,
    524   *                            true.
    525   */
    526  MOZ_CAN_RUN_SCRIPT bool SetValueWithoutTextEditor(
    527      AutoTextControlHandlingState& aHandlingSetValue);
    528 
    529  IMEContentObserver* GetIMEContentObserver() const;
    530 
    531  // When this class handles something which may run script, this should be
    532  // set to non-nullptr.  If so, this class claims that it's busy and that
    533  // prevents destroying TextControlState instance.
    534  AutoTextControlHandlingState* mHandlingState = nullptr;
    535 
    536  // The text control element owns this object, and ensures that this object
    537  // has a smaller lifetime except the owner releases the instance while it
    538  // does something with this.
    539  TextControlElement* MOZ_NON_OWNING_REF mTextCtrlElement;
    540  RefPtr<TextInputSelectionController> mSelCon;
    541  RefPtr<RestoreSelectionState> mRestoringSelection;
    542  RefPtr<TextEditor> mTextEditor;
    543  nsTextControlFrame* mBoundFrame = nullptr;
    544  RefPtr<TextInputListener> mTextListener;
    545  UniquePtr<PasswordMaskData> mPasswordMaskData;
    546 
    547  nsString mValue{VoidString()};  // Void if there's no value.
    548 
    549  // If our input's last value change was not interactive (as in, the value
    550  // change was caused by a ValueChangeKind::UserInteraction), this is the value
    551  // that the last interaction had.
    552  nsString mLastInteractiveValue{VoidString()};
    553 
    554  SelectionProperties mSelectionProperties;
    555 
    556  bool mEverInited : 1;  // Have we ever been initialized?
    557  bool mEditorInitialized : 1;
    558  bool mValueTransferInProgress : 1;  // Whether a value is being transferred to
    559                                      // the frame
    560  bool mSelectionCached : 1;          // Whether mSelectionProperties is valid
    561 
    562  friend class AutoTextControlHandlingState;
    563  friend class PrepareEditorEvent;
    564  friend class RestoreSelectionState;
    565 };
    566 
    567 }  // namespace mozilla
    568 
    569 #endif  // #ifndef mozilla_TextControlState_h