Add more auto fill button types
[WebKit-https.git] / Source / WebCore / html / HTMLInputElement.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
6  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
8  * Copyright (C) 2010 Google Inc. All rights reserved.
9  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
10  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  *
27  */
28
29 #include "config.h"
30 #include "HTMLInputElement.h"
31
32 #include "AXObjectCache.h"
33 #include "BeforeTextInsertedEvent.h"
34 #include "CSSGradientValue.h"
35 #include "CSSPropertyNames.h"
36 #include "CSSValuePool.h"
37 #include "DateTimeChooser.h"
38 #include "Document.h"
39 #include "Editor.h"
40 #include "EventNames.h"
41 #include "FileInputType.h"
42 #include "FileList.h"
43 #include "FormController.h"
44 #include "Frame.h"
45 #include "FrameSelection.h"
46 #include "FrameView.h"
47 #include "HTMLDataListElement.h"
48 #include "HTMLFormElement.h"
49 #include "HTMLImageLoader.h"
50 #include "HTMLOptionElement.h"
51 #include "HTMLParserIdioms.h"
52 #include "IdTargetObserver.h"
53 #include "KeyboardEvent.h"
54 #include "LocalizedStrings.h"
55 #include "MouseEvent.h"
56 #include "PlatformMouseEvent.h"
57 #include "RenderTextControlSingleLine.h"
58 #include "RenderTheme.h"
59 #include "ScopedEventQueue.h"
60 #include "SearchInputType.h"
61 #include "Settings.h"
62 #include "StyleResolver.h"
63 #include "StyleTreeResolver.h"
64 #include "TextControlInnerElements.h"
65 #include <wtf/Language.h>
66 #include <wtf/MathExtras.h>
67 #include <wtf/Ref.h>
68
69 #if ENABLE(TOUCH_EVENTS)
70 #include "TouchEvent.h"
71 #endif
72
73 #if ENABLE(ALTERNATIVE_PRESENTATION_BUTTON_ELEMENT)
74 #include "AlternativePresentationButtonInputType.h"
75 #include "InputTypeNames.h"
76 #endif
77
78 namespace WebCore {
79
80 using namespace HTMLNames;
81
82 #if ENABLE(DATALIST_ELEMENT)
83 class ListAttributeTargetObserver : IdTargetObserver {
84     WTF_MAKE_FAST_ALLOCATED;
85 public:
86     ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement*);
87
88     void idTargetChanged() override;
89
90 private:
91     HTMLInputElement* m_element;
92 };
93 #endif
94
95 // FIXME: According to HTML4, the length attribute's value can be arbitrarily
96 // large. However, due to https://bugs.webkit.org/show_bug.cgi?id=14536 things
97 // get rather sluggish when a text field has a larger number of characters than
98 // this, even when just clicking in the text field.
99 const unsigned HTMLInputElement::maxEffectiveLength = 524288;
100 const int defaultSize = 20;
101 const int maxSavedResults = 256;
102
103 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser)
104     : HTMLTextFormControlElement(tagName, document, form)
105     , m_size(defaultSize)
106     , m_maxResults(-1)
107     , m_isChecked(false)
108     , m_reflectsCheckedAttribute(true)
109     , m_isIndeterminate(false)
110     , m_hasType(false)
111     , m_isActivatedSubmit(false)
112     , m_autocomplete(Uninitialized)
113     , m_isAutoFilled(false)
114     , m_autoFillButtonType(static_cast<uint8_t>(AutoFillButtonType::None))
115     , m_isAutoFillAvailable(false)
116 #if ENABLE(DATALIST_ELEMENT)
117     , m_hasNonEmptyList(false)
118 #endif
119     , m_stateRestored(false)
120     , m_parsingInProgress(createdByParser)
121     , m_valueAttributeWasUpdatedAfterParsing(false)
122     , m_wasModifiedByUser(false)
123     , m_canReceiveDroppedFiles(false)
124 #if ENABLE(TOUCH_EVENTS)
125     , m_hasTouchEventHandler(false)
126 #endif
127     , m_isSpellcheckDisabledExceptTextReplacement(false)
128     // m_inputType is lazily created when constructed by the parser to avoid constructing unnecessarily a text inputType and
129     // its shadow subtree, just to destroy them when the |type| attribute gets set by the parser to something else than 'text'.
130     , m_inputType(createdByParser ? nullptr : InputType::createText(*this))
131 {
132     ASSERT(hasTagName(inputTag));
133     setHasCustomStyleResolveCallbacks();
134 }
135
136 Ref<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser)
137 {
138     bool shouldCreateShadowRootLazily = createdByParser;
139     Ref<HTMLInputElement> inputElement = adoptRef(*new HTMLInputElement(tagName, document, form, createdByParser));
140     if (!shouldCreateShadowRootLazily)
141         inputElement->ensureUserAgentShadowRoot();
142     return inputElement;
143 }
144
145 HTMLImageLoader& HTMLInputElement::ensureImageLoader()
146 {
147     if (!m_imageLoader)
148         m_imageLoader = std::make_unique<HTMLImageLoader>(*this);
149     return *m_imageLoader;
150 }
151
152 void HTMLInputElement::didAddUserAgentShadowRoot(ShadowRoot&)
153 {
154     m_inputType->createShadowSubtree();
155     updateInnerTextElementEditability();
156 }
157
158 HTMLInputElement::~HTMLInputElement()
159 {
160     if (needsSuspensionCallback())
161         document().unregisterForDocumentSuspensionCallbacks(this);
162
163     // Need to remove form association while this is still an HTMLInputElement
164     // so that virtual functions are called correctly.
165     setForm(0);
166     // setForm(0) may register this to a document-level radio button group.
167     // We should unregister it to avoid accessing a deleted object.
168     if (isRadioButton())
169         document().formController().radioButtonGroups().removeButton(this);
170 #if ENABLE(TOUCH_EVENTS)
171     if (m_hasTouchEventHandler)
172         document().didRemoveEventTargetNode(*this);
173 #endif
174 }
175
176 const AtomicString& HTMLInputElement::name() const
177 {
178     return m_name.isNull() ? emptyAtom() : m_name;
179 }
180
181 Vector<FileChooserFileInfo> HTMLInputElement::filesFromFileInputFormControlState(const FormControlState& state)
182 {
183     return FileInputType::filesFromFormControlState(state);
184 }
185
186 HTMLElement* HTMLInputElement::containerElement() const
187 {
188     return m_inputType->containerElement();
189 }
190
191 RefPtr<TextControlInnerTextElement> HTMLInputElement::innerTextElement() const
192 {
193     return m_inputType->innerTextElement();
194 }
195
196 HTMLElement* HTMLInputElement::innerBlockElement() const
197 {
198     return m_inputType->innerBlockElement();
199 }
200
201 HTMLElement* HTMLInputElement::innerSpinButtonElement() const
202 {
203     return m_inputType->innerSpinButtonElement();
204 }
205
206 HTMLElement* HTMLInputElement::capsLockIndicatorElement() const
207 {
208     return m_inputType->capsLockIndicatorElement();
209 }
210
211 HTMLElement* HTMLInputElement::autoFillButtonElement() const
212 {
213     return m_inputType->autoFillButtonElement();
214 }
215
216 HTMLElement* HTMLInputElement::resultsButtonElement() const
217 {
218     return m_inputType->resultsButtonElement();
219 }
220
221 HTMLElement* HTMLInputElement::cancelButtonElement() const
222 {
223     return m_inputType->cancelButtonElement();
224 }
225
226 HTMLElement* HTMLInputElement::sliderThumbElement() const
227 {
228     return m_inputType->sliderThumbElement();
229 }
230
231 HTMLElement* HTMLInputElement::sliderTrackElement() const
232 {
233     return m_inputType->sliderTrackElement();
234 }
235
236 HTMLElement* HTMLInputElement::placeholderElement() const
237 {
238     return m_inputType->placeholderElement();
239 }
240
241 #if ENABLE(ALTERNATIVE_PRESENTATION_BUTTON_ELEMENT)
242 HTMLElement* HTMLInputElement::alternativePresentationButtonElement() const
243 {
244     return m_inputType->alternativePresentationButtonElement();
245 }
246 #endif
247
248 bool HTMLInputElement::shouldAutocomplete() const
249 {
250     if (m_autocomplete != Uninitialized)
251         return m_autocomplete == On;
252     return HTMLTextFormControlElement::shouldAutocomplete();
253 }
254
255 bool HTMLInputElement::isValidValue(const String& value) const
256 {
257     if (!m_inputType->canSetStringValue()) {
258         ASSERT_NOT_REACHED();
259         return false;
260     }
261     return !m_inputType->typeMismatchFor(value)
262         && !m_inputType->stepMismatch(value)
263         && !m_inputType->rangeUnderflow(value)
264         && !m_inputType->rangeOverflow(value)
265         && !tooShort(value, IgnoreDirtyFlag)
266         && !tooLong(value, IgnoreDirtyFlag)
267         && !m_inputType->patternMismatch(value)
268         && !m_inputType->valueMissing(value);
269 }
270
271 bool HTMLInputElement::tooShort() const
272 {
273     return willValidate() && tooShort(value(), CheckDirtyFlag);
274 }
275
276 bool HTMLInputElement::tooLong() const
277 {
278     return willValidate() && tooLong(value(), CheckDirtyFlag);
279 }
280
281 bool HTMLInputElement::typeMismatch() const
282 {
283     return willValidate() && m_inputType->typeMismatch();
284 }
285
286 bool HTMLInputElement::valueMissing() const
287 {
288     return willValidate() && m_inputType->valueMissing(value());
289 }
290
291 bool HTMLInputElement::hasBadInput() const
292 {
293     return willValidate() && m_inputType->hasBadInput();
294 }
295
296 bool HTMLInputElement::patternMismatch() const
297 {
298     return willValidate() && m_inputType->patternMismatch(value());
299 }
300
301 bool HTMLInputElement::tooShort(StringView value, NeedsToCheckDirtyFlag check) const
302 {
303     if (!supportsMinLength())
304         return false;
305
306     int min = minLength();
307     if (min <= 0)
308         return false;
309
310     if (check == CheckDirtyFlag) {
311         // Return false for the default value or a value set by a script even if
312         // it is shorter than minLength.
313         if (!hasDirtyValue() || !m_wasModifiedByUser)
314             return false;
315     }
316
317     // The empty string is excluded from tooShort validation.
318     if (value.isEmpty())
319         return false;
320
321     // FIXME: The HTML specification says that the "number of characters" is measured using code-unit length.
322     return numGraphemeClusters(value) < static_cast<unsigned>(min);
323 }
324
325 bool HTMLInputElement::tooLong(StringView value, NeedsToCheckDirtyFlag check) const
326 {
327     if (!supportsMaxLength())
328         return false;
329     unsigned max = effectiveMaxLength();
330     if (check == CheckDirtyFlag) {
331         // Return false for the default value or a value set by a script even if
332         // it is longer than maxLength.
333         if (!hasDirtyValue() || !m_wasModifiedByUser)
334             return false;
335     }
336     // FIXME: The HTML specification says that the "number of characters" is measured using code-unit length.
337     return numGraphemeClusters(value) > max;
338 }
339
340 bool HTMLInputElement::rangeUnderflow() const
341 {
342     return willValidate() && m_inputType->rangeUnderflow(value());
343 }
344
345 bool HTMLInputElement::rangeOverflow() const
346 {
347     return willValidate() && m_inputType->rangeOverflow(value());
348 }
349
350 String HTMLInputElement::validationMessage() const
351 {
352     if (!willValidate())
353         return String();
354
355     if (customError())
356         return customValidationMessage();
357
358     return m_inputType->validationMessage();
359 }
360
361 double HTMLInputElement::minimum() const
362 {
363     return m_inputType->minimum();
364 }
365
366 double HTMLInputElement::maximum() const
367 {
368     return m_inputType->maximum();
369 }
370
371 bool HTMLInputElement::stepMismatch() const
372 {
373     return willValidate() && m_inputType->stepMismatch(value());
374 }
375
376 bool HTMLInputElement::isValid() const
377 {
378     if (!willValidate())
379         return true;
380
381     String value = this->value();
382     bool someError = m_inputType->typeMismatch() || m_inputType->stepMismatch(value) || m_inputType->rangeUnderflow(value) || m_inputType->rangeOverflow(value)
383         || tooShort(value, CheckDirtyFlag) || tooLong(value, CheckDirtyFlag) || m_inputType->patternMismatch(value) || m_inputType->valueMissing(value)
384         || m_inputType->hasBadInput() || customError();
385     return !someError;
386 }
387
388 bool HTMLInputElement::getAllowedValueStep(Decimal* step) const
389 {
390     return m_inputType->getAllowedValueStep(step);
391 }
392
393 StepRange HTMLInputElement::createStepRange(AnyStepHandling anyStepHandling) const
394 {
395     return m_inputType->createStepRange(anyStepHandling);
396 }
397
398 #if ENABLE(DATALIST_ELEMENT)
399 std::optional<Decimal> HTMLInputElement::findClosestTickMarkValue(const Decimal& value)
400 {
401     return m_inputType->findClosestTickMarkValue(value);
402 }
403 #endif
404
405 ExceptionOr<void> HTMLInputElement::stepUp(int n)
406 {
407     return m_inputType->stepUp(n);
408 }
409
410 ExceptionOr<void> HTMLInputElement::stepDown(int n)
411 {
412     return m_inputType->stepUp(-n);
413 }
414
415 void HTMLInputElement::blur()
416 {
417     m_inputType->blur();
418 }
419
420 void HTMLInputElement::defaultBlur()
421 {
422     HTMLTextFormControlElement::blur();
423 }
424
425 bool HTMLInputElement::hasCustomFocusLogic() const
426 {
427     return m_inputType->hasCustomFocusLogic();
428 }
429
430 bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent& event) const
431 {
432     return m_inputType->isKeyboardFocusable(event);
433 }
434
435 bool HTMLInputElement::isMouseFocusable() const
436 {
437     return m_inputType->isMouseFocusable();
438 }
439
440 bool HTMLInputElement::isTextFormControlFocusable() const
441 {
442     return HTMLTextFormControlElement::isFocusable();
443 }
444
445 bool HTMLInputElement::isTextFormControlKeyboardFocusable(KeyboardEvent& event) const
446 {
447     return HTMLTextFormControlElement::isKeyboardFocusable(event);
448 }
449
450 bool HTMLInputElement::isTextFormControlMouseFocusable() const
451 {
452     return HTMLTextFormControlElement::isMouseFocusable();
453 }
454
455 void HTMLInputElement::updateFocusAppearance(SelectionRestorationMode restorationMode, SelectionRevealMode revealMode)
456 {
457     if (isTextField()) {
458         if (restorationMode == SelectionRestorationMode::SetDefault || !hasCachedSelection())
459             select(Element::defaultFocusTextStateChangeIntent());
460         else
461             restoreCachedSelection();
462         if (document().frame())
463             document().frame()->selection().revealSelection(revealMode);
464     } else
465         HTMLTextFormControlElement::updateFocusAppearance(restorationMode, revealMode);
466 }
467
468 void HTMLInputElement::endEditing()
469 {
470     if (!isTextField())
471         return;
472
473     if (RefPtr<Frame> frame = document().frame())
474         frame->editor().textFieldDidEndEditing(this);
475 }
476
477 bool HTMLInputElement::shouldUseInputMethod()
478 {
479     return m_inputType->shouldUseInputMethod();
480 }
481
482 void HTMLInputElement::handleFocusEvent(Node* oldFocusedNode, FocusDirection direction)
483 {
484     m_inputType->handleFocusEvent(oldFocusedNode, direction);
485 }
486
487 void HTMLInputElement::handleBlurEvent()
488 {
489     m_inputType->handleBlurEvent();
490 }
491
492 void HTMLInputElement::setType(const AtomicString& type)
493 {
494     setAttributeWithoutSynchronization(typeAttr, type);
495 }
496
497 #if ENABLE(ALTERNATIVE_PRESENTATION_BUTTON_ELEMENT)
498 void HTMLInputElement::setTypeWithoutUpdatingAttribute(const AtomicString& type)
499 {
500     updateType(type);
501 }
502 #endif
503
504 inline std::unique_ptr<InputType> HTMLInputElement::createInputType(const AtomicString& type)
505 {
506 #if ENABLE(ALTERNATIVE_PRESENTATION_BUTTON_ELEMENT)
507     if (type == InputTypeNames::alternativePresentationButton())
508         return std::make_unique<AlternativePresentationButtonInputType>(*this);
509 #endif
510     return InputType::create(*this, type);
511 }
512
513 void HTMLInputElement::updateType(const AtomicString& newType)
514 {
515     ASSERT(m_inputType);
516     auto newInputType = createInputType(newType);
517     m_hasType = true;
518     if (m_inputType->formControlType() == newInputType->formControlType())
519         return;
520
521     removeFromRadioButtonGroup();
522
523     bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
524     bool neededSuspensionCallback = needsSuspensionCallback();
525     bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
526     bool wasSuccessfulSubmitButtonCandidate = m_inputType->canBeSuccessfulSubmitButton();
527
528     std::unique_ptr<InputType> oldInputType = WTFMove(m_inputType);
529     m_inputType = WTFMove(newInputType);
530     oldInputType->destroyShadowSubtree();
531     m_inputType->createShadowSubtree();
532     updateInnerTextElementEditability();
533
534     setNeedsWillValidateCheck();
535
536     bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
537
538     if (didStoreValue && !willStoreValue && hasDirtyValue()) {
539         setAttributeWithoutSynchronization(valueAttr, m_valueIfDirty);
540         m_valueIfDirty = String();
541     }
542     if (!didStoreValue && willStoreValue)
543         m_valueIfDirty = sanitizeValue(attributeWithoutSynchronization(valueAttr));
544     else
545         updateValueIfNeeded();
546
547     setFormControlValueMatchesRenderer(false);
548     m_inputType->updateInnerTextValue();
549
550     m_wasModifiedByUser = false;
551
552     if (neededSuspensionCallback)
553         unregisterForSuspensionCallbackIfNeeded();
554     else
555         registerForSuspensionCallbackIfNeeded();
556
557     if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
558         ASSERT(elementData());
559         // FIXME: We don't have the old attribute values so we pretend that we didn't have the old values.
560         if (const Attribute* height = findAttributeByName(heightAttr))
561             attributeChanged(heightAttr, nullAtom(), height->value());
562         if (const Attribute* width = findAttributeByName(widthAttr))
563             attributeChanged(widthAttr, nullAtom(), width->value());
564         if (const Attribute* align = findAttributeByName(alignAttr))
565             attributeChanged(alignAttr, nullAtom(), align->value());
566     }
567
568     if (form() && wasSuccessfulSubmitButtonCandidate != m_inputType->canBeSuccessfulSubmitButton())
569         form()->resetDefaultButton();
570
571     runPostTypeUpdateTasks();
572 }
573
574 inline void HTMLInputElement::runPostTypeUpdateTasks()
575 {
576     ASSERT(m_inputType);
577 #if ENABLE(TOUCH_EVENTS)
578     bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();
579     if (hasTouchEventHandler != m_hasTouchEventHandler) {
580         if (hasTouchEventHandler)
581             document().didAddTouchEventHandler(*this);
582         else
583             document().didRemoveTouchEventHandler(*this);
584         m_hasTouchEventHandler = hasTouchEventHandler;
585     }
586 #endif
587
588     if (renderer())
589         invalidateStyleAndRenderersForSubtree();
590
591     if (document().focusedElement() == this)
592         updateFocusAppearance(SelectionRestorationMode::Restore, SelectionRevealMode::Reveal);
593
594     setChangedSinceLastFormControlChangeEvent(false);
595
596     addToRadioButtonGroup();
597
598     updateValidity();
599 }
600
601 void HTMLInputElement::subtreeHasChanged()
602 {
603     m_inputType->subtreeHasChanged();
604     // When typing in an input field, childrenChanged is not called, so we need to force the directionality check.
605     calculateAndAdjustDirectionality();
606 }
607
608 const AtomicString& HTMLInputElement::formControlType() const
609 {
610     return m_inputType->formControlType();
611 }
612
613 bool HTMLInputElement::shouldSaveAndRestoreFormControlState() const
614 {
615     if (!m_inputType->shouldSaveAndRestoreFormControlState())
616         return false;
617     return HTMLTextFormControlElement::shouldSaveAndRestoreFormControlState();
618 }
619
620 FormControlState HTMLInputElement::saveFormControlState() const
621 {
622     return m_inputType->saveFormControlState();
623 }
624
625 void HTMLInputElement::restoreFormControlState(const FormControlState& state)
626 {
627     m_inputType->restoreFormControlState(state);
628     m_stateRestored = true;
629 }
630
631 bool HTMLInputElement::canStartSelection() const
632 {
633     if (!isTextField())
634         return false;
635     return HTMLTextFormControlElement::canStartSelection();
636 }
637
638 bool HTMLInputElement::canHaveSelection() const
639 {
640     return isTextField();
641 }
642
643 void HTMLInputElement::accessKeyAction(bool sendMouseEvents)
644 {
645     m_inputType->accessKeyAction(sendMouseEvents);
646 }
647
648 bool HTMLInputElement::isPresentationAttribute(const QualifiedName& name) const
649 {
650     if (name == vspaceAttr || name == hspaceAttr || name == alignAttr || name == widthAttr || name == heightAttr || (name == borderAttr && isImageButton()))
651         return true;
652     return HTMLTextFormControlElement::isPresentationAttribute(name);
653 }
654
655 void HTMLInputElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
656 {
657     if (name == vspaceAttr) {
658         addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
659         addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
660     } else if (name == hspaceAttr) {
661         addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
662         addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
663     } else if (name == alignAttr) {
664         if (m_inputType->shouldRespectAlignAttribute())
665             applyAlignmentAttributeToStyle(value, style);
666     } else if (name == widthAttr) {
667         if (m_inputType->shouldRespectHeightAndWidthAttributes())
668             addHTMLLengthToStyle(style, CSSPropertyWidth, value);
669     } else if (name == heightAttr) {
670         if (m_inputType->shouldRespectHeightAndWidthAttributes())
671             addHTMLLengthToStyle(style, CSSPropertyHeight, value);
672     } else if (name == borderAttr && isImageButton())
673         applyBorderAttributeToStyle(value, style);
674     else
675         HTMLTextFormControlElement::collectStyleForPresentationAttribute(name, value, style);
676 }
677
678 inline void HTMLInputElement::initializeInputType()
679 {
680     ASSERT(m_parsingInProgress);
681     ASSERT(!m_inputType);
682
683     const AtomicString& type = attributeWithoutSynchronization(typeAttr);
684     if (type.isNull()) {
685         m_inputType = InputType::createText(*this);
686         ensureUserAgentShadowRoot();
687         setNeedsWillValidateCheck();
688         return;
689     }
690
691     m_hasType = true;
692     m_inputType = InputType::create(*this, type);
693     ensureUserAgentShadowRoot();
694     setNeedsWillValidateCheck();
695     registerForSuspensionCallbackIfNeeded();
696     runPostTypeUpdateTasks();
697 }
698
699 void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
700 {
701     ASSERT(m_inputType);
702
703     if (name == nameAttr) {
704         removeFromRadioButtonGroup();
705         m_name = value;
706         addToRadioButtonGroup();
707         HTMLTextFormControlElement::parseAttribute(name, value);
708     } else if (name == autocompleteAttr) {
709         if (equalLettersIgnoringASCIICase(value, "off")) {
710             m_autocomplete = Off;
711             registerForSuspensionCallbackIfNeeded();
712         } else {
713             bool needsToUnregister = m_autocomplete == Off;
714
715             if (value.isEmpty())
716                 m_autocomplete = Uninitialized;
717             else
718                 m_autocomplete = On;
719
720             if (needsToUnregister)
721                 unregisterForSuspensionCallbackIfNeeded();
722         }
723     } else if (name == typeAttr)
724         updateType(value);
725     else if (name == valueAttr) {
726         // Changes to the value attribute may change whether or not this element has a default value.
727         // If this field is autocomplete=off that might affect the return value of needsSuspensionCallback.
728         if (m_autocomplete == Off) {
729             unregisterForSuspensionCallbackIfNeeded();
730             registerForSuspensionCallbackIfNeeded();
731         }
732         // We only need to setChanged if the form is looking at the default value right now.
733         if (!hasDirtyValue()) {
734             updatePlaceholderVisibility();
735             invalidateStyleForSubtree();
736         }
737         setFormControlValueMatchesRenderer(false);
738         updateValidity();
739         m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress;
740     } else if (name == checkedAttr) {
741         if (m_inputType->isCheckable())
742             invalidateStyleForSubtree();
743
744         // Another radio button in the same group might be checked by state
745         // restore. We shouldn't call setChecked() even if this has the checked
746         // attribute. So, delay the setChecked() call until
747         // finishParsingChildren() is called if parsing is in progress.
748         if (!m_parsingInProgress && m_reflectsCheckedAttribute) {
749             setChecked(!value.isNull());
750             m_reflectsCheckedAttribute = true;
751         }
752     } else if (name == maxlengthAttr)
753         maxLengthAttributeChanged(value);
754     else if (name == minlengthAttr)
755         minLengthAttributeChanged(value);
756     else if (name == sizeAttr) {
757         unsigned oldSize = m_size;
758         m_size = limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(value, defaultSize);
759         if (m_size != oldSize && renderer())
760             renderer()->setNeedsLayoutAndPrefWidthsRecalc();
761     } else if (name == altAttr)
762         m_inputType->altAttributeChanged();
763     else if (name == srcAttr)
764         m_inputType->srcAttributeChanged();
765     else if (name == usemapAttr || name == accesskeyAttr) {
766         // FIXME: ignore for the moment
767     } else if (name == resultsAttr) {
768         m_maxResults = !value.isNull() ? std::min(value.toInt(), maxSavedResults) : -1;
769         m_inputType->maxResultsAttributeChanged();
770     } else if (name == autosaveAttr) {
771         invalidateStyleForSubtree();
772     } else if (name == incrementalAttr) {
773         invalidateStyleForSubtree();
774     } else if (name == minAttr) {
775         m_inputType->minOrMaxAttributeChanged();
776         updateValidity();
777     } else if (name == maxAttr) {
778         m_inputType->minOrMaxAttributeChanged();
779         updateValidity();
780     } else if (name == multipleAttr) {
781         m_inputType->multipleAttributeChanged();
782         updateValidity();
783     } else if (name == stepAttr) {
784         m_inputType->stepAttributeChanged();
785         updateValidity();
786     } else if (name == patternAttr) {
787         updateValidity();
788     } else if (name == precisionAttr) {
789         updateValidity();
790     } else if (name == disabledAttr) {
791         HTMLTextFormControlElement::parseAttribute(name, value);
792         m_inputType->disabledAttributeChanged();
793     } else if (name == readonlyAttr) {
794         HTMLTextFormControlElement::parseAttribute(name, value);
795         m_inputType->readonlyAttributeChanged();
796     }
797 #if ENABLE(DATALIST_ELEMENT)
798     else if (name == listAttr) {
799         m_hasNonEmptyList = !value.isEmpty();
800         if (m_hasNonEmptyList) {
801             resetListAttributeTargetObserver();
802             listAttributeTargetChanged();
803         }
804     }
805 #endif
806     else
807         HTMLTextFormControlElement::parseAttribute(name, value);
808
809     m_inputType->attributeChanged(name);
810 }
811
812 void HTMLInputElement::parserDidSetAttributes()
813 {
814     ASSERT(m_parsingInProgress);
815     initializeInputType();
816 }
817
818 void HTMLInputElement::finishParsingChildren()
819 {
820     m_parsingInProgress = false;
821     ASSERT(m_inputType);
822     HTMLTextFormControlElement::finishParsingChildren();
823     if (!m_stateRestored) {
824         bool checked = hasAttributeWithoutSynchronization(checkedAttr);
825         if (checked)
826             setChecked(checked);
827         m_reflectsCheckedAttribute = true;
828     }
829 }
830
831 bool HTMLInputElement::rendererIsNeeded(const RenderStyle& style)
832 {
833     return m_inputType->rendererIsNeeded() && HTMLTextFormControlElement::rendererIsNeeded(style);
834 }
835
836 RenderPtr<RenderElement> HTMLInputElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
837 {
838     return m_inputType->createInputRenderer(WTFMove(style));
839 }
840
841 void HTMLInputElement::willAttachRenderers()
842 {
843     if (!m_hasType)
844         updateType(attributeWithoutSynchronization(typeAttr));
845 }
846
847 void HTMLInputElement::didAttachRenderers()
848 {
849     HTMLTextFormControlElement::didAttachRenderers();
850
851     if (m_inputType->needsPostStyleResolutionCallback()) {
852         Style::queuePostResolutionCallback([protectedElement = makeRef(*this)] {
853             protectedElement->m_inputType->updateAfterStyleResolution();
854         });
855     }
856
857     if (document().focusedElement() == this) {
858         document().view()->queuePostLayoutCallback([protectedThis = makeRef(*this)] {
859             protectedThis->updateFocusAppearance(SelectionRestorationMode::Restore, SelectionRevealMode::Reveal);
860         });
861     }
862 }
863
864 void HTMLInputElement::didDetachRenderers()
865 {
866     setFormControlValueMatchesRenderer(false);
867     m_inputType->detach();
868 }
869
870 String HTMLInputElement::altText() const
871 {
872     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
873     // also heavily discussed by Hixie on bugzilla
874     // note this is intentionally different to HTMLImageElement::altText()
875     String alt = attributeWithoutSynchronization(altAttr);
876     // fall back to title attribute
877     if (alt.isNull())
878         alt = attributeWithoutSynchronization(titleAttr);
879     if (alt.isNull())
880         alt = attributeWithoutSynchronization(valueAttr);
881     if (alt.isEmpty())
882         alt = inputElementAltText();
883     return alt;
884 }
885
886 bool HTMLInputElement::isSuccessfulSubmitButton() const
887 {
888     // HTML spec says that buttons must have names to be considered successful.
889     // However, other browsers do not impose this constraint. So we do not.
890     return !isDisabledFormControl() && m_inputType->canBeSuccessfulSubmitButton();
891 }
892
893 bool HTMLInputElement::matchesDefaultPseudoClass() const
894 {
895     ASSERT(m_inputType);
896     if (m_inputType->canBeSuccessfulSubmitButton())
897         return !isDisabledFormControl() && form() && form()->defaultButton() == this;
898     return m_inputType->isCheckable() && hasAttributeWithoutSynchronization(checkedAttr);
899 }
900
901 bool HTMLInputElement::isActivatedSubmit() const
902 {
903     return m_isActivatedSubmit;
904 }
905
906 void HTMLInputElement::setActivatedSubmit(bool flag)
907 {
908     m_isActivatedSubmit = flag;
909 }
910
911 bool HTMLInputElement::appendFormData(DOMFormData& formData, bool multipart)
912 {
913     return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(formData, multipart);
914 }
915
916 void HTMLInputElement::reset()
917 {
918     if (m_inputType->storesValueSeparateFromAttribute())
919         setValue(String());
920
921     setAutoFilled(false);
922     setShowAutoFillButton(AutoFillButtonType::None);
923     setChecked(hasAttributeWithoutSynchronization(checkedAttr));
924     m_reflectsCheckedAttribute = true;
925 }
926
927 bool HTMLInputElement::isTextField() const
928 {
929     return m_inputType->isTextField();
930 }
931
932 bool HTMLInputElement::isTextType() const
933 {
934     return m_inputType->isTextType();
935 }
936
937 void HTMLInputElement::setChecked(bool nowChecked, TextFieldEventBehavior eventBehavior)
938 {
939     if (checked() == nowChecked)
940         return;
941
942     m_reflectsCheckedAttribute = false;
943     m_isChecked = nowChecked;
944     invalidateStyleForSubtree();
945
946     if (RadioButtonGroups* buttons = radioButtonGroups())
947         buttons->updateCheckedState(this);
948     if (renderer() && renderer()->style().hasAppearance())
949         renderer()->theme().stateChanged(*renderer(), ControlStates::CheckedState);
950     updateValidity();
951
952     // Ideally we'd do this from the render tree (matching
953     // RenderTextView), but it's not possible to do it at the moment
954     // because of the way the code is structured.
955     if (renderer()) {
956         if (AXObjectCache* cache = renderer()->document().existingAXObjectCache())
957             cache->checkedStateChanged(this);
958     }
959
960     // Only send a change event for items in the document (avoid firing during
961     // parsing) and don't send a change event for a radio button that's getting
962     // unchecked to match other browsers. DOM is not a useful standard for this
963     // because it says only to fire change events at "lose focus" time, which is
964     // definitely wrong in practice for these types of elements.
965     if (eventBehavior != DispatchNoEvent && isConnected() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) {
966         setTextAsOfLastFormControlChangeEvent(String());
967         dispatchFormControlChangeEvent();
968     }
969
970     invalidateStyleForSubtree();
971 }
972
973 void HTMLInputElement::setIndeterminate(bool newValue)
974 {
975     if (indeterminate() == newValue)
976         return;
977
978     m_isIndeterminate = newValue;
979
980     invalidateStyleForSubtree();
981
982     if (renderer() && renderer()->style().hasAppearance())
983         renderer()->theme().stateChanged(*renderer(), ControlStates::CheckedState);
984 }
985
986 unsigned HTMLInputElement::size() const
987 {
988     return m_size;
989 }
990
991 bool HTMLInputElement::sizeShouldIncludeDecoration(int& preferredSize) const
992 {
993     return m_inputType->sizeShouldIncludeDecoration(defaultSize, preferredSize);
994 }
995
996 float HTMLInputElement::decorationWidth() const
997 {
998     return m_inputType->decorationWidth();
999 }
1000
1001 void HTMLInputElement::copyNonAttributePropertiesFromElement(const Element& source)
1002 {
1003     auto& sourceElement = downcast<HTMLInputElement>(source);
1004
1005     m_valueIfDirty = sourceElement.m_valueIfDirty;
1006     m_wasModifiedByUser = false;
1007     setChecked(sourceElement.m_isChecked);
1008     m_reflectsCheckedAttribute = sourceElement.m_reflectsCheckedAttribute;
1009     m_isIndeterminate = sourceElement.m_isIndeterminate;
1010
1011     HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source);
1012
1013     updateValidity();
1014     setFormControlValueMatchesRenderer(false);
1015     m_inputType->updateInnerTextValue();
1016 }
1017
1018 String HTMLInputElement::value() const
1019 {
1020     String value;
1021     if (m_inputType->getTypeSpecificValue(value))
1022         return value;
1023
1024     value = m_valueIfDirty;
1025     if (!value.isNull())
1026         return value;
1027
1028     auto& valueString = attributeWithoutSynchronization(valueAttr);
1029     value = sanitizeValue(valueString);
1030     if (!value.isNull())
1031         return value;
1032
1033     return m_inputType->fallbackValue();
1034 }
1035
1036 String HTMLInputElement::valueWithDefault() const
1037 {
1038     String value = this->value();
1039     if (!value.isNull())
1040         return value;
1041
1042     return m_inputType->defaultValue();
1043 }
1044
1045 void HTMLInputElement::setValueForUser(const String& value)
1046 {
1047     // Call setValue and make it send a change event.
1048     setValue(value, DispatchChangeEvent);
1049 }
1050
1051 void HTMLInputElement::setEditingValue(const String& value)
1052 {
1053     if (!renderer() || !isTextField())
1054         return;
1055     setInnerTextValue(value);
1056     subtreeHasChanged();
1057
1058     unsigned max = value.length();
1059     if (focused())
1060         setSelectionRange(max, max);
1061     else
1062         cacheSelectionInResponseToSetValue(max);
1063
1064     dispatchInputEvent();
1065 }
1066
1067 ExceptionOr<void> HTMLInputElement::setValue(const String& value, TextFieldEventBehavior eventBehavior)
1068 {
1069     if (isFileUpload() && !value.isEmpty())
1070         return Exception { InvalidStateError };
1071
1072     if (!m_inputType->canSetValue(value))
1073         return { };
1074
1075     Ref<HTMLInputElement> protectedThis(*this);
1076     EventQueueScope scope;
1077     String sanitizedValue = sanitizeValue(value);
1078     bool valueChanged = sanitizedValue != this->value();
1079
1080     setLastChangeWasNotUserEdit();
1081     setFormControlValueMatchesRenderer(false);
1082     m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior);
1083     return { };
1084 }
1085
1086 void HTMLInputElement::setValueInternal(const String& sanitizedValue, TextFieldEventBehavior eventBehavior)
1087 {
1088     m_valueIfDirty = sanitizedValue;
1089     m_wasModifiedByUser = eventBehavior != DispatchNoEvent;
1090     updateValidity();
1091 }
1092
1093 double HTMLInputElement::valueAsDate() const
1094 {
1095     return m_inputType->valueAsDate();
1096 }
1097
1098 ExceptionOr<void> HTMLInputElement::setValueAsDate(double value)
1099 {
1100     return m_inputType->setValueAsDate(value);
1101 }
1102
1103 double HTMLInputElement::valueAsNumber() const
1104 {
1105     return m_inputType->valueAsDouble();
1106 }
1107
1108 ExceptionOr<void> HTMLInputElement::setValueAsNumber(double newValue, TextFieldEventBehavior eventBehavior)
1109 {
1110     if (!std::isfinite(newValue))
1111         return Exception { NotSupportedError };
1112     return m_inputType->setValueAsDouble(newValue, eventBehavior);
1113 }
1114
1115 void HTMLInputElement::setValueFromRenderer(const String& value)
1116 {
1117     // File upload controls will never use this.
1118     ASSERT(!isFileUpload());
1119
1120     // Renderer and our event handler are responsible for sanitizing values.
1121     // Input types that support the selection API do *not* sanitize their
1122     // user input in order to retain parity between what's in the model and
1123     // what's on the screen.
1124     ASSERT(m_inputType->supportsSelectionAPI() || value == sanitizeValue(value) || sanitizeValue(value).isEmpty());
1125
1126     // Workaround for bug where trailing \n is included in the result of textContent.
1127     // The assert macro above may also be simplified by removing the expression
1128     // that calls isEmpty.
1129     // http://bugs.webkit.org/show_bug.cgi?id=9661
1130     m_valueIfDirty = value == "\n" ? emptyString() : value;
1131
1132     setFormControlValueMatchesRenderer(true);
1133     m_wasModifiedByUser = true;
1134
1135     // Input event is fired by the Node::defaultEventHandler for editable controls.
1136     if (!isTextField())
1137         dispatchInputEvent();
1138
1139     updateValidity();
1140
1141     // Clear auto fill flag (and yellow background) on user edit.
1142     setAutoFilled(false);
1143 }
1144
1145 void HTMLInputElement::willDispatchEvent(Event& event, InputElementClickState& state)
1146 {
1147     if (event.type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event))
1148         event.stopPropagation();
1149     if (event.type() == eventNames().clickEvent && is<MouseEvent>(event) && downcast<MouseEvent>(event).button() == LeftButton) {
1150         m_inputType->willDispatchClick(state);
1151         state.stateful = true;
1152     }
1153 }
1154
1155 void HTMLInputElement::didDispatchClickEvent(Event& event, const InputElementClickState& state)
1156 {
1157     m_inputType->didDispatchClick(event, state);
1158 }
1159
1160 void HTMLInputElement::didBlur()
1161 {
1162     m_inputType->elementDidBlur();
1163 }
1164
1165 void HTMLInputElement::defaultEventHandler(Event& event)
1166 {
1167     if (is<MouseEvent>(event) && event.type() == eventNames().clickEvent && downcast<MouseEvent>(event).button() == LeftButton) {
1168         m_inputType->handleClickEvent(downcast<MouseEvent>(event));
1169         if (event.defaultHandled())
1170             return;
1171     }
1172
1173 #if ENABLE(TOUCH_EVENTS)
1174     if (is<TouchEvent>(event)) {
1175         m_inputType->handleTouchEvent(downcast<TouchEvent>(event));
1176         if (event.defaultHandled())
1177             return;
1178     }
1179 #endif
1180
1181     if (is<KeyboardEvent>(event) && event.type() == eventNames().keydownEvent) {
1182         m_inputType->handleKeydownEvent(downcast<KeyboardEvent>(event));
1183         if (event.defaultHandled())
1184             return;
1185     }
1186
1187     // Call the base event handler before any of our own event handling for almost all events in text fields.
1188     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
1189     bool callBaseClassEarly = isTextField() && (event.type() == eventNames().keydownEvent || event.type() == eventNames().keypressEvent);
1190     if (callBaseClassEarly) {
1191         HTMLTextFormControlElement::defaultEventHandler(event);
1192         if (event.defaultHandled())
1193             return;
1194     }
1195
1196     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
1197     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
1198     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
1199     // must dispatch a DOMActivate event - a click event will not do the job.
1200     if (event.type() == eventNames().DOMActivateEvent) {
1201         m_inputType->handleDOMActivateEvent(event);
1202         if (event.defaultHandled())
1203             return;
1204     }
1205
1206     // Use key press event here since sending simulated mouse events
1207     // on key down blocks the proper sending of the key press event.
1208     if (is<KeyboardEvent>(event)) {
1209         KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(event);
1210         if (keyboardEvent.type() == eventNames().keypressEvent) {
1211             m_inputType->handleKeypressEvent(keyboardEvent);
1212             if (keyboardEvent.defaultHandled())
1213                 return;
1214         } else if (keyboardEvent.type() == eventNames().keyupEvent) {
1215             m_inputType->handleKeyupEvent(keyboardEvent);
1216             if (keyboardEvent.defaultHandled())
1217                 return;
1218         }
1219     }
1220
1221     if (m_inputType->shouldSubmitImplicitly(event)) {
1222         if (isSearchField()) {
1223             addSearchResult();
1224             onSearch();
1225         }
1226         // Form submission finishes editing, just as loss of focus does.
1227         // If there was a change, send the event now.
1228         if (wasChangedSinceLastFormControlChangeEvent())
1229             dispatchFormControlChangeEvent();
1230
1231         // Form may never have been present, or may have been destroyed by code responding to the change event.
1232         if (auto formElement = makeRefPtr(form()))
1233             formElement->submitImplicitly(event, canTriggerImplicitSubmission());
1234
1235         event.setDefaultHandled();
1236         return;
1237     }
1238
1239     if (is<BeforeTextInsertedEvent>(event))
1240         m_inputType->handleBeforeTextInsertedEvent(downcast<BeforeTextInsertedEvent>(event));
1241
1242     if (is<MouseEvent>(event) && event.type() == eventNames().mousedownEvent) {
1243         m_inputType->handleMouseDownEvent(downcast<MouseEvent>(event));
1244         if (event.defaultHandled())
1245             return;
1246     }
1247
1248     m_inputType->forwardEvent(event);
1249
1250     if (!callBaseClassEarly && !event.defaultHandled())
1251         HTMLTextFormControlElement::defaultEventHandler(event);
1252 }
1253
1254 bool HTMLInputElement::willRespondToMouseClickEvents()
1255 {
1256     if (!isDisabledFormControl())
1257         return true;
1258
1259     return HTMLTextFormControlElement::willRespondToMouseClickEvents();
1260 }
1261
1262 bool HTMLInputElement::isURLAttribute(const Attribute& attribute) const
1263 {
1264     return attribute.name() == srcAttr || attribute.name() == formactionAttr || HTMLTextFormControlElement::isURLAttribute(attribute);
1265 }
1266
1267 String HTMLInputElement::defaultValue() const
1268 {
1269     return attributeWithoutSynchronization(valueAttr);
1270 }
1271
1272 void HTMLInputElement::setDefaultValue(const String &value)
1273 {
1274     setAttributeWithoutSynchronization(valueAttr, value);
1275 }
1276
1277 static inline bool isRFC2616TokenCharacter(UChar ch)
1278 {
1279     return isASCII(ch) && ch > ' ' && ch != '"' && ch != '(' && ch != ')' && ch != ',' && ch != '/' && (ch < ':' || ch > '@') && (ch < '[' || ch > ']') && ch != '{' && ch != '}' && ch != 0x7f;
1280 }
1281
1282 static bool isValidMIMEType(const String& type)
1283 {
1284     size_t slashPosition = type.find('/');
1285     if (slashPosition == notFound || !slashPosition || slashPosition == type.length() - 1)
1286         return false;
1287     for (size_t i = 0; i < type.length(); ++i) {
1288         if (!isRFC2616TokenCharacter(type[i]) && i != slashPosition)
1289             return false;
1290     }
1291     return true;
1292 }
1293
1294 static bool isValidFileExtension(const String& type)
1295 {
1296     if (type.length() < 2)
1297         return false;
1298     return type[0] == '.';
1299 }
1300
1301 static Vector<String> parseAcceptAttribute(const String& acceptString, bool (*predicate)(const String&))
1302 {
1303     Vector<String> types;
1304     if (acceptString.isEmpty())
1305         return types;
1306
1307     Vector<String> splitTypes;
1308     acceptString.split(',', false, splitTypes);
1309     for (auto& splitType : splitTypes) {
1310         String trimmedType = stripLeadingAndTrailingHTMLSpaces(splitType);
1311         if (trimmedType.isEmpty())
1312             continue;
1313         if (!predicate(trimmedType))
1314             continue;
1315         types.append(trimmedType.convertToASCIILowercase());
1316     }
1317
1318     return types;
1319 }
1320
1321 Vector<String> HTMLInputElement::acceptMIMETypes()
1322 {
1323     return parseAcceptAttribute(attributeWithoutSynchronization(acceptAttr), isValidMIMEType);
1324 }
1325
1326 Vector<String> HTMLInputElement::acceptFileExtensions()
1327 {
1328     return parseAcceptAttribute(attributeWithoutSynchronization(acceptAttr), isValidFileExtension);
1329 }
1330
1331 String HTMLInputElement::accept() const
1332 {
1333     return attributeWithoutSynchronization(acceptAttr);
1334 }
1335
1336 String HTMLInputElement::alt() const
1337 {
1338     return attributeWithoutSynchronization(altAttr);
1339 }
1340
1341 unsigned HTMLInputElement::effectiveMaxLength() const
1342 {
1343     // The number -1 represents no maximum at all; conveniently it becomes a super-large value when converted to unsigned.
1344     return std::min<unsigned>(maxLength(), maxEffectiveLength);
1345 }
1346
1347 bool HTMLInputElement::multiple() const
1348 {
1349     return hasAttributeWithoutSynchronization(multipleAttr);
1350 }
1351
1352 ExceptionOr<void> HTMLInputElement::setSize(unsigned size)
1353 {
1354     if (!size)
1355         return Exception { IndexSizeError };
1356     setUnsignedIntegralAttribute(sizeAttr, limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(size, defaultSize));
1357     return { };
1358 }
1359
1360 URL HTMLInputElement::src() const
1361 {
1362     return document().completeURL(attributeWithoutSynchronization(srcAttr));
1363 }
1364
1365 void HTMLInputElement::setAutoFilled(bool autoFilled)
1366 {
1367     if (autoFilled == m_isAutoFilled)
1368         return;
1369
1370     m_isAutoFilled = autoFilled;
1371     invalidateStyleForSubtree();
1372 }
1373
1374 void HTMLInputElement::setShowAutoFillButton(AutoFillButtonType autoFillButtonType)
1375 {
1376     if (static_cast<uint8_t>(autoFillButtonType) == m_autoFillButtonType)
1377         return;
1378
1379     m_autoFillButtonType = static_cast<uint8_t>(autoFillButtonType);
1380     m_inputType->updateAutoFillButton();
1381     updateInnerTextElementEditability();
1382     invalidateStyleForSubtree();
1383 }
1384
1385 FileList* HTMLInputElement::files()
1386 {
1387     return m_inputType->files();
1388 }
1389
1390 void HTMLInputElement::setFiles(RefPtr<FileList>&& files)
1391 {
1392     m_inputType->setFiles(WTFMove(files));
1393 }
1394
1395 #if ENABLE(DRAG_SUPPORT)
1396 bool HTMLInputElement::receiveDroppedFiles(const DragData& dragData)
1397 {
1398     return m_inputType->receiveDroppedFiles(dragData);
1399 }
1400 #endif
1401
1402 Icon* HTMLInputElement::icon() const
1403 {
1404     return m_inputType->icon();
1405 }
1406
1407 String HTMLInputElement::displayString() const
1408 {
1409     return m_inputType->displayString();
1410 }
1411
1412 bool HTMLInputElement::canReceiveDroppedFiles() const
1413 {
1414     return m_canReceiveDroppedFiles;
1415 }
1416
1417 void HTMLInputElement::setCanReceiveDroppedFiles(bool canReceiveDroppedFiles)
1418 {
1419     if (m_canReceiveDroppedFiles == canReceiveDroppedFiles)
1420         return;
1421     m_canReceiveDroppedFiles = canReceiveDroppedFiles;
1422     if (renderer())
1423         renderer()->updateFromElement();
1424 }
1425
1426 String HTMLInputElement::visibleValue() const
1427 {
1428     return m_inputType->visibleValue();
1429 }
1430
1431 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
1432 {
1433     if (proposedValue.isNull())
1434         return proposedValue;
1435     return m_inputType->sanitizeValue(proposedValue);
1436 }
1437
1438 String HTMLInputElement::localizeValue(const String& proposedValue) const
1439 {
1440     if (proposedValue.isNull())
1441         return proposedValue;
1442     return m_inputType->localizeValue(proposedValue);
1443 }
1444
1445 bool HTMLInputElement::isInRange() const
1446 {
1447     return willValidate() && m_inputType->isInRange(value());
1448 }
1449
1450 bool HTMLInputElement::isOutOfRange() const
1451 {
1452     return willValidate() && m_inputType->isOutOfRange(value());
1453 }
1454
1455 bool HTMLInputElement::needsSuspensionCallback()
1456 {
1457     if (m_inputType->shouldResetOnDocumentActivation())
1458         return true;
1459
1460     // Sensitive input elements are marked with autocomplete=off, and we want to wipe them out
1461     // when going back; returning true here arranges for us to call reset at the time
1462     // the page is restored. Non-empty textual default values indicate that the field
1463     // is not really sensitive -- there's no default value for an account number --
1464     // and we would see unexpected results if we reset to something other than blank.
1465     bool isSensitive = m_autocomplete == Off && !(m_inputType->isTextType() && !defaultValue().isEmpty());
1466
1467     return isSensitive;
1468 }
1469
1470 void HTMLInputElement::registerForSuspensionCallbackIfNeeded()
1471 {
1472     if (needsSuspensionCallback())
1473         document().registerForDocumentSuspensionCallbacks(this);
1474 }
1475
1476 void HTMLInputElement::unregisterForSuspensionCallbackIfNeeded()
1477 {
1478     if (!needsSuspensionCallback())
1479         document().unregisterForDocumentSuspensionCallbacks(this);
1480 }
1481
1482 bool HTMLInputElement::isRequiredFormControl() const
1483 {
1484     return m_inputType->supportsRequired() && isRequired();
1485 }
1486
1487 bool HTMLInputElement::matchesReadWritePseudoClass() const
1488 {
1489     return m_inputType->supportsReadOnly() && !isDisabledOrReadOnly();
1490 }
1491
1492 void HTMLInputElement::addSearchResult()
1493 {
1494     m_inputType->addSearchResult();
1495 }
1496
1497 void HTMLInputElement::onSearch()
1498 {
1499     // The type of the input element could have changed during event handling. If we are no longer
1500     // a search field, don't try to do search things.
1501     if (!isSearchField())
1502         return;
1503
1504     if (m_inputType)
1505         downcast<SearchInputType>(*m_inputType.get()).stopSearchEventTimer();
1506     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
1507 }
1508
1509 void HTMLInputElement::resumeFromDocumentSuspension()
1510 {
1511     ASSERT(needsSuspensionCallback());
1512
1513 #if ENABLE(INPUT_TYPE_COLOR)
1514     // <input type=color> uses prepareForDocumentSuspension to detach the color picker UI,
1515     // so it should not be reset when being loaded from page cache.
1516     if (isColorControl()) 
1517         return;
1518 #endif // ENABLE(INPUT_TYPE_COLOR)
1519     reset();
1520 }
1521
1522 #if ENABLE(INPUT_TYPE_COLOR)
1523 void HTMLInputElement::prepareForDocumentSuspension()
1524 {
1525     if (!isColorControl())
1526         return;
1527     m_inputType->detach();
1528 }
1529 #endif // ENABLE(INPUT_TYPE_COLOR)
1530
1531
1532 void HTMLInputElement::willChangeForm()
1533 {
1534     removeFromRadioButtonGroup();
1535     HTMLTextFormControlElement::willChangeForm();
1536 }
1537
1538 void HTMLInputElement::didChangeForm()
1539 {
1540     HTMLTextFormControlElement::didChangeForm();
1541     addToRadioButtonGroup();
1542 }
1543
1544 Node::InsertedIntoAncestorResult HTMLInputElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
1545 {
1546     HTMLTextFormControlElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
1547 #if ENABLE(DATALIST_ELEMENT)
1548     resetListAttributeTargetObserver();
1549 #endif
1550     return InsertedIntoAncestorResult::NeedsPostInsertionCallback;
1551 }
1552
1553 void HTMLInputElement::didFinishInsertingNode()
1554 {
1555     HTMLTextFormControlElement::didFinishInsertingNode();
1556     if (isConnected() && !form())
1557         addToRadioButtonGroup();
1558 }
1559
1560 void HTMLInputElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
1561 {
1562     if (removalType.disconnectedFromDocument && !form())
1563         removeFromRadioButtonGroup();
1564     HTMLTextFormControlElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
1565     ASSERT(!isConnected());
1566 #if ENABLE(DATALIST_ELEMENT)
1567     resetListAttributeTargetObserver();
1568 #endif
1569 }
1570
1571 void HTMLInputElement::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
1572 {
1573     if (imageLoader())
1574         imageLoader()->elementDidMoveToNewDocument();
1575
1576     // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
1577     if (needsSuspensionCallback()) {
1578         oldDocument.unregisterForDocumentSuspensionCallbacks(this);
1579         newDocument.registerForDocumentSuspensionCallbacks(this);
1580     }
1581     if (isRadioButton())
1582         oldDocument.formController().radioButtonGroups().removeButton(this);
1583 #if ENABLE(TOUCH_EVENTS)
1584     if (m_hasTouchEventHandler) {
1585         oldDocument.didRemoveEventTargetNode(*this);
1586         newDocument.didAddTouchEventHandler(*this);
1587     }
1588 #endif
1589
1590     HTMLTextFormControlElement::didMoveToNewDocument(oldDocument, newDocument);
1591 }
1592
1593 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
1594 {
1595     HTMLTextFormControlElement::addSubresourceAttributeURLs(urls);
1596
1597     addSubresourceURL(urls, src());
1598 }
1599
1600 bool HTMLInputElement::computeWillValidate() const
1601 {
1602     return m_inputType->supportsValidation() && HTMLTextFormControlElement::computeWillValidate();
1603 }
1604
1605 void HTMLInputElement::requiredAttributeChanged()
1606 {
1607     HTMLTextFormControlElement::requiredAttributeChanged();
1608     if (RadioButtonGroups* buttons = radioButtonGroups())
1609         buttons->requiredAttributeChanged(this);
1610     m_inputType->requiredAttributeChanged();
1611 }
1612
1613 Color HTMLInputElement::valueAsColor() const
1614 {
1615     return m_inputType->valueAsColor();
1616 }
1617
1618 void HTMLInputElement::selectColor(StringView color)
1619 {
1620     m_inputType->selectColor(color);
1621 }
1622
1623 #if ENABLE(DATALIST_ELEMENT)
1624
1625 RefPtr<HTMLElement> HTMLInputElement::list() const
1626 {
1627     return dataList();
1628 }
1629
1630 RefPtr<HTMLDataListElement> HTMLInputElement::dataList() const
1631 {
1632     if (!m_hasNonEmptyList)
1633         return nullptr;
1634
1635     if (!m_inputType->shouldRespectListAttribute())
1636         return nullptr;
1637
1638     RefPtr<Element> element = treeScope().getElementById(attributeWithoutSynchronization(listAttr));
1639     if (!is<HTMLDataListElement>(element))
1640         return nullptr;
1641
1642     return downcast<HTMLDataListElement>(element.get());
1643 }
1644
1645 void HTMLInputElement::resetListAttributeTargetObserver()
1646 {
1647     if (isConnected())
1648         m_listAttributeTargetObserver = std::make_unique<ListAttributeTargetObserver>(attributeWithoutSynchronization(listAttr), this);
1649     else
1650         m_listAttributeTargetObserver = nullptr;
1651 }
1652
1653 void HTMLInputElement::listAttributeTargetChanged()
1654 {
1655     m_inputType->listAttributeTargetChanged();
1656 }
1657
1658 #endif // ENABLE(DATALIST_ELEMENT)
1659
1660 bool HTMLInputElement::isSteppable() const
1661 {
1662     return m_inputType->isSteppable();
1663 }
1664
1665 #if PLATFORM(IOS)
1666 DateComponents::Type HTMLInputElement::dateType() const
1667 {
1668     return m_inputType->dateType();
1669 }
1670 #endif
1671
1672 bool HTMLInputElement::isTextButton() const
1673 {
1674     return m_inputType->isTextButton();
1675 }
1676
1677 bool HTMLInputElement::isRadioButton() const
1678 {
1679     return m_inputType->isRadioButton();
1680 }
1681
1682 bool HTMLInputElement::isSearchField() const
1683 {
1684     return m_inputType->isSearchField();
1685 }
1686
1687 bool HTMLInputElement::isInputTypeHidden() const
1688 {
1689     return m_inputType->isHiddenType();
1690 }
1691
1692 bool HTMLInputElement::isPasswordField() const
1693 {
1694     return m_inputType->isPasswordField();
1695 }
1696
1697 bool HTMLInputElement::isCheckbox() const
1698 {
1699     return m_inputType->isCheckbox();
1700 }
1701
1702 bool HTMLInputElement::isRangeControl() const
1703 {
1704     return m_inputType->isRangeControl();
1705 }
1706
1707 #if ENABLE(INPUT_TYPE_COLOR)
1708 bool HTMLInputElement::isColorControl() const
1709 {
1710     return m_inputType->isColorControl();
1711 }
1712 #endif
1713
1714 bool HTMLInputElement::isText() const
1715 {
1716     return m_inputType->isTextType();
1717 }
1718
1719 bool HTMLInputElement::isEmailField() const
1720 {
1721     return m_inputType->isEmailField();
1722 }
1723
1724 bool HTMLInputElement::isFileUpload() const
1725 {
1726     return m_inputType->isFileUpload();
1727 }
1728
1729 bool HTMLInputElement::isImageButton() const
1730 {
1731     return m_inputType->isImageButton();
1732 }
1733
1734 bool HTMLInputElement::isNumberField() const
1735 {
1736     return m_inputType->isNumberField();
1737 }
1738
1739 bool HTMLInputElement::isSubmitButton() const
1740 {
1741     return m_inputType->isSubmitButton();
1742 }
1743
1744 bool HTMLInputElement::isTelephoneField() const
1745 {
1746     return m_inputType->isTelephoneField();
1747 }
1748
1749 bool HTMLInputElement::isURLField() const
1750 {
1751     return m_inputType->isURLField();
1752 }
1753
1754 bool HTMLInputElement::isDateField() const
1755 {
1756     return m_inputType->isDateField();
1757 }
1758
1759 bool HTMLInputElement::isDateTimeField() const
1760 {
1761     return m_inputType->isDateTimeField();
1762 }
1763
1764 bool HTMLInputElement::isDateTimeLocalField() const
1765 {
1766     return m_inputType->isDateTimeLocalField();
1767 }
1768
1769 bool HTMLInputElement::isMonthField() const
1770 {
1771     return m_inputType->isMonthField();
1772 }
1773
1774 bool HTMLInputElement::isTimeField() const
1775 {
1776     return m_inputType->isTimeField();
1777 }
1778
1779 bool HTMLInputElement::isWeekField() const
1780 {
1781     return m_inputType->isWeekField();
1782 }
1783
1784 bool HTMLInputElement::isEnumeratable() const
1785 {
1786     return m_inputType->isEnumeratable();
1787 }
1788
1789 bool HTMLInputElement::supportLabels() const
1790 {
1791     return m_inputType->supportLabels();
1792 }
1793
1794 bool HTMLInputElement::shouldAppearChecked() const
1795 {
1796     return checked() && m_inputType->isCheckable();
1797 }
1798
1799 bool HTMLInputElement::supportsPlaceholder() const
1800 {
1801     return m_inputType->supportsPlaceholder();
1802 }
1803
1804 void HTMLInputElement::updatePlaceholderText()
1805 {
1806     return m_inputType->updatePlaceholderText();
1807 }
1808
1809 bool HTMLInputElement::isEmptyValue() const
1810 {
1811     return m_inputType->isEmptyValue();
1812 }
1813
1814 void HTMLInputElement::maxLengthAttributeChanged(const AtomicString& newValue)
1815 {
1816     unsigned oldEffectiveMaxLength = effectiveMaxLength();
1817     internalSetMaxLength(parseHTMLNonNegativeInteger(newValue).value_or(-1));
1818     if (oldEffectiveMaxLength != effectiveMaxLength())
1819         updateValueIfNeeded();
1820
1821     // FIXME: Do we really need to do this if the effective maxLength has not changed?
1822     invalidateStyleForSubtree();
1823     updateValidity();
1824 }
1825
1826 void HTMLInputElement::minLengthAttributeChanged(const AtomicString& newValue)
1827 {
1828     int oldMinLength = minLength();
1829     internalSetMinLength(parseHTMLNonNegativeInteger(newValue).value_or(-1));
1830     if (oldMinLength != minLength())
1831         updateValueIfNeeded();
1832
1833     // FIXME: Do we really need to do this if the effective minLength has not changed?
1834     invalidateStyleForSubtree();
1835     updateValidity();
1836 }
1837
1838 void HTMLInputElement::updateValueIfNeeded()
1839 {
1840     String newValue = sanitizeValue(m_valueIfDirty);
1841     ASSERT(!m_valueIfDirty.isNull() || newValue.isNull());
1842     if (newValue != m_valueIfDirty)
1843         setValue(newValue);
1844 }
1845
1846 String HTMLInputElement::defaultToolTip() const
1847 {
1848     return m_inputType->defaultToolTip();
1849 }
1850
1851 bool HTMLInputElement::matchesIndeterminatePseudoClass() const
1852 {
1853     // For input elements, matchesIndeterminatePseudoClass()
1854     // is not equivalent to shouldAppearIndeterminate() because of radio button.
1855     //
1856     // A group of radio button without any checked button is indeterminate
1857     // for the :indeterminate selector. On the other hand, RenderTheme
1858     // currently only supports single element being indeterminate.
1859     // Because of this, radio is indetermindate for CSS but not for render theme.
1860     return m_inputType->matchesIndeterminatePseudoClass();
1861 }
1862
1863 bool HTMLInputElement::shouldAppearIndeterminate() const 
1864 {
1865     return m_inputType->shouldAppearIndeterminate();
1866 }
1867
1868 #if ENABLE(MEDIA_CAPTURE)
1869 MediaCaptureType HTMLInputElement::mediaCaptureType() const
1870 {
1871     if (!isFileUpload())
1872         return MediaCaptureTypeNone;
1873     
1874     auto& captureAttribute = attributeWithoutSynchronization(captureAttr);
1875     if (captureAttribute.isNull())
1876         return MediaCaptureTypeNone;
1877     
1878     if (equalLettersIgnoringASCIICase(captureAttribute, "user"))
1879         return MediaCaptureTypeUser;
1880     
1881     return MediaCaptureTypeEnvironment;
1882 }
1883 #endif
1884
1885 bool HTMLInputElement::isInRequiredRadioButtonGroup()
1886 {
1887     ASSERT(isRadioButton());
1888     if (RadioButtonGroups* buttons = radioButtonGroups())
1889         return buttons->isInRequiredGroup(this);
1890     return false;
1891 }
1892
1893 Vector<HTMLInputElement*> HTMLInputElement::radioButtonGroup() const
1894 {
1895     RadioButtonGroups* buttons = radioButtonGroups();
1896     if (!buttons)
1897         return { };
1898     return buttons->groupMembers(*this);
1899 }
1900     
1901 HTMLInputElement* HTMLInputElement::checkedRadioButtonForGroup() const
1902 {
1903     if (RadioButtonGroups* buttons = radioButtonGroups())
1904         return buttons->checkedButtonForGroup(name());
1905     return 0;
1906 }
1907
1908 RadioButtonGroups* HTMLInputElement::radioButtonGroups() const
1909 {
1910     if (!isRadioButton())
1911         return nullptr;
1912     if (auto* formElement = form())
1913         return &formElement->radioButtonGroups();
1914     if (isConnected())
1915         return &document().formController().radioButtonGroups();
1916     return nullptr;
1917 }
1918
1919 inline void HTMLInputElement::addToRadioButtonGroup()
1920 {
1921     if (RadioButtonGroups* buttons = radioButtonGroups())
1922         buttons->addButton(this);
1923 }
1924
1925 inline void HTMLInputElement::removeFromRadioButtonGroup()
1926 {
1927     if (RadioButtonGroups* buttons = radioButtonGroups())
1928         buttons->removeButton(this);
1929 }
1930
1931 unsigned HTMLInputElement::height() const
1932 {
1933     return m_inputType->height();
1934 }
1935
1936 unsigned HTMLInputElement::width() const
1937 {
1938     return m_inputType->width();
1939 }
1940
1941 void HTMLInputElement::setHeight(unsigned height)
1942 {
1943     setUnsignedIntegralAttribute(heightAttr, height);
1944 }
1945
1946 void HTMLInputElement::setWidth(unsigned width)
1947 {
1948     setUnsignedIntegralAttribute(widthAttr, width);
1949 }
1950
1951 #if ENABLE(DATALIST_ELEMENT)
1952 ListAttributeTargetObserver::ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement* element)
1953     : IdTargetObserver(element->treeScope().idTargetObserverRegistry(), id)
1954     , m_element(element)
1955 {
1956 }
1957
1958 void ListAttributeTargetObserver::idTargetChanged()
1959 {
1960     m_element->listAttributeTargetChanged();
1961 }
1962 #endif
1963
1964 ExceptionOr<void> HTMLInputElement::setRangeText(const String& replacement)
1965 {
1966     if (!m_inputType->supportsSelectionAPI())
1967         return Exception { InvalidStateError };
1968
1969     return HTMLTextFormControlElement::setRangeText(replacement);
1970 }
1971
1972 ExceptionOr<void> HTMLInputElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode)
1973 {
1974     if (!m_inputType->supportsSelectionAPI())
1975         return Exception { InvalidStateError };
1976
1977     return HTMLTextFormControlElement::setRangeText(replacement, start, end, selectionMode);
1978 }
1979
1980 bool HTMLInputElement::shouldTruncateText(const RenderStyle& style) const
1981 {
1982     if (!isTextField())
1983         return false;
1984     return document().focusedElement() != this && style.textOverflow() == TextOverflowEllipsis;
1985 }
1986
1987 ExceptionOr<int> HTMLInputElement::selectionStartForBindings() const
1988 {
1989     if (!canHaveSelection())
1990         return Exception { TypeError };
1991
1992     return selectionStart();
1993 }
1994
1995 ExceptionOr<void> HTMLInputElement::setSelectionStartForBindings(int start)
1996 {
1997     if (!canHaveSelection())
1998         return Exception { TypeError };
1999
2000     setSelectionStart(start);
2001     return { };
2002 }
2003
2004 ExceptionOr<int> HTMLInputElement::selectionEndForBindings() const
2005 {
2006     if (!canHaveSelection())
2007         return Exception { TypeError };
2008
2009     return selectionEnd();
2010 }
2011
2012 ExceptionOr<void> HTMLInputElement::setSelectionEndForBindings(int end)
2013 {
2014     if (!canHaveSelection())
2015         return Exception { TypeError };
2016
2017     setSelectionEnd(end);
2018     return { };
2019 }
2020
2021 ExceptionOr<String> HTMLInputElement::selectionDirectionForBindings() const
2022 {
2023     if (!canHaveSelection())
2024         return Exception { TypeError };
2025
2026     return String { selectionDirection() };
2027 }
2028
2029 ExceptionOr<void> HTMLInputElement::setSelectionDirectionForBindings(const String& direction)
2030 {
2031     if (!canHaveSelection())
2032         return Exception { TypeError };
2033
2034     setSelectionDirection(direction);
2035     return { };
2036 }
2037
2038 ExceptionOr<void> HTMLInputElement::setSelectionRangeForBindings(int start, int end, const String& direction)
2039 {
2040     if (!canHaveSelection())
2041         return Exception { TypeError };
2042     
2043     setSelectionRange(start, end, direction);
2044     return { };
2045 }
2046
2047 static Ref<CSSLinearGradientValue> autoFillStrongPasswordMaskImage()
2048 {
2049     CSSGradientColorStop firstStop;
2050     firstStop.m_color = CSSValuePool::singleton().createColorValue(Color::black);
2051     firstStop.m_position = CSSValuePool::singleton().createValue(3, CSSPrimitiveValue::UnitType::CSS_EMS);
2052
2053     CSSGradientColorStop secondStop;
2054     secondStop.m_color = CSSValuePool::singleton().createColorValue(Color::transparent);
2055     secondStop.m_position = CSSValuePool::singleton().createValue(7, CSSPrimitiveValue::UnitType::CSS_EMS);
2056
2057     auto gradient = CSSLinearGradientValue::create(CSSGradientRepeat::NonRepeating, CSSGradientType::CSSLinearGradient);
2058     gradient->setAngle(CSSValuePool::singleton().createValue(90, CSSPrimitiveValue::UnitType::CSS_DEG));
2059     gradient->addStop(firstStop);
2060     gradient->addStop(secondStop);
2061     return gradient;
2062 }
2063
2064 RenderStyle HTMLInputElement::createInnerTextStyle(const RenderStyle& style)
2065 {
2066     auto textBlockStyle = RenderStyle::create();
2067     textBlockStyle.inheritFrom(style);
2068     adjustInnerTextStyle(style, textBlockStyle);
2069
2070     textBlockStyle.setWhiteSpace(PRE);
2071     textBlockStyle.setOverflowWrap(NormalOverflowWrap);
2072     textBlockStyle.setOverflowX(OHIDDEN);
2073     textBlockStyle.setOverflowY(OHIDDEN);
2074     textBlockStyle.setTextOverflow(shouldTruncateText(style) ? TextOverflowEllipsis : TextOverflowClip);
2075
2076     textBlockStyle.setDisplay(BLOCK);
2077
2078     if (hasAutoFillStrongPasswordButton()) {
2079         textBlockStyle.setColor({ 0.0f, 0.0f, 0.0f, 0.6f });
2080         textBlockStyle.setTextOverflow(TextOverflowClip);
2081         textBlockStyle.setMaskImage(styleResolver().styleImage(autoFillStrongPasswordMaskImage()));
2082         // A stacking context is needed for the mask.
2083         if (textBlockStyle.hasAutoZIndex())
2084             textBlockStyle.setZIndex(0);
2085     }
2086
2087     // Do not allow line-height to be smaller than our default.
2088     if (textBlockStyle.fontMetrics().lineSpacing() > style.computedLineHeight())
2089         textBlockStyle.setLineHeight(RenderStyle::initialLineHeight());
2090
2091     return textBlockStyle;
2092 }
2093
2094 #if ENABLE(DATE_AND_TIME_INPUT_TYPES)
2095 bool HTMLInputElement::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
2096 {
2097     if (!document().view())
2098         return false;
2099
2100     parameters.type = type();
2101     parameters.minimum = minimum();
2102     parameters.maximum = maximum();
2103     parameters.required = isRequired();
2104
2105     if (!document().settings().langAttributeAwareFormControlUIEnabled())
2106         parameters.locale = defaultLanguage();
2107     else {
2108         AtomicString computedLocale = computeInheritedLanguage();
2109         parameters.locale = computedLocale.isEmpty() ? AtomicString(defaultLanguage()) : computedLocale;
2110     }
2111
2112     StepRange stepRange = createStepRange(RejectAny);
2113     if (stepRange.hasStep()) {
2114         parameters.step = stepRange.step().toDouble();
2115         parameters.stepBase = stepRange.stepBase().toDouble();
2116     } else {
2117         parameters.step = 1.0;
2118         parameters.stepBase = 0;
2119     }
2120
2121     if (RenderElement* renderer = this->renderer())
2122         parameters.anchorRectInRootView = document().view()->contentsToRootView(renderer->absoluteBoundingBoxRect());
2123     else
2124         parameters.anchorRectInRootView = IntRect();
2125     parameters.currentValue = value();
2126     parameters.isAnchorElementRTL = computedStyle()->direction() == RTL;
2127 #if ENABLE(DATALIST_ELEMENT)
2128     if (auto dataList = this->dataList()) {
2129         Ref<HTMLCollection> options = dataList->options();
2130         for (unsigned i = 0; RefPtr<HTMLOptionElement> option = downcast<HTMLOptionElement>(options->item(i)); ++i) {
2131             if (!isValidValue(option->value()))
2132                 continue;
2133             parameters.suggestionValues.append(sanitizeValue(option->value()));
2134             parameters.localizedSuggestionValues.append(localizeValue(option->value()));
2135             parameters.suggestionLabels.append(option->value() == option->label() ? String() : option->label());
2136         }
2137     }
2138 #endif
2139     return true;
2140 }
2141 #endif
2142
2143 void HTMLInputElement::capsLockStateMayHaveChanged()
2144 {
2145     m_inputType->capsLockStateMayHaveChanged();
2146 }
2147
2148 } // namespace