Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/forms/nsTextControlFrame.h
Line
Count
Source (jump to first uncovered line)
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 nsTextControlFrame_h___
8
#define nsTextControlFrame_h___
9
10
#include "mozilla/Attributes.h"
11
#include "mozilla/dom/Element.h"
12
#include "nsContainerFrame.h"
13
#include "nsIAnonymousContentCreator.h"
14
#include "nsIContent.h"
15
#include "nsITextControlFrame.h"
16
#include "nsITextControlElement.h"
17
#include "nsIStatefulFrame.h"
18
19
class nsISelectionController;
20
class EditorInitializerEntryTracker;
21
class nsTextEditorState;
22
namespace mozilla {
23
class TextEditor;
24
enum class CSSPseudoElementType : uint8_t;
25
namespace dom {
26
class Element;
27
} // namespace dom
28
} // namespace mozilla
29
30
class nsTextControlFrame final : public nsContainerFrame,
31
                                 public nsIAnonymousContentCreator,
32
                                 public nsITextControlFrame,
33
                                 public nsIStatefulFrame
34
{
35
public:
36
  NS_DECL_FRAMEARENA_HELPERS(nsTextControlFrame)
37
38
  NS_DECLARE_FRAME_PROPERTY_DELETABLE(ContentScrollPos, nsPoint)
39
40
  explicit nsTextControlFrame(ComputedStyle* aStyle);
41
  virtual ~nsTextControlFrame();
42
43
  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
44
45
0
  virtual nsIScrollableFrame* GetScrollTargetFrame() override {
46
0
    return do_QueryFrame(PrincipalChildList().FirstChild());
47
0
  }
48
49
  virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
50
  virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
51
52
  virtual mozilla::LogicalSize
53
  ComputeAutoSize(gfxContext*                 aRenderingContext,
54
                  mozilla::WritingMode        aWM,
55
                  const mozilla::LogicalSize& aCBSize,
56
                  nscoord                     aAvailableISize,
57
                  const mozilla::LogicalSize& aMargin,
58
                  const mozilla::LogicalSize& aBorder,
59
                  const mozilla::LogicalSize& aPadding,
60
                  ComputeSizeFlags            aFlags) override;
61
62
  virtual void Reflow(nsPresContext*           aPresContext,
63
                      ReflowOutput&     aDesiredSize,
64
                      const ReflowInput& aReflowInput,
65
                      nsReflowStatus&          aStatus) override;
66
67
  bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
68
                                nscoord* aBaseline) const override
69
0
  {
70
0
    return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::eFirst, aBaseline);
71
0
  }
72
73
  bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
74
                                 BaselineSharingGroup aBaselineGroup,
75
                                 nscoord* aBaseline) const override
76
0
  {
77
0
    if (!IsSingleLineTextControl()) {
78
0
      return false;
79
0
    }
80
0
    NS_ASSERTION(mFirstBaseline != NS_INTRINSIC_WIDTH_UNKNOWN,
81
0
                 "please call Reflow before asking for the baseline");
82
0
    if (aBaselineGroup == BaselineSharingGroup::eFirst) {
83
0
      *aBaseline = mFirstBaseline;
84
0
    } else {
85
0
      *aBaseline = BSize(aWM) - mFirstBaseline;
86
0
    }
87
0
    return true;
88
0
  }
89
90
  virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
91
  virtual bool IsXULCollapsed() override;
92
93
#ifdef ACCESSIBILITY
94
  virtual mozilla::a11y::AccType AccessibleType() override;
95
#endif
96
97
#ifdef DEBUG_FRAME_DUMP
98
  virtual nsresult GetFrameName(nsAString& aResult) const override
99
  {
100
    aResult.AssignLiteral("nsTextControlFrame");
101
    return NS_OK;
102
  }
103
#endif
104
105
  virtual bool IsFrameOfType(uint32_t aFlags) const override
106
0
  {
107
0
    // nsStackFrame is already both of these, but that's somewhat bogus,
108
0
    // and we really mean it.
109
0
    return nsContainerFrame::IsFrameOfType(aFlags &
110
0
      ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
111
0
  }
112
113
#ifdef DEBUG
114
  void MarkIntrinsicISizesDirty() override
115
  {
116
    // Need another Reflow to have a correct baseline value again.
117
    mFirstBaseline = NS_INTRINSIC_WIDTH_UNKNOWN;
118
  }
119
#endif
120
121
  // nsIAnonymousContentCreator
122
  virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
123
  virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
124
                                        uint32_t aFilter) override;
125
126
  virtual void SetInitialChildList(ChildListID     aListID,
127
                                   nsFrameList&    aChildList) override;
128
129
  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
130
                                const nsDisplayListSet& aLists) override;
131
132
//==== BEGIN NSIFORMCONTROLFRAME
133
  virtual void SetFocus(bool aOn , bool aRepaint) override;
134
  virtual nsresult SetFormProperty(nsAtom* aName, const nsAString& aValue) override;
135
136
//==== END NSIFORMCONTROLFRAME
137
138
//==== NSITEXTCONTROLFRAME
139
140
  NS_IMETHOD_(already_AddRefed<mozilla::TextEditor>) GetTextEditor() override;
141
  NS_IMETHOD    SetSelectionRange(uint32_t aSelectionStart,
142
                                  uint32_t aSelectionEnd,
143
                                  SelectionDirection aDirection = eNone) override;
144
  NS_IMETHOD    GetOwnedSelectionController(nsISelectionController** aSelCon) override;
145
  virtual nsFrameSelection* GetOwnedFrameSelection() override;
146
147
  /**
148
   * Ensure mEditor is initialized with the proper flags and the default value.
149
   * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
150
   * @throws various and sundry other things
151
   */
152
  virtual nsresult EnsureEditorInitialized() override;
153
154
//==== END NSITEXTCONTROLFRAME
155
156
//==== NSISTATEFULFRAME
157
158
  mozilla::UniquePtr<mozilla::PresState> SaveState() override;
159
  NS_IMETHOD RestoreState(mozilla::PresState* aState) override;
160
161
//=== END NSISTATEFULFRAME
162
163
//==== OVERLOAD of nsIFrame
164
165
  /** handler for attribute changes to mContent */
166
  virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
167
                                    nsAtom*        aAttribute,
168
                                    int32_t         aModType) override;
169
170
  void GetText(nsString& aText);
171
172
  virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos) override;
173
174
  NS_DECL_QUERYFRAME
175
176
protected:
177
  /**
178
   * Launch the reflow on the child frames - see nsTextControlFrame::Reflow()
179
   */
180
  void ReflowTextControlChild(nsIFrame*                aFrame,
181
                              nsPresContext*           aPresContext,
182
                              const ReflowInput& aReflowInput,
183
                              nsReflowStatus&          aStatus,
184
                              ReflowOutput& aParentDesiredSize);
185
186
public: //for methods who access nsTextControlFrame directly
187
  void SetValueChanged(bool aValueChanged);
188
189
0
  mozilla::dom::Element* GetRootNode() const {
190
0
    return mRootNode;
191
0
  }
192
193
0
  mozilla::dom::Element* GetPreviewNode() const {
194
0
    return mPreviewDiv;
195
0
  }
196
197
  // called by the focus listener
198
  nsresult MaybeBeginSecureKeyboardInput();
199
  void MaybeEndSecureKeyboardInput();
200
201
#define DEFINE_TEXTCTRL_CONST_FORWARDER(type, name)                            \
202
0
  type name() const {                                                          \
203
0
    nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \
204
0
    NS_ASSERTION(txtCtrl, "Content not a text control element");               \
205
0
    return txtCtrl->name();                                                    \
206
0
  }
Unexecuted instantiation: nsTextControlFrame::IsSingleLineTextControl() const
Unexecuted instantiation: nsTextControlFrame::IsTextArea() const
Unexecuted instantiation: nsTextControlFrame::IsPasswordTextControl() const
Unexecuted instantiation: nsTextControlFrame::GetCols() const
Unexecuted instantiation: nsTextControlFrame::GetRows() const
207
208
  DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsSingleLineTextControl)
209
  DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsTextArea)
210
  DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPasswordTextControl)
211
  DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetCols)
212
  DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetRows)
213
214
#undef DEFINE_TEXTCTRL_CONST_FORWARDER
215
216
protected:
217
  class EditorInitializer;
218
  friend class EditorInitializer;
219
  friend class nsTextEditorState; // needs access to UpdateValueDisplay
220
221
  // Temp reference to scriptrunner
222
  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(TextControlInitializer,
223
                                      EditorInitializer,
224
                                      nsTextControlFrame::RevokeInitializer)
225
226
  static void
227
0
  RevokeInitializer(EditorInitializer* aInitializer) {
228
0
    aInitializer->Revoke();
229
0
  };
230
231
  class EditorInitializer : public mozilla::Runnable {
232
  public:
233
    explicit EditorInitializer(nsTextControlFrame* aFrame)
234
      : mozilla::Runnable("nsTextControlFrame::EditorInitializer")
235
      , mFrame(aFrame)
236
0
    {
237
0
    }
238
239
    NS_IMETHOD Run() override;
240
241
    // avoids use of AutoWeakFrame
242
0
    void Revoke() {
243
0
      mFrame = nullptr;
244
0
    }
245
246
  private:
247
    nsTextControlFrame* mFrame;
248
  };
249
250
  class ScrollOnFocusEvent;
251
  friend class ScrollOnFocusEvent;
252
253
  class ScrollOnFocusEvent : public mozilla::Runnable {
254
  public:
255
    explicit ScrollOnFocusEvent(nsTextControlFrame* aFrame)
256
      : mozilla::Runnable("nsTextControlFrame::ScrollOnFocusEvent")
257
      , mFrame(aFrame)
258
0
    {
259
0
    }
260
261
    NS_DECL_NSIRUNNABLE
262
263
0
    void Revoke() {
264
0
      mFrame = nullptr;
265
0
    }
266
267
  private:
268
    nsTextControlFrame* mFrame;
269
  };
270
271
  nsresult OffsetToDOMPoint(uint32_t aOffset, nsINode** aResult,
272
                            uint32_t* aPosition);
273
274
  /**
275
   * Update the textnode under our anonymous div to show the new
276
   * value. This should only be called when we have no editor yet.
277
   * @throws NS_ERROR_UNEXPECTED if the div has no text content
278
   */
279
  nsresult UpdateValueDisplay(bool aNotify,
280
                              bool aBeforeEditorInit = false,
281
                              const nsAString *aValue = nullptr);
282
283
  /**
284
   * Get the maxlength attribute
285
   * @param aMaxLength the value of the max length attr
286
   * @returns false if attr not defined
287
   */
288
  bool GetMaxLength(int32_t* aMaxLength);
289
290
  /**
291
   * Find out whether an attribute exists on the content or not.
292
   * @param aAtt the attribute to determine the existence of
293
   * @returns false if it does not exist
294
   */
295
  bool AttributeExists(nsAtom *aAtt) const
296
0
  { return mContent && mContent->AsElement()->HasAttr(kNameSpaceID_None, aAtt); }
297
298
  /**
299
   * We call this when we are being destroyed or removed from the PFM.
300
   * @param aPresContext the current pres context
301
   */
302
  void PreDestroy();
303
304
  // Compute our intrinsic size.  This does not include any borders, paddings,
305
  // etc.  Just the size of our actual area for the text (and the scrollbars,
306
  // for <textarea>).
307
  mozilla::LogicalSize CalcIntrinsicSize(gfxContext* aRenderingContext,
308
                                         mozilla::WritingMode aWM,
309
                                         float aFontSizeInflation) const;
310
311
  nsresult ScrollSelectionIntoView() override;
312
313
private:
314
  //helper methods
315
  nsresult SetSelectionInternal(nsINode* aStartNode, uint32_t aStartOffset,
316
                                nsINode* aEndNode, uint32_t aEndOffset,
317
                                SelectionDirection aDirection = eNone);
318
  nsresult SelectAllOrCollapseToEndOfText(bool aSelect);
319
  nsresult SetSelectionEndPoints(uint32_t aSelStart, uint32_t aSelEnd,
320
                                 SelectionDirection aDirection = eNone);
321
322
0
  void FinishedInitializer() {
323
0
    DeleteProperty(TextControlInitializer());
324
0
  }
325
326
  const nsAString& CachedValue() const
327
0
  {
328
0
    return mCachedValue;
329
0
  }
330
331
  void ClearCachedValue()
332
0
  {
333
0
    mCachedValue.SetIsVoid(true);
334
0
  }
335
336
  void CacheValue(const nsAString& aValue)
337
0
  {
338
0
    mCachedValue.Assign(aValue);
339
0
  }
340
341
  MOZ_MUST_USE bool
342
  CacheValue(const nsAString& aValue, const mozilla::fallible_t& aFallible)
343
0
  {
344
0
    if (!mCachedValue.Assign(aValue, aFallible)) {
345
0
      ClearCachedValue();
346
0
      return false;
347
0
    }
348
0
    return true;
349
0
  }
350
351
private:
352
  class nsAnonDivObserver;
353
354
  nsresult CreateRootNode();
355
  void CreatePlaceholderIfNeeded();
356
  void CreatePreviewIfNeeded();
357
  bool ShouldInitializeEagerly() const;
358
  void InitializeEagerlyIfNeeded();
359
360
  RefPtr<mozilla::dom::Element> mRootNode;
361
  RefPtr<mozilla::dom::Element> mPlaceholderDiv;
362
  RefPtr<mozilla::dom::Element> mPreviewDiv;
363
  RefPtr<nsAnonDivObserver> mMutationObserver;
364
  // Cache of the |.value| of <input> or <textarea> element without hard-wrap.
365
  // If its IsVoid() returns true, it doesn't cache |.value|.
366
  // Otherwise, it's cached when setting specific value or getting value from
367
  // TextEditor.  Additionally, when contents in the anonymous <div> element
368
  // is modified, this is cleared.
369
  //
370
  // FIXME(bug 1402545): Consider using an nsAutoString here.
371
  nsString mCachedValue;
372
373
  // Our first baseline, or NS_INTRINSIC_WIDTH_UNKNOWN if we have a pending
374
  // Reflow.
375
  nscoord mFirstBaseline;
376
377
  // these packed bools could instead use the high order bits on mState, saving 4 bytes
378
  bool mEditorHasBeenInitialized;
379
  bool mIsProcessing;
380
381
#ifdef DEBUG
382
  bool mInEditorInitialization;
383
  friend class EditorInitializerEntryTracker;
384
#endif
385
386
  nsRevocableEventPtr<ScrollOnFocusEvent> mScrollEvent;
387
};
388
389
#endif
390
391