Line data Source code
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_dom_HTMLInputElement_h
8 : #define mozilla_dom_HTMLInputElement_h
9 :
10 : #include "mozilla/Attributes.h"
11 : #include "nsGenericHTMLElement.h"
12 : #include "nsImageLoadingContent.h"
13 : #include "nsIDOMHTMLInputElement.h"
14 : #include "nsITextControlElement.h"
15 : #include "nsITimer.h"
16 : #include "nsIDOMNSEditableElement.h"
17 : #include "nsCOMPtr.h"
18 : #include "nsIConstraintValidation.h"
19 : #include "mozilla/UniquePtr.h"
20 : #include "mozilla/dom/BindingDeclarations.h"
21 : #include "mozilla/dom/HTMLFormElement.h" // for HasEverTriedInvalidSubmit()
22 : #include "mozilla/dom/HTMLInputElementBinding.h"
23 : #include "mozilla/dom/Promise.h"
24 : #include "mozilla/dom/UnionTypes.h"
25 : #include "nsIFilePicker.h"
26 : #include "nsIContentPrefService2.h"
27 : #include "mozilla/Decimal.h"
28 : #include "nsContentUtils.h"
29 : #include "nsTextEditorState.h"
30 : #include "mozilla/Variant.h"
31 : #include "SingleLineTextInputTypes.h"
32 : #include "NumericInputTypes.h"
33 : #include "CheckableInputTypes.h"
34 : #include "ButtonInputTypes.h"
35 : #include "DateTimeInputTypes.h"
36 : #include "ColorInputType.h"
37 : #include "FileInputType.h"
38 : #include "HiddenInputType.h"
39 :
40 : static constexpr size_t INPUT_TYPE_SIZE = sizeof(
41 : mozilla::Variant<TextInputType, SearchInputType, TelInputType, URLInputType,
42 : EmailInputType, PasswordInputType, NumberInputType,
43 : RangeInputType, RadioInputType, CheckboxInputType,
44 : ButtonInputType, ImageInputType, ResetInputType,
45 : SubmitInputType, DateInputType, TimeInputType, WeekInputType,
46 : MonthInputType, DateTimeLocalInputType, FileInputType,
47 : ColorInputType, HiddenInputType> );
48 :
49 : class InputType;
50 : struct DoNotDelete;
51 : class nsIRadioGroupContainer;
52 : class nsIRadioVisitor;
53 :
54 : namespace mozilla {
55 :
56 : class EventChainPostVisitor;
57 : class EventChainPreVisitor;
58 :
59 : namespace dom {
60 :
61 : class AfterSetFilesOrDirectoriesRunnable;
62 : class Date;
63 : class DispatchChangeEventCallback;
64 : class File;
65 : class FileList;
66 : class FileSystemEntry;
67 : class GetFilesHelper;
68 :
69 : /**
70 : * A class we use to create a singleton object that is used to keep track of
71 : * the last directory from which the user has picked files (via
72 : * <input type=file>) on a per-domain basis. The implementation uses
73 : * nsIContentPrefService2/NS_CONTENT_PREF_SERVICE_CONTRACTID to store the last
74 : * directory per-domain, and to ensure that whether the directories are
75 : * persistently saved (saved across sessions) or not honors whether or not the
76 : * page is being viewed in private browsing.
77 : */
78 1 : class UploadLastDir final : public nsIObserver, public nsSupportsWeakReference
79 : {
80 0 : ~UploadLastDir() {}
81 :
82 : public:
83 : NS_DECL_ISUPPORTS
84 : NS_DECL_NSIOBSERVER
85 :
86 : /**
87 : * Fetch the last used directory for this location from the content
88 : * pref service, and display the file picker opened in that directory.
89 : *
90 : * @param aDoc current document
91 : * @param aFilePicker the file picker to open
92 : * @param aFpCallback the callback object to be run when the file is shown.
93 : */
94 : nsresult FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
95 : nsIFilePicker* aFilePicker,
96 : nsIFilePickerShownCallback* aFpCallback);
97 :
98 : /**
99 : * Store the last used directory for this location using the
100 : * content pref service, if it is available
101 : * @param aURI URI of the current page
102 : * @param aDir Parent directory of the file(s)/directory chosen by the user
103 : */
104 : nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir);
105 :
106 : class ContentPrefCallback final : public nsIContentPrefCallback2
107 : {
108 0 : virtual ~ContentPrefCallback()
109 0 : { }
110 :
111 : public:
112 0 : ContentPrefCallback(nsIFilePicker* aFilePicker, nsIFilePickerShownCallback* aFpCallback)
113 0 : : mFilePicker(aFilePicker)
114 0 : , mFpCallback(aFpCallback)
115 0 : { }
116 :
117 : NS_DECL_ISUPPORTS
118 : NS_DECL_NSICONTENTPREFCALLBACK2
119 :
120 : nsCOMPtr<nsIFilePicker> mFilePicker;
121 : nsCOMPtr<nsIFilePickerShownCallback> mFpCallback;
122 : nsCOMPtr<nsIContentPref> mResult;
123 : };
124 : };
125 :
126 : class HTMLInputElement final : public nsGenericHTMLFormElementWithState,
127 : public nsImageLoadingContent,
128 : public nsIDOMHTMLInputElement,
129 : public nsITextControlElement,
130 : public nsIDOMNSEditableElement,
131 : public nsIConstraintValidation
132 : {
133 : friend class AfterSetFilesOrDirectoriesCallback;
134 : friend class DispatchChangeEventCallback;
135 : friend class ::InputType;
136 :
137 : public:
138 : using nsIConstraintValidation::GetValidationMessage;
139 : using nsIConstraintValidation::CheckValidity;
140 : using nsIConstraintValidation::ReportValidity;
141 : using nsIConstraintValidation::WillValidate;
142 : using nsIConstraintValidation::Validity;
143 : using nsGenericHTMLFormElementWithState::GetForm;
144 :
145 : enum class FromClone { no, yes };
146 :
147 : HTMLInputElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
148 : mozilla::dom::FromParser aFromParser,
149 : FromClone aFromClone = FromClone::no);
150 :
151 418 : NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLInputElement, input)
152 :
153 : // nsISupports
154 : NS_DECL_ISUPPORTS_INHERITED
155 :
156 : virtual int32_t TabIndexDefault() override;
157 : using nsGenericHTMLElement::Focus;
158 : virtual void Blur(ErrorResult& aError) override;
159 : virtual void Focus(ErrorResult& aError) override;
160 :
161 : // nsINode
162 : #if !defined(ANDROID) && !defined(XP_MACOSX)
163 : virtual bool IsNodeApzAwareInternal() const override;
164 : #endif
165 :
166 : // Element
167 : virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
168 :
169 : // EventTarget
170 : virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
171 :
172 : // nsIDOMHTMLInputElement
173 : NS_DECL_NSIDOMHTMLINPUTELEMENT
174 :
175 : // nsIDOMNSEditableElement
176 0 : NS_IMETHOD GetEditor(nsIEditor** aEditor) override
177 : {
178 0 : nsCOMPtr<nsIEditor> editor = GetEditor();
179 0 : editor.forget(aEditor);
180 0 : return NS_OK;
181 : }
182 :
183 : NS_IMETHOD SetUserInput(const nsAString& aInput) override;
184 :
185 : // Overriden nsIFormControl methods
186 : NS_IMETHOD Reset() override;
187 : NS_IMETHOD SubmitNamesValues(HTMLFormSubmission* aFormSubmission) override;
188 : NS_IMETHOD SaveState() override;
189 : virtual bool RestoreState(nsPresState* aState) override;
190 : virtual bool AllowDrop() override;
191 : virtual bool IsDisabledForEvents(EventMessage aMessage) override;
192 :
193 : virtual void FieldSetDisabledChanged(bool aNotify) override;
194 :
195 : // nsIContent
196 : virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
197 :
198 : virtual bool ParseAttribute(int32_t aNamespaceID,
199 : nsIAtom* aAttribute,
200 : const nsAString& aValue,
201 : nsAttrValue& aResult) override;
202 : virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
203 : int32_t aModType) const override;
204 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
205 : virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
206 :
207 : virtual nsresult GetEventTargetParent(
208 : EventChainPreVisitor& aVisitor) override;
209 : virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override;
210 : virtual nsresult PostHandleEvent(
211 : EventChainPostVisitor& aVisitor) override;
212 : void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
213 : void StartRangeThumbDrag(WidgetGUIEvent* aEvent);
214 : void FinishRangeThumbDrag(WidgetGUIEvent* aEvent = nullptr);
215 : void CancelRangeThumbDrag(bool aIsForUserEvent = true);
216 : void SetValueOfRangeForUserEvent(Decimal aValue);
217 :
218 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
219 : nsIContent* aBindingParent,
220 : bool aCompileEventHandlers) override;
221 : virtual void UnbindFromTree(bool aDeep = true,
222 : bool aNullParent = true) override;
223 :
224 : virtual void DoneCreatingElement() override;
225 :
226 : virtual EventStates IntrinsicState() const override;
227 :
228 : // Element
229 : private:
230 : virtual void AddStates(EventStates aStates) override;
231 : virtual void RemoveStates(EventStates aStates) override;
232 :
233 : public:
234 :
235 : // nsITextControlElement
236 : NS_IMETHOD SetValueChanged(bool aValueChanged) override;
237 : NS_IMETHOD_(bool) IsSingleLineTextControl() const override;
238 : NS_IMETHOD_(bool) IsTextArea() const override;
239 : NS_IMETHOD_(bool) IsPlainTextControl() const override;
240 : NS_IMETHOD_(bool) IsPasswordTextControl() const override;
241 : NS_IMETHOD_(int32_t) GetCols() override;
242 : NS_IMETHOD_(int32_t) GetWrapCols() override;
243 : NS_IMETHOD_(int32_t) GetRows() override;
244 : NS_IMETHOD_(void) GetDefaultValueFromContent(nsAString& aValue) override;
245 : NS_IMETHOD_(bool) ValueChanged() const override;
246 : NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
247 : NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
248 : NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
249 : NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
250 : NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
251 : NS_IMETHOD_(void) UnbindFromFrame(nsTextControlFrame* aFrame) override;
252 : NS_IMETHOD CreateEditor() override;
253 : NS_IMETHOD_(Element*) GetRootEditorNode() override;
254 : NS_IMETHOD_(Element*) CreatePlaceholderNode() override;
255 : NS_IMETHOD_(Element*) GetPlaceholderNode() override;
256 : NS_IMETHOD_(Element*) CreatePreviewNode() override;
257 : NS_IMETHOD_(Element*) GetPreviewNode() override;
258 : NS_IMETHOD_(void) UpdateOverlayTextVisibility(bool aNotify) override;
259 : NS_IMETHOD_(void) SetPreviewValue(const nsAString& aValue) override;
260 : NS_IMETHOD_(void) GetPreviewValue(nsAString& aValue) override;
261 : NS_IMETHOD_(void) EnablePreview() override;
262 : NS_IMETHOD_(bool) IsPreviewEnabled() override;
263 : NS_IMETHOD_(bool) GetPlaceholderVisibility() override;
264 : NS_IMETHOD_(bool) GetPreviewVisibility() override;
265 : NS_IMETHOD_(void) InitializeKeyboardEventListeners() override;
266 : NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override;
267 : virtual void GetValueFromSetRangeText(nsAString& aValue) override;
268 : virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override;
269 : NS_IMETHOD_(bool) HasCachedSelection() override;
270 :
271 : // Methods for nsFormFillController so it can do selection operations on input
272 : // types the HTML spec doesn't support them on, like "email".
273 : uint32_t GetSelectionStartIgnoringType(ErrorResult& aRv);
274 : uint32_t GetSelectionEndIgnoringType(ErrorResult& aRv);
275 :
276 : void GetDisplayFileName(nsAString& aFileName) const;
277 :
278 : const nsTArray<OwningFileOrDirectory>& GetFilesOrDirectoriesInternal() const;
279 :
280 : void SetFilesOrDirectories(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories,
281 : bool aSetValueChanged);
282 : void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
283 :
284 : // This method is used for test only. Onces the data is set, a 'change' event
285 : // is dispatched.
286 : void MozSetDndFilesAndDirectories(const nsTArray<OwningFileOrDirectory>& aSequence);
287 :
288 : // Called when a nsIFilePicker or a nsIColorPicker terminate.
289 : void PickerClosed();
290 :
291 : void SetCheckedChangedInternal(bool aCheckedChanged);
292 0 : bool GetCheckedChanged() const {
293 0 : return mCheckedChanged;
294 : }
295 : void AddedToRadioGroup();
296 : void WillRemoveFromRadioGroup();
297 :
298 : /**
299 : * Helper function returning the currently selected button in the radio group.
300 : * Returning null if the element is not a button or if there is no selectied
301 : * button in the group.
302 : *
303 : * @return the selected button (or null).
304 : */
305 : already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton() const;
306 :
307 : virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
308 : bool aPreallocateChildren) const override;
309 :
310 27 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLInputElement,
311 : nsGenericHTMLFormElementWithState)
312 :
313 : static UploadLastDir* gUploadLastDir;
314 : // create and destroy the static UploadLastDir object for remembering
315 : // which directory was last used on a site-by-site basis
316 : static void InitUploadLastDir();
317 : static void DestroyUploadLastDir();
318 :
319 : //If the valueAsDate attribute should be enabled in webIDL
320 : static bool ValueAsDateEnabled(JSContext* cx, JSObject* obj);
321 :
322 : void MaybeLoadImage();
323 :
324 0 : void SetSelectionCached()
325 : {
326 0 : MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
327 0 : mSelectionCached = true;
328 0 : }
329 0 : bool IsSelectionCached() const
330 : {
331 0 : MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
332 0 : return mSelectionCached;
333 : }
334 0 : void ClearSelectionCached()
335 : {
336 0 : MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
337 0 : mSelectionCached = false;
338 0 : }
339 0 : nsTextEditorState::SelectionProperties& GetSelectionProperties()
340 : {
341 0 : MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
342 0 : return mSelectionProperties;
343 : }
344 :
345 : // nsIConstraintValidation
346 : bool IsTooLong();
347 : bool IsTooShort();
348 : bool IsValueMissing() const;
349 : bool HasTypeMismatch() const;
350 : bool HasPatternMismatch() const;
351 : bool IsRangeOverflow() const;
352 : bool IsRangeUnderflow() const;
353 : bool HasStepMismatch(bool aUseZeroIfValueNaN = false) const;
354 : bool HasBadInput() const;
355 : void UpdateTooLongValidityState();
356 : void UpdateTooShortValidityState();
357 : void UpdateValueMissingValidityState();
358 : void UpdateTypeMismatchValidityState();
359 : void UpdatePatternMismatchValidityState();
360 : void UpdateRangeOverflowValidityState();
361 : void UpdateRangeUnderflowValidityState();
362 : void UpdateStepMismatchValidityState();
363 : void UpdateBadInputValidityState();
364 : void UpdateAllValidityStates(bool aNotify);
365 : void UpdateBarredFromConstraintValidation();
366 : nsresult GetValidationMessage(nsAString& aValidationMessage,
367 : ValidityStateType aType) override;
368 : /**
369 : * Update the value missing validity state for radio elements when they have
370 : * a group.
371 : *
372 : * @param aIgnoreSelf Whether the required attribute and the checked state
373 : * of the current radio should be ignored.
374 : * @note This method shouldn't be called if the radio element hasn't a group.
375 : */
376 : void UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf);
377 :
378 : /**
379 : * Set filters to the filePicker according to the accept attribute value.
380 : *
381 : * See:
382 : * http://dev.w3.org/html5/spec/forms.html#attr-input-accept
383 : *
384 : * @note You should not call this function if the element has no @accept.
385 : * @note "All Files" filter is always set, no matter if there is a valid
386 : * filter specified or not.
387 : * @note If more than one valid filter is found, the "All Supported Types"
388 : * filter is added, which is the concatenation of all valid filters.
389 : * @note Duplicate filters and similar filters (i.e. filters whose file
390 : * extensions already exist in another filter) are ignored.
391 : * @note "All Files" filter will be selected by default if unknown mime types
392 : * have been specified and no file extension filter has been specified.
393 : * Otherwise, specified filter or "All Supported Types" filter will be
394 : * selected by default.
395 : * The logic behind is that having unknown mime type means we might restrict
396 : * user's input too much, as some filters will be missing.
397 : * However, if author has also specified some file extension filters, it's
398 : * likely those are fallback for the unusual mime type we haven't been able
399 : * to resolve; so it's better to select author specified filters in that case.
400 : */
401 : void SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker);
402 :
403 : /**
404 : * The form might need to request an update of the UI bits
405 : * (BF_CAN_SHOW_INVALID_UI and BF_CAN_SHOW_VALID_UI) when an invalid form
406 : * submission is tried.
407 : *
408 : * @param aIsFocused Whether the element is currently focused.
409 : *
410 : * @note The caller is responsible to call ContentStatesChanged.
411 : */
412 : void UpdateValidityUIBits(bool aIsFocused);
413 :
414 : /**
415 : * Fires change event if mFocusedValue and current value held are unequal.
416 : */
417 : void FireChangeEventIfNeeded();
418 :
419 : /**
420 : * Returns the input element's value as a Decimal.
421 : * Returns NaN if the current element's value is not a floating point number.
422 : *
423 : * @return the input element's value as a Decimal.
424 : */
425 : Decimal GetValueAsDecimal() const;
426 :
427 : /**
428 : * Returns the input's "minimum" (as defined by the HTML5 spec) as a double.
429 : * Note this takes account of any default minimum that the type may have.
430 : * Returns NaN if the min attribute isn't a valid floating point number and
431 : * the input's type does not have a default minimum.
432 : *
433 : * NOTE: Only call this if you know DoesMinMaxApply() returns true.
434 : */
435 : Decimal GetMinimum() const;
436 :
437 : /**
438 : * Returns the input's "maximum" (as defined by the HTML5 spec) as a double.
439 : * Note this takes account of any default maximum that the type may have.
440 : * Returns NaN if the max attribute isn't a valid floating point number and
441 : * the input's type does not have a default maximum.
442 : *
443 : * NOTE:Only call this if you know DoesMinMaxApply() returns true.
444 : */
445 : Decimal GetMaximum() const;
446 :
447 : // WebIDL
448 :
449 : // XPCOM GetAccept() is OK
450 0 : void SetAccept(const nsAString& aValue, ErrorResult& aRv)
451 : {
452 0 : SetHTMLAttr(nsGkAtoms::accept, aValue, aRv);
453 0 : }
454 :
455 : // XPCOM GetAlt() is OK
456 0 : void SetAlt(const nsAString& aValue, ErrorResult& aRv)
457 : {
458 0 : SetHTMLAttr(nsGkAtoms::alt, aValue, aRv);
459 0 : }
460 :
461 : // XPCOM GetAutocomplete() is OK
462 0 : void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv)
463 : {
464 0 : SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
465 0 : }
466 :
467 : void GetAutocompleteInfo(Nullable<AutocompleteInfo>& aInfo);
468 :
469 0 : bool Autofocus() const
470 : {
471 0 : return GetBoolAttr(nsGkAtoms::autofocus);
472 : }
473 :
474 0 : void SetAutofocus(bool aValue, ErrorResult& aRv)
475 : {
476 0 : SetHTMLBoolAttr(nsGkAtoms::autofocus, aValue, aRv);
477 0 : }
478 :
479 0 : bool DefaultChecked() const
480 : {
481 0 : return HasAttr(kNameSpaceID_None, nsGkAtoms::checked);
482 : }
483 :
484 0 : void SetDefaultChecked(bool aValue, ErrorResult& aRv)
485 : {
486 0 : SetHTMLBoolAttr(nsGkAtoms::checked, aValue, aRv);
487 0 : }
488 :
489 0 : bool Checked() const
490 : {
491 0 : return mChecked;
492 : }
493 : // XPCOM SetChecked() is OK
494 :
495 0 : bool Disabled() const
496 : {
497 0 : return GetBoolAttr(nsGkAtoms::disabled);
498 : }
499 :
500 0 : void SetDisabled(bool aValue,ErrorResult& aRv)
501 : {
502 0 : SetHTMLBoolAttr(nsGkAtoms::disabled, aValue, aRv);
503 0 : }
504 :
505 : // XPCOM GetForm() is OK
506 :
507 : FileList* GetFiles();
508 :
509 : // XPCOM GetFormAction() is OK
510 0 : void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
511 : {
512 0 : SetHTMLAttr(nsGkAtoms::formaction, aValue, aRv);
513 0 : }
514 :
515 : // XPCOM GetFormEnctype() is OK
516 0 : void SetFormEnctype(const nsAString& aValue, ErrorResult& aRv)
517 : {
518 0 : SetHTMLAttr(nsGkAtoms::formenctype, aValue, aRv);
519 0 : }
520 :
521 : // XPCOM GetFormMethod() is OK
522 0 : void SetFormMethod(const nsAString& aValue, ErrorResult& aRv)
523 : {
524 0 : SetHTMLAttr(nsGkAtoms::formmethod, aValue, aRv);
525 0 : }
526 :
527 0 : bool FormNoValidate() const
528 : {
529 0 : return GetBoolAttr(nsGkAtoms::formnovalidate);
530 : }
531 :
532 0 : void SetFormNoValidate(bool aValue, ErrorResult& aRv)
533 : {
534 0 : SetHTMLBoolAttr(nsGkAtoms::formnovalidate, aValue, aRv);
535 0 : }
536 :
537 : // XPCOM GetFormTarget() is OK
538 0 : void SetFormTarget(const nsAString& aValue, ErrorResult& aRv)
539 : {
540 0 : SetHTMLAttr(nsGkAtoms::formtarget, aValue, aRv);
541 0 : }
542 :
543 : uint32_t Height();
544 :
545 0 : void SetHeight(uint32_t aValue, ErrorResult& aRv)
546 : {
547 0 : SetUnsignedIntAttr(nsGkAtoms::height, aValue, 0, aRv);
548 0 : }
549 :
550 0 : bool Indeterminate() const
551 : {
552 0 : return mIndeterminate;
553 : }
554 : // XPCOM SetIndeterminate() is OK
555 :
556 : // XPCOM GetInputMode() is OK
557 0 : void SetInputMode(const nsAString& aValue, ErrorResult& aRv)
558 : {
559 0 : SetHTMLAttr(nsGkAtoms::inputmode, aValue, aRv);
560 0 : }
561 :
562 : nsGenericHTMLElement* GetList() const;
563 :
564 : // XPCOM GetMax() is OK
565 0 : void SetMax(const nsAString& aValue, ErrorResult& aRv)
566 : {
567 0 : SetHTMLAttr(nsGkAtoms::max, aValue, aRv);
568 0 : }
569 :
570 0 : int32_t MaxLength() const
571 : {
572 0 : return GetIntAttr(nsGkAtoms::maxlength, -1);
573 : }
574 :
575 0 : void SetMaxLength(int32_t aValue, ErrorResult& aRv)
576 : {
577 0 : int32_t minLength = MinLength();
578 0 : if (aValue < 0 || (minLength >= 0 && aValue < minLength)) {
579 0 : aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
580 0 : return;
581 : }
582 :
583 0 : SetHTMLIntAttr(nsGkAtoms::maxlength, aValue, aRv);
584 : }
585 :
586 0 : int32_t MinLength() const
587 : {
588 0 : return GetIntAttr(nsGkAtoms::minlength, -1);
589 : }
590 :
591 0 : void SetMinLength(int32_t aValue, ErrorResult& aRv)
592 : {
593 0 : int32_t maxLength = MaxLength();
594 0 : if (aValue < 0 || (maxLength >= 0 && aValue > maxLength)) {
595 0 : aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
596 0 : return;
597 : }
598 :
599 0 : SetHTMLIntAttr(nsGkAtoms::minlength, aValue, aRv);
600 : }
601 :
602 : // XPCOM GetMin() is OK
603 0 : void SetMin(const nsAString& aValue, ErrorResult& aRv)
604 : {
605 0 : SetHTMLAttr(nsGkAtoms::min, aValue, aRv);
606 0 : }
607 :
608 0 : bool Multiple() const
609 : {
610 0 : return GetBoolAttr(nsGkAtoms::multiple);
611 : }
612 :
613 0 : void SetMultiple(bool aValue, ErrorResult& aRv)
614 : {
615 0 : SetHTMLBoolAttr(nsGkAtoms::multiple, aValue, aRv);
616 0 : }
617 :
618 : // XPCOM GetName() is OK
619 0 : void SetName(const nsAString& aValue, ErrorResult& aRv)
620 : {
621 0 : SetHTMLAttr(nsGkAtoms::name, aValue, aRv);
622 0 : }
623 :
624 : // XPCOM GetPattern() is OK
625 0 : void SetPattern(const nsAString& aValue, ErrorResult& aRv)
626 : {
627 0 : SetHTMLAttr(nsGkAtoms::pattern, aValue, aRv);
628 0 : }
629 :
630 : // XPCOM GetPlaceholder() is OK
631 0 : void SetPlaceholder(const nsAString& aValue, ErrorResult& aRv)
632 : {
633 0 : SetHTMLAttr(nsGkAtoms::placeholder, aValue, aRv);
634 0 : }
635 :
636 0 : bool ReadOnly() const
637 : {
638 0 : return GetBoolAttr(nsGkAtoms::readonly);
639 : }
640 :
641 0 : void SetReadOnly(bool aValue, ErrorResult& aRv)
642 : {
643 0 : SetHTMLBoolAttr(nsGkAtoms::readonly, aValue, aRv);
644 0 : }
645 :
646 0 : bool Required() const
647 : {
648 0 : return GetBoolAttr(nsGkAtoms::required);
649 : }
650 :
651 0 : void SetRequired(bool aValue, ErrorResult& aRv)
652 : {
653 0 : SetHTMLBoolAttr(nsGkAtoms::required, aValue, aRv);
654 0 : }
655 :
656 0 : uint32_t Size() const
657 : {
658 0 : return GetUnsignedIntAttr(nsGkAtoms::size, DEFAULT_COLS);
659 : }
660 :
661 0 : void SetSize(uint32_t aValue, ErrorResult& aRv)
662 : {
663 0 : if (aValue == 0) {
664 0 : aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
665 0 : return;
666 : }
667 :
668 0 : SetUnsignedIntAttr(nsGkAtoms::size, aValue, DEFAULT_COLS, aRv);
669 : }
670 :
671 : // XPCOM GetSrc() is OK
672 0 : void SetSrc(const nsAString& aValue, ErrorResult& aRv)
673 : {
674 0 : SetHTMLAttr(nsGkAtoms::src, aValue, aRv);
675 0 : }
676 :
677 : // XPCOM GetStep() is OK
678 0 : void SetStep(const nsAString& aValue, ErrorResult& aRv)
679 : {
680 0 : SetHTMLAttr(nsGkAtoms::step, aValue, aRv);
681 0 : }
682 :
683 : // XPCOM GetType() is OK
684 0 : void SetType(const nsAString& aValue, ErrorResult& aRv)
685 : {
686 0 : SetHTMLAttr(nsGkAtoms::type, aValue, aRv);
687 0 : }
688 :
689 : // XPCOM GetDefaultValue() is OK
690 0 : void SetDefaultValue(const nsAString& aValue, ErrorResult& aRv)
691 : {
692 0 : SetHTMLAttr(nsGkAtoms::value, aValue, aRv);
693 0 : }
694 :
695 : void SetValue(const nsAString& aValue, CallerType aCallerType,
696 : ErrorResult& aRv);
697 : void GetValue(nsAString& aValue, CallerType aCallerType);
698 :
699 : Nullable<Date> GetValueAsDate(ErrorResult& aRv);
700 :
701 : void SetValueAsDate(const Nullable<Date>& aDate, ErrorResult& aRv);
702 :
703 0 : double ValueAsNumber() const
704 : {
705 0 : return DoesValueAsNumberApply() ? GetValueAsDecimal().toDouble()
706 0 : : UnspecifiedNaN<double>();
707 : }
708 :
709 : void SetValueAsNumber(double aValue, ErrorResult& aRv);
710 :
711 : uint32_t Width();
712 :
713 0 : void SetWidth(uint32_t aValue, ErrorResult& aRv)
714 : {
715 0 : SetUnsignedIntAttr(nsGkAtoms::width, aValue, 0, aRv);
716 0 : }
717 :
718 0 : void StepUp(int32_t aN, ErrorResult& aRv)
719 : {
720 0 : aRv = ApplyStep(aN);
721 0 : }
722 :
723 0 : void StepDown(int32_t aN, ErrorResult& aRv)
724 : {
725 0 : aRv = ApplyStep(-aN);
726 0 : }
727 :
728 : /**
729 : * Returns the current step value.
730 : * Returns kStepAny if the current step is "any" string.
731 : *
732 : * @return the current step value.
733 : */
734 : Decimal GetStep() const;
735 :
736 : void GetValidationMessage(nsAString& aValidationMessage, ErrorResult& aRv);
737 :
738 : // XPCOM GetCustomVisibility() is OK
739 :
740 : already_AddRefed<nsINodeList> GetLabels();
741 :
742 : // XPCOM Select() is OK
743 :
744 : Nullable<uint32_t> GetSelectionStart(ErrorResult& aRv);
745 : void SetSelectionStart(const Nullable<uint32_t>& aValue, ErrorResult& aRv);
746 :
747 : Nullable<uint32_t> GetSelectionEnd(ErrorResult& aRv);
748 : void SetSelectionEnd(const Nullable<uint32_t>& aValue, ErrorResult& aRv);
749 :
750 : void GetSelectionDirection(nsAString& aValue, ErrorResult& aRv);
751 : void SetSelectionDirection(const nsAString& aValue, ErrorResult& aRv);
752 :
753 : void SetSelectionRange(uint32_t aStart, uint32_t aEnd,
754 : const Optional< nsAString >& direction,
755 : ErrorResult& aRv);
756 :
757 : void SetRangeText(const nsAString& aReplacement, ErrorResult& aRv);
758 :
759 : void SetRangeText(const nsAString& aReplacement, uint32_t aStart,
760 : uint32_t aEnd, SelectionMode aSelectMode,
761 : ErrorResult& aRv);
762 :
763 0 : bool Allowdirs() const
764 : {
765 0 : return HasAttr(kNameSpaceID_None, nsGkAtoms::allowdirs);
766 : }
767 :
768 0 : void SetAllowdirs(bool aValue, ErrorResult& aRv)
769 : {
770 0 : SetHTMLBoolAttr(nsGkAtoms::allowdirs, aValue, aRv);
771 0 : }
772 :
773 0 : bool WebkitDirectoryAttr() const
774 : {
775 0 : return HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory);
776 : }
777 :
778 0 : void SetWebkitDirectoryAttr(bool aValue, ErrorResult& aRv)
779 : {
780 0 : SetHTMLBoolAttr(nsGkAtoms::webkitdirectory, aValue, aRv);
781 0 : }
782 :
783 : void GetWebkitEntries(nsTArray<RefPtr<FileSystemEntry>>& aSequence);
784 :
785 : bool IsFilesAndDirectoriesSupported() const;
786 :
787 : already_AddRefed<Promise> GetFilesAndDirectories(ErrorResult& aRv);
788 :
789 : already_AddRefed<Promise> GetFiles(bool aRecursiveFlag, ErrorResult& aRv);
790 :
791 : void ChooseDirectory(ErrorResult& aRv);
792 :
793 : // XPCOM GetAlign() is OK
794 0 : void SetAlign(const nsAString& aValue, ErrorResult& aRv)
795 : {
796 0 : SetHTMLAttr(nsGkAtoms::align, aValue, aRv);
797 0 : }
798 :
799 : // XPCOM GetUseMap() is OK
800 0 : void SetUseMap(const nsAString& aValue, ErrorResult& aRv)
801 : {
802 0 : SetHTMLAttr(nsGkAtoms::usemap, aValue, aRv);
803 0 : }
804 :
805 : nsIControllers* GetControllers(ErrorResult& aRv);
806 :
807 : int32_t InputTextLength(CallerType aCallerType);
808 :
809 : void MozGetFileNameArray(nsTArray<nsString>& aFileNames, ErrorResult& aRv);
810 :
811 : void MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv);
812 : void MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles);
813 : void MozSetDirectory(const nsAString& aDirectoryPath, ErrorResult& aRv);
814 :
815 0 : bool MozInputRangeIgnorePreventDefault() const
816 : {
817 0 : return (IsInChromeDocument() || IsInNativeAnonymousSubtree()) &&
818 0 : GetBoolAttr(nsGkAtoms::mozinputrangeignorepreventdefault);
819 : }
820 :
821 : /*
822 : * The following functions are called from datetime picker to let input box
823 : * know the current state of the picker or to update the input box on changes.
824 : */
825 : void GetDateTimeInputBoxValue(DateTimeValue& aValue);
826 : void UpdateDateTimeInputBox(const DateTimeValue& aValue);
827 : void SetDateTimePickerState(bool aOpen);
828 :
829 : /*
830 : * The following functions are called from datetime input box XBL to control
831 : * and update the picker.
832 : */
833 : void OpenDateTimePicker(const DateTimeValue& aInitialValue);
834 : void UpdateDateTimePicker(const DateTimeValue& aValue);
835 : void CloseDateTimePicker();
836 :
837 : /*
838 : * Called from datetime input box binding when inner text fields are focused
839 : * or blurred.
840 : */
841 : void SetFocusState(bool aIsFocused);
842 :
843 : /*
844 : * Called from datetime input box binding when the the user entered value
845 : * becomes valid/invalid.
846 : */
847 : void UpdateValidityState();
848 :
849 : /*
850 : * The following are called from datetime input box binding to get the
851 : * corresponding computed values.
852 : */
853 0 : double GetStepAsDouble() { return GetStep().toDouble(); }
854 0 : double GetStepBaseAsDouble() { return GetStepBase().toDouble(); }
855 :
856 : HTMLInputElement* GetOwnerNumberControl();
857 :
858 : void StartNumberControlSpinnerSpin();
859 : enum SpinnerStopState {
860 : eAllowDispatchingEvents,
861 : eDisallowDispatchingEvents
862 : };
863 : void StopNumberControlSpinnerSpin(SpinnerStopState aState =
864 : eAllowDispatchingEvents);
865 : void StepNumberControlForUserEvent(int32_t aDirection);
866 :
867 : /**
868 : * The callback function used by the nsRepeatService that we use to spin the
869 : * spinner for <input type=number>.
870 : */
871 : static void HandleNumberControlSpin(void* aData);
872 :
873 0 : bool NumberSpinnerUpButtonIsDepressed() const
874 : {
875 0 : return mNumberControlSpinnerIsSpinning && mNumberControlSpinnerSpinsUp;
876 : }
877 :
878 0 : bool NumberSpinnerDownButtonIsDepressed() const
879 : {
880 0 : return mNumberControlSpinnerIsSpinning && !mNumberControlSpinnerSpinsUp;
881 : }
882 :
883 : bool MozIsTextField(bool aExcludePassword);
884 :
885 : /**
886 : * GetEditor() is for webidl bindings.
887 : */
888 : nsIEditor* GetEditor();
889 :
890 : void SetUserInput(const nsAString& aInput,
891 : nsIPrincipal& aSubjectPrincipal);
892 :
893 : /**
894 : * If aValue contains a valid floating-point number in the format specified
895 : * by the HTML 5 spec:
896 : *
897 : * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#floating-point-numbers
898 : *
899 : * then this function will return the number parsed as a Decimal, otherwise
900 : * it will return a Decimal for which Decimal::isFinite() will return false.
901 : */
902 : static Decimal StringToDecimal(const nsAString& aValue);
903 :
904 : void UpdateEntries(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories);
905 :
906 : static void Shutdown();
907 :
908 : protected:
909 : virtual ~HTMLInputElement();
910 :
911 : virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
912 :
913 : // Pull IsSingleLineTextControl into our scope, otherwise it'd be hidden
914 : // by the nsITextControlElement version.
915 : using nsGenericHTMLFormElementWithState::IsSingleLineTextControl;
916 :
917 : /**
918 : * The ValueModeType specifies how the value IDL attribute should behave.
919 : *
920 : * See: http://dev.w3.org/html5/spec/forms.html#dom-input-value
921 : */
922 : enum ValueModeType
923 : {
924 : // On getting, returns the value.
925 : // On setting, sets value.
926 : VALUE_MODE_VALUE,
927 : // On getting, returns the value if present or the empty string.
928 : // On setting, sets the value.
929 : VALUE_MODE_DEFAULT,
930 : // On getting, returns the value if present or "on".
931 : // On setting, sets the value.
932 : VALUE_MODE_DEFAULT_ON,
933 : // On getting, returns "C:\fakepath\" followed by the file name of the
934 : // first file of the selected files if any.
935 : // On setting the empty string, empties the selected files list, otherwise
936 : // throw the INVALID_STATE_ERR exception.
937 : VALUE_MODE_FILENAME
938 : };
939 :
940 : /**
941 : * This helper method convert a sub-string that contains only digits to a
942 : * number (unsigned int given that it can't contain a minus sign).
943 : * This method will return whether the sub-string is correctly formatted
944 : * (ie. contains only digit) and it can be successfuly parsed to generate a
945 : * number).
946 : * If the method returns true, |aResult| will contained the parsed number.
947 : *
948 : * @param aValue the string on which the sub-string will be extracted and parsed.
949 : * @param aStart the beginning of the sub-string in aValue.
950 : * @param aLen the length of the sub-string.
951 : * @param aResult the parsed number.
952 : * @return whether the sub-string has been parsed successfully.
953 : */
954 : static bool DigitSubStringToNumber(const nsAString& aValue, uint32_t aStart,
955 : uint32_t aLen, uint32_t* aResult);
956 :
957 : // Helper method
958 :
959 : /**
960 : * Setting the value.
961 : *
962 : * @param aValue String to set.
963 : * @param aOldValue Previous value before setting aValue.
964 : If previous value is unknown, aOldValue can be nullptr.
965 : * @param aFlags See nsTextEditorState::SetValueFlags.
966 : */
967 : nsresult SetValueInternal(const nsAString& aValue,
968 : const nsAString* aOldValue,
969 : uint32_t aFlags);
970 :
971 3 : nsresult SetValueInternal(const nsAString& aValue,
972 : uint32_t aFlags)
973 : {
974 3 : return SetValueInternal(aValue, nullptr, aFlags);
975 : }
976 :
977 : // Generic getter for the value that doesn't do experimental control type
978 : // sanitization.
979 : void GetValueInternal(nsAString& aValue, CallerType aCallerType) const;
980 :
981 : // A getter for callers that know we're not dealing with a file input, so they
982 : // don't have to think about the caller type.
983 : void GetNonFileValueInternal(nsAString& aValue) const;
984 :
985 : /**
986 : * Returns whether the current value is the empty string. This only makes
987 : * sense for some input types; does NOT make sense for file inputs.
988 : *
989 : * @return whether the current value is the empty string.
990 : */
991 : bool IsValueEmpty() const;
992 :
993 : void ClearFiles(bool aSetValueChanged);
994 :
995 : void SetIndeterminateInternal(bool aValue,
996 : bool aShouldInvalidate);
997 :
998 : /**
999 : * Called when an attribute is about to be changed
1000 : */
1001 : virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
1002 : const nsAttrValueOrString* aValue,
1003 : bool aNotify) override;
1004 : /**
1005 : * Called when an attribute has just been changed
1006 : */
1007 : virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
1008 : const nsAttrValue* aValue,
1009 : const nsAttrValue* aOldValue,
1010 : bool aNotify) override;
1011 :
1012 : virtual void BeforeSetForm(bool aBindToTree) override;
1013 :
1014 : virtual void AfterClearForm(bool aUnbindOrDelete) override;
1015 :
1016 : /**
1017 : * Dispatch a select event. Returns true if the event was not cancelled.
1018 : */
1019 : bool DispatchSelectEvent(nsPresContext* aPresContext);
1020 :
1021 : void SelectAll(nsPresContext* aPresContext);
1022 : bool IsImage() const
1023 : {
1024 : return AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
1025 : nsGkAtoms::image, eIgnoreCase);
1026 : }
1027 :
1028 : /**
1029 : * Visit the group of radio buttons this radio belongs to
1030 : * @param aVisitor the visitor to visit with
1031 : */
1032 : nsresult VisitGroup(nsIRadioVisitor* aVisitor, bool aFlushContent);
1033 :
1034 : /**
1035 : * Do all the work that |SetChecked| does (radio button handling, etc.), but
1036 : * take an |aNotify| parameter.
1037 : */
1038 : void DoSetChecked(bool aValue, bool aNotify, bool aSetValueChanged);
1039 :
1040 : /**
1041 : * Do all the work that |SetCheckedChanged| does (radio button handling,
1042 : * etc.), but take an |aNotify| parameter that lets it avoid flushing content
1043 : * when it can.
1044 : */
1045 : void DoSetCheckedChanged(bool aCheckedChanged, bool aNotify);
1046 :
1047 : /**
1048 : * Actually set checked and notify the frame of the change.
1049 : * @param aValue the value of checked to set
1050 : */
1051 : void SetCheckedInternal(bool aValue, bool aNotify);
1052 :
1053 : void RadioSetChecked(bool aNotify);
1054 : void SetCheckedChanged(bool aCheckedChanged);
1055 :
1056 : /**
1057 : * MaybeSubmitForm looks for a submit input or a single text control
1058 : * and submits the form if either is present.
1059 : */
1060 : nsresult MaybeSubmitForm(nsPresContext* aPresContext);
1061 :
1062 : /**
1063 : * Update mFileList with the currently selected file.
1064 : */
1065 : void UpdateFileList();
1066 :
1067 : /**
1068 : * Called after calling one of the SetFilesOrDirectories() functions.
1069 : * This method can explore the directory recursively if needed.
1070 : */
1071 : void AfterSetFilesOrDirectories(bool aSetValueChanged);
1072 :
1073 : /**
1074 : * Recursively explore the directory and populate mFileOrDirectories correctly
1075 : * for webkitdirectory.
1076 : */
1077 : void ExploreDirectoryRecursively(bool aSetValuechanged);
1078 :
1079 : /**
1080 : * Determine whether the editor needs to be initialized explicitly for
1081 : * a particular event.
1082 : */
1083 : bool NeedToInitializeEditorForEvent(EventChainPreVisitor& aVisitor) const;
1084 :
1085 : /**
1086 : * Get the value mode of the element, depending of the type.
1087 : */
1088 : ValueModeType GetValueMode() const;
1089 :
1090 : /**
1091 : * Get the mutable state of the element.
1092 : * When the element isn't mutable (immutable), the value or checkedness
1093 : * should not be changed by the user.
1094 : *
1095 : * See: http://dev.w3.org/html5/spec/forms.html#concept-input-mutable
1096 : */
1097 : bool IsMutable() const;
1098 :
1099 : /**
1100 : * Returns if the readonly attribute applies for the current type.
1101 : */
1102 : bool DoesReadOnlyApply() const;
1103 :
1104 : /**
1105 : * Returns if the required attribute applies for the current type.
1106 : */
1107 : bool DoesRequiredApply() const;
1108 :
1109 : /**
1110 : * Returns if the min and max attributes apply for the current type.
1111 : */
1112 : bool DoesMinMaxApply() const;
1113 :
1114 : /**
1115 : * Returns if the step attribute apply for the current type.
1116 : */
1117 0 : bool DoesStepApply() const { return DoesMinMaxApply(); }
1118 :
1119 : /**
1120 : * Returns if stepDown and stepUp methods apply for the current type.
1121 : */
1122 0 : bool DoStepDownStepUpApply() const { return DoesStepApply(); }
1123 :
1124 : /**
1125 : * Returns if valueAsNumber attribute applies for the current type.
1126 : */
1127 0 : bool DoesValueAsNumberApply() const { return DoesMinMaxApply(); }
1128 :
1129 : /**
1130 : * Returns if autocomplete attribute applies for the current type.
1131 : */
1132 : bool DoesAutocompleteApply() const;
1133 :
1134 : void FreeData();
1135 : nsTextEditorState *GetEditorState() const;
1136 :
1137 : mozilla::TextEditor* GetTextEditorFromState();
1138 :
1139 : /**
1140 : * Manages the internal data storage across type changes.
1141 : */
1142 : void HandleTypeChange(uint8_t aNewType, bool aNotify);
1143 :
1144 : /**
1145 : * Sanitize the value of the element depending of its current type.
1146 : * See: http://www.whatwg.org/specs/web-apps/current-work/#value-sanitization-algorithm
1147 : */
1148 : void SanitizeValue(nsAString& aValue);
1149 :
1150 : /**
1151 : * Returns whether the placeholder attribute applies for the current type.
1152 : */
1153 : bool PlaceholderApplies() const;
1154 :
1155 : /**
1156 : * Set the current default value to the value of the input element.
1157 : * @note You should not call this method if GetValueMode() doesn't return
1158 : * VALUE_MODE_VALUE.
1159 : */
1160 : nsresult SetDefaultValueAsValue();
1161 :
1162 : void SetDirectionFromValue(bool aNotify);
1163 :
1164 : /**
1165 : * Return if an element should have a specific validity UI
1166 : * (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).
1167 : *
1168 : * @return Whether the element should have a validity UI.
1169 : */
1170 60 : bool ShouldShowValidityUI() const {
1171 : /**
1172 : * Always show the validity UI if the form has already tried to be submitted
1173 : * but was invalid.
1174 : *
1175 : * Otherwise, show the validity UI if the element's value has been changed.
1176 : */
1177 60 : if (mForm && mForm->HasEverTriedInvalidSubmit()) {
1178 0 : return true;
1179 : }
1180 :
1181 60 : switch (GetValueMode()) {
1182 : case VALUE_MODE_DEFAULT:
1183 0 : return true;
1184 : case VALUE_MODE_DEFAULT_ON:
1185 0 : return GetCheckedChanged();
1186 : case VALUE_MODE_VALUE:
1187 : case VALUE_MODE_FILENAME:
1188 60 : return mValueChanged;
1189 : default:
1190 0 : NS_NOTREACHED("We should not be there: there are no other modes.");
1191 0 : return false;
1192 : }
1193 : }
1194 :
1195 : /**
1196 : * Returns the radio group container if the element has one, null otherwise.
1197 : * The radio group container will be the form owner if there is one.
1198 : * The current document otherwise.
1199 : * @return the radio group container if the element has one, null otherwise.
1200 : */
1201 : nsIRadioGroupContainer* GetRadioGroupContainer() const;
1202 :
1203 : /**
1204 : * Parse a color string of the form #XXXXXX where X should be hexa characters
1205 : * @param the string to be parsed.
1206 : * @return whether the string is a valid simple color.
1207 : * Note : this function does not consider the empty string as valid.
1208 : */
1209 : bool IsValidSimpleColor(const nsAString& aValue) const;
1210 :
1211 : /**
1212 : * Parse a week string of the form yyyy-Www
1213 : * @param the string to be parsed.
1214 : * @return whether the string is a valid week.
1215 : * Note : this function does not consider the empty string as valid.
1216 : */
1217 : bool IsValidWeek(const nsAString& aValue) const;
1218 :
1219 : /**
1220 : * Parse a month string of the form yyyy-mm
1221 : * @param the string to be parsed.
1222 : * @return whether the string is a valid month.
1223 : * Note : this function does not consider the empty string as valid.
1224 : */
1225 : bool IsValidMonth(const nsAString& aValue) const;
1226 :
1227 : /**
1228 : * Parse a date string of the form yyyy-mm-dd
1229 : * @param the string to be parsed.
1230 : * @return whether the string is a valid date.
1231 : * Note : this function does not consider the empty string as valid.
1232 : */
1233 : bool IsValidDate(const nsAString& aValue) const;
1234 :
1235 : /**
1236 : * Parse a datetime-local string of the form yyyy-mm-ddThh:mm[:ss.s] or
1237 : * yyyy-mm-dd hh:mm[:ss.s], where fractions of seconds can be 1 to 3 digits.
1238 : *
1239 : * @param the string to be parsed.
1240 : * @return whether the string is a valid datetime-local string.
1241 : * Note : this function does not consider the empty string as valid.
1242 : */
1243 : bool IsValidDateTimeLocal(const nsAString& aValue) const;
1244 :
1245 : /**
1246 : * Parse a year string of the form yyyy
1247 : *
1248 : * @param the string to be parsed.
1249 : *
1250 : * @return the year in aYear.
1251 : * @return whether the parsing was successful.
1252 : */
1253 : bool ParseYear(const nsAString& aValue, uint32_t* aYear) const;
1254 :
1255 : /**
1256 : * Parse a month string of the form yyyy-mm
1257 : *
1258 : * @param the string to be parsed.
1259 : * @return the year and month in aYear and aMonth.
1260 : * @return whether the parsing was successful.
1261 : */
1262 : bool ParseMonth(const nsAString& aValue,
1263 : uint32_t* aYear,
1264 : uint32_t* aMonth) const;
1265 :
1266 : /**
1267 : * Parse a week string of the form yyyy-Www
1268 : *
1269 : * @param the string to be parsed.
1270 : * @return the year and week in aYear and aWeek.
1271 : * @return whether the parsing was successful.
1272 : */
1273 : bool ParseWeek(const nsAString& aValue,
1274 : uint32_t* aYear,
1275 : uint32_t* aWeek) const;
1276 : /**
1277 : * Parse a date string of the form yyyy-mm-dd
1278 : *
1279 : * @param the string to be parsed.
1280 : * @return the date in aYear, aMonth, aDay.
1281 : * @return whether the parsing was successful.
1282 : */
1283 : bool ParseDate(const nsAString& aValue,
1284 : uint32_t* aYear,
1285 : uint32_t* aMonth,
1286 : uint32_t* aDay) const;
1287 :
1288 : /**
1289 : * Parse a datetime-local string of the form yyyy-mm-ddThh:mm[:ss.s] or
1290 : * yyyy-mm-dd hh:mm[:ss.s], where fractions of seconds can be 1 to 3 digits.
1291 : *
1292 : * @param the string to be parsed.
1293 : * @return the date in aYear, aMonth, aDay and time expressed in milliseconds
1294 : * in aTime.
1295 : * @return whether the parsing was successful.
1296 : */
1297 : bool ParseDateTimeLocal(const nsAString& aValue,
1298 : uint32_t* aYear,
1299 : uint32_t* aMonth,
1300 : uint32_t* aDay,
1301 : uint32_t* aTime) const;
1302 :
1303 : /**
1304 : * Normalize the datetime-local string following the HTML specifications:
1305 : * https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string
1306 : */
1307 : void NormalizeDateTimeLocal(nsAString& aValue) const;
1308 :
1309 : /**
1310 : * This methods returns the number of days since epoch for a given year and
1311 : * week.
1312 : */
1313 : double DaysSinceEpochFromWeek(uint32_t aYear, uint32_t aWeek) const;
1314 :
1315 : /**
1316 : * This methods returns the number of days in a given month, for a given year.
1317 : */
1318 : uint32_t NumberOfDaysInMonth(uint32_t aMonth, uint32_t aYear) const;
1319 :
1320 : /**
1321 : * This methods returns the number of months between January 1970 and the
1322 : * given year and month.
1323 : */
1324 : int32_t MonthsSinceJan1970(uint32_t aYear, uint32_t aMonth) const;
1325 :
1326 : /**
1327 : * This methods returns the day of the week given a date. If @isoWeek is true,
1328 : * 7=Sunday, otherwise, 0=Sunday.
1329 : */
1330 : uint32_t DayOfWeek(uint32_t aYear, uint32_t aMonth, uint32_t aDay,
1331 : bool isoWeek) const;
1332 :
1333 : /**
1334 : * This methods returns the maximum number of week in a given year, the
1335 : * result is either 52 or 53.
1336 : */
1337 : uint32_t MaximumWeekInYear(uint32_t aYear) const;
1338 :
1339 : /**
1340 : * This methods returns true if it's a leap year.
1341 : */
1342 : bool IsLeapYear(uint32_t aYear) const;
1343 :
1344 : /**
1345 : * Returns whether aValue is a valid time as described by HTML specifications:
1346 : * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string
1347 : *
1348 : * @param aValue the string to be tested.
1349 : * @return Whether the string is a valid time per HTML specifications.
1350 : */
1351 : bool IsValidTime(const nsAString& aValue) const;
1352 :
1353 : /**
1354 : * Returns the time expressed in milliseconds of |aValue| being parsed as a
1355 : * time following the HTML specifications:
1356 : * http://www.whatwg.org/specs/web-apps/current-work/#parse-a-time-string
1357 : *
1358 : * Note: |aResult| can be null.
1359 : *
1360 : * @param aValue the string to be parsed.
1361 : * @param aResult the time expressed in milliseconds representing the time [out]
1362 : * @return Whether the parsing was successful.
1363 : */
1364 : static bool ParseTime(const nsAString& aValue, uint32_t* aResult);
1365 :
1366 : /**
1367 : * Sets the value of the element to the string representation of the Decimal.
1368 : *
1369 : * @param aValue The Decimal that will be used to set the value.
1370 : */
1371 : void SetValue(Decimal aValue, CallerType aCallerType);
1372 :
1373 : /**
1374 : * Update the HAS_RANGE bit field value.
1375 : */
1376 : void UpdateHasRange();
1377 :
1378 : /**
1379 : * Get the step scale value for the current type.
1380 : * See:
1381 : * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#concept-input-step-scale
1382 : */
1383 : Decimal GetStepScaleFactor() const;
1384 :
1385 : /**
1386 : * Return the base used to compute if a value matches step.
1387 : * Basically, it's the min attribute if present and a default value otherwise.
1388 : *
1389 : * @return The step base.
1390 : */
1391 : Decimal GetStepBase() const;
1392 :
1393 : /**
1394 : * Returns the default step for the current type.
1395 : * @return the default step for the current type.
1396 : */
1397 : Decimal GetDefaultStep() const;
1398 :
1399 : enum StepCallerType {
1400 : CALLED_FOR_USER_EVENT,
1401 : CALLED_FOR_SCRIPT
1402 : };
1403 :
1404 : /**
1405 : * Sets the aValue outparam to the value that this input would take if
1406 : * someone tries to step aStep steps and this input's value would change as
1407 : * a result. Leaves aValue untouched if this inputs value would not change
1408 : * (e.g. already at max, and asking for the next step up).
1409 : *
1410 : * Negative aStep means step down, positive means step up.
1411 : *
1412 : * Returns NS_OK or else the error values that should be thrown if this call
1413 : * was initiated by a stepUp()/stepDown() call from script under conditions
1414 : * that such a call should throw.
1415 : */
1416 : nsresult GetValueIfStepped(int32_t aStepCount,
1417 : StepCallerType aCallerType,
1418 : Decimal* aNextStep);
1419 :
1420 : /**
1421 : * Apply a step change from stepUp or stepDown by multiplying aStep by the
1422 : * current step value.
1423 : *
1424 : * @param aStep The value used to be multiplied against the step value.
1425 : */
1426 : nsresult ApplyStep(int32_t aStep);
1427 :
1428 : /**
1429 : * Returns if the current type is an experimental mobile type.
1430 : */
1431 : static bool IsExperimentalMobileType(uint8_t aType);
1432 :
1433 : /*
1434 : * Returns if the current type is one of the date/time input types: date,
1435 : * time and month. TODO: week and datetime-local.
1436 : */
1437 : static bool IsDateTimeInputType(uint8_t aType);
1438 :
1439 : /**
1440 : * Flushes the layout frame tree to make sure we have up-to-date frames.
1441 : */
1442 : void FlushFrames();
1443 :
1444 : /**
1445 : * Returns true if the element should prevent dispatching another DOMActivate.
1446 : * This is used in situations where the anonymous subtree should already have
1447 : * sent a DOMActivate and prevents firing more than once.
1448 : */
1449 : bool ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget);
1450 :
1451 : /**
1452 : * Some input type (color and file) let user choose a value using a picker:
1453 : * this function checks if it is needed, and if so, open the corresponding
1454 : * picker (color picker or file picker).
1455 : */
1456 : nsresult MaybeInitPickers(EventChainPostVisitor& aVisitor);
1457 :
1458 : enum FilePickerType {
1459 : FILE_PICKER_FILE,
1460 : FILE_PICKER_DIRECTORY
1461 : };
1462 : nsresult InitFilePicker(FilePickerType aType);
1463 : nsresult InitColorPicker();
1464 :
1465 : /**
1466 : * Use this function before trying to open a picker.
1467 : * It checks if the page is allowed to open a new pop-up.
1468 : * If it returns true, you should not create the picker.
1469 : *
1470 : * @return true if popup should be blocked, false otherwise
1471 : */
1472 : bool IsPopupBlocked() const;
1473 :
1474 : GetFilesHelper* GetOrCreateGetFilesHelper(bool aRecursiveFlag,
1475 : ErrorResult& aRv);
1476 :
1477 : void ClearGetFilesHelpers();
1478 :
1479 : /**
1480 : * nsINode::SetMayBeApzAware() will be invoked in this function if necessary
1481 : * to prevent default action of APZC so that we can increase/decrease the
1482 : * value of this InputElement when mouse wheel event comes without scrolling
1483 : * the page.
1484 : *
1485 : * SetMayBeApzAware() will set flag MayBeApzAware which is checked by apzc to
1486 : * decide whether to add this element into its dispatch-to-content region.
1487 : */
1488 : void UpdateApzAwareFlag();
1489 :
1490 : /**
1491 : * A helper to get the current selection range. Will throw on the ErrorResult
1492 : * if we have no editor state.
1493 : */
1494 : void GetSelectionRange(uint32_t* aSelectionStart,
1495 : uint32_t* aSelectionEnd,
1496 : ErrorResult& aRv);
1497 :
1498 : /**
1499 : * Override for nsImageLoadingContent.
1500 : */
1501 2 : nsIContent* AsContent() override { return this; }
1502 :
1503 : nsCOMPtr<nsIControllers> mControllers;
1504 :
1505 : /*
1506 : * In mInputData, the mState field is used if IsSingleLineTextControl returns
1507 : * true and mValue is used otherwise. We have to be careful when handling it
1508 : * on a type change.
1509 : *
1510 : * Accessing the mState member should be done using the GetEditorState function,
1511 : * which returns null if the state is not present.
1512 : */
1513 : union InputData {
1514 : /**
1515 : * The current value of the input if it has been changed from the default
1516 : */
1517 : char16_t* mValue;
1518 : /**
1519 : * The state of the text editor associated with the text/password input
1520 : */
1521 : nsTextEditorState* mState;
1522 : } mInputData;
1523 :
1524 : struct FileData;
1525 : UniquePtr<FileData> mFileData;
1526 :
1527 : /**
1528 : * The value of the input element when first initialized and it is updated
1529 : * when the element is either changed through a script, focused or dispatches
1530 : * a change event. This is to ensure correct future change event firing.
1531 : * NB: This is ONLY applicable where the element is a text control. ie,
1532 : * where type= "text", "email", "search", "tel", "url" or "password".
1533 : */
1534 : nsString mFocusedValue;
1535 :
1536 : /**
1537 : * If mIsDraggingRange is true, this is the value that the input had before
1538 : * the drag started. Used to reset the input to its old value if the drag is
1539 : * canceled.
1540 : */
1541 : Decimal mRangeThumbDragStartValue;
1542 :
1543 : /**
1544 : * Current value in the input box, in DateTimeValue dictionary format, see
1545 : * HTMLInputElement.webidl for details.
1546 : */
1547 : nsAutoPtr<DateTimeValue> mDateTimeInputBoxValue;
1548 :
1549 : /**
1550 : * The selection properties cache for number controls. This is needed because
1551 : * the number controls don't recycle their text field, so the normal cache in
1552 : * nsTextEditorState cannot do its job.
1553 : */
1554 : nsTextEditorState::SelectionProperties mSelectionProperties;
1555 :
1556 : /*
1557 : * InputType object created based on input type.
1558 : */
1559 : UniquePtr<InputType, DoNotDelete> mInputType;
1560 :
1561 : // Memory allocated for mInputType, reused when type changes.
1562 : char mInputTypeMem[INPUT_TYPE_SIZE];
1563 :
1564 : // Step scale factor values, for input types that have one.
1565 : static const Decimal kStepScaleFactorDate;
1566 : static const Decimal kStepScaleFactorNumberRange;
1567 : static const Decimal kStepScaleFactorTime;
1568 : static const Decimal kStepScaleFactorMonth;
1569 : static const Decimal kStepScaleFactorWeek;
1570 :
1571 : // Default step base value when a type do not have specific one.
1572 : static const Decimal kDefaultStepBase;
1573 : // Default step base value when type=week does not not have a specific one,
1574 : // which is −259200000, the start of week 1970-W01.
1575 : static const Decimal kDefaultStepBaseWeek;
1576 :
1577 : // Default step used when there is no specified step.
1578 : static const Decimal kDefaultStep;
1579 : static const Decimal kDefaultStepTime;
1580 :
1581 : // Float value returned by GetStep() when the step attribute is set to 'any'.
1582 : static const Decimal kStepAny;
1583 :
1584 : // Minimum year limited by HTML standard, year >= 1.
1585 : static const double kMinimumYear;
1586 : // Maximum year limited by ECMAScript date object range, year <= 275760.
1587 : static const double kMaximumYear;
1588 : // Maximum valid week is 275760-W37.
1589 : static const double kMaximumWeekInMaximumYear;
1590 : // Maximum valid day is 275760-09-13.
1591 : static const double kMaximumDayInMaximumYear;
1592 : // Maximum valid month is 275760-09.
1593 : static const double kMaximumMonthInMaximumYear;
1594 : // Long years in a ISO calendar have 53 weeks in them.
1595 : static const double kMaximumWeekInYear;
1596 : // Milliseconds in a day.
1597 : static const double kMsPerDay;
1598 :
1599 : nsContentUtils::AutocompleteAttrState mAutocompleteAttrState;
1600 : nsContentUtils::AutocompleteAttrState mAutocompleteInfoState;
1601 : bool mDisabledChanged : 1;
1602 : bool mValueChanged : 1;
1603 : bool mLastValueChangeWasInteractive : 1;
1604 : bool mCheckedChanged : 1;
1605 : bool mChecked : 1;
1606 : bool mHandlingSelectEvent : 1;
1607 : bool mShouldInitChecked : 1;
1608 : bool mDoneCreating : 1;
1609 : bool mInInternalActivate : 1;
1610 : bool mCheckedIsToggled : 1;
1611 : bool mIndeterminate : 1;
1612 : bool mInhibitRestoration : 1;
1613 : bool mCanShowValidUI : 1;
1614 : bool mCanShowInvalidUI : 1;
1615 : bool mHasRange : 1;
1616 : bool mIsDraggingRange : 1;
1617 : bool mNumberControlSpinnerIsSpinning : 1;
1618 : bool mNumberControlSpinnerSpinsUp : 1;
1619 : bool mPickerRunning : 1;
1620 : bool mSelectionCached : 1;
1621 : bool mIsPreviewEnabled : 1;
1622 :
1623 : private:
1624 : static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
1625 : GenericSpecifiedValues* aGenericData);
1626 :
1627 : /**
1628 : * Returns true if this input's type will fire a DOM "change" event when it
1629 : * loses focus if its value has changed since it gained focus.
1630 : */
1631 1 : bool MayFireChangeOnBlur() const {
1632 1 : return MayFireChangeOnBlur(mType);
1633 : }
1634 :
1635 : /**
1636 : * Returns true if selection methods can be called on element
1637 : */
1638 2 : bool SupportsTextSelection() const {
1639 2 : return mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_SEARCH ||
1640 2 : mType == NS_FORM_INPUT_URL || mType == NS_FORM_INPUT_TEL ||
1641 2 : mType == NS_FORM_INPUT_PASSWORD;
1642 : }
1643 :
1644 3 : static bool MayFireChangeOnBlur(uint8_t aType) {
1645 3 : return IsSingleLineTextControl(false, aType) ||
1646 0 : aType == NS_FORM_INPUT_RANGE ||
1647 0 : aType == NS_FORM_INPUT_NUMBER ||
1648 3 : aType == NS_FORM_INPUT_TIME ||
1649 3 : aType == NS_FORM_INPUT_DATE;
1650 : }
1651 :
1652 : /**
1653 : * Checks if aDateTimeInputType should be supported based on "dom.forms.datetime",
1654 : * and "dom.experimental_forms".
1655 : */
1656 : static bool
1657 : IsDateTimeTypeSupported(uint8_t aDateTimeInputType);
1658 :
1659 : /**
1660 : * Checks preference "dom.webkitBlink.dirPicker.enabled" to determine if
1661 : * webkitdirectory should be supported.
1662 : */
1663 : static bool
1664 : IsWebkitDirPickerEnabled();
1665 :
1666 : /**
1667 : * Checks preference "dom.webkitBlink.filesystem.enabled" to determine if
1668 : * webkitEntries should be supported.
1669 : */
1670 : static bool
1671 : IsWebkitFileSystemEnabled();
1672 :
1673 : /**
1674 : * Checks preference "dom.input.dirpicker" to determine if file and directory
1675 : * entries API should be supported.
1676 : */
1677 : static bool
1678 : IsDirPickerEnabled();
1679 :
1680 : /**
1681 : * Checks preference "dom.experimental_forms" to determine if experimental
1682 : * implementation of input element should be enabled.
1683 : */
1684 : static bool
1685 : IsExperimentalFormsEnabled();
1686 :
1687 : /**
1688 : * Checks preference "dom.forms.datetime" to determine if input date and time
1689 : * should be supported.
1690 : */
1691 : static bool
1692 : IsInputDateTimeEnabled();
1693 :
1694 : /**
1695 : * Checks preference "dom.forms.datetime.others" to determine if input week,
1696 : * month and datetime-local should be supported.
1697 : */
1698 : static bool
1699 : IsInputDateTimeOthersEnabled();
1700 :
1701 : /**
1702 : * Checks preference "dom.forms.number" to determine if input type=number
1703 : * should be supported.
1704 : */
1705 : static bool
1706 : IsInputNumberEnabled();
1707 :
1708 : /**
1709 : * Checks preference "dom.forms.color" to determine if date/time related
1710 : * types should be supported.
1711 : */
1712 : static bool
1713 : IsInputColorEnabled();
1714 :
1715 0 : struct nsFilePickerFilter {
1716 0 : nsFilePickerFilter()
1717 0 : : mFilterMask(0) {}
1718 :
1719 0 : explicit nsFilePickerFilter(int32_t aFilterMask)
1720 0 : : mFilterMask(aFilterMask) {}
1721 :
1722 0 : nsFilePickerFilter(const nsString& aTitle,
1723 : const nsString& aFilter)
1724 0 : : mFilterMask(0), mTitle(aTitle), mFilter(aFilter) {}
1725 :
1726 0 : nsFilePickerFilter(const nsFilePickerFilter& other) {
1727 0 : mFilterMask = other.mFilterMask;
1728 0 : mTitle = other.mTitle;
1729 0 : mFilter = other.mFilter;
1730 0 : }
1731 :
1732 0 : bool operator== (const nsFilePickerFilter& other) const {
1733 0 : if ((mFilter == other.mFilter) && (mFilterMask == other.mFilterMask)) {
1734 0 : return true;
1735 : } else {
1736 0 : return false;
1737 : }
1738 : }
1739 :
1740 : // Filter mask, using values defined in nsIFilePicker
1741 : int32_t mFilterMask;
1742 : // If mFilterMask is defined, mTitle and mFilter are useless and should be
1743 : // ignored
1744 : nsString mTitle;
1745 : nsString mFilter;
1746 : };
1747 :
1748 : class nsFilePickerShownCallback
1749 : : public nsIFilePickerShownCallback
1750 : {
1751 0 : virtual ~nsFilePickerShownCallback()
1752 0 : { }
1753 :
1754 : public:
1755 : nsFilePickerShownCallback(HTMLInputElement* aInput,
1756 : nsIFilePicker* aFilePicker);
1757 : NS_DECL_ISUPPORTS
1758 :
1759 : NS_IMETHOD Done(int16_t aResult) override;
1760 :
1761 : private:
1762 : nsCOMPtr<nsIFilePicker> mFilePicker;
1763 : RefPtr<HTMLInputElement> mInput;
1764 : };
1765 :
1766 : static void ReleaseTextEditorState(nsTextEditorState* aState);
1767 :
1768 : static nsTextEditorState* sCachedTextEditorState;
1769 : static bool sShutdown;
1770 : };
1771 :
1772 : } // namespace dom
1773 : } // namespace mozilla
1774 :
1775 : #endif
|