40f4e7435ff419fbbed6317c2af6138ab3e3ffbf
[WebKit-https.git] / Source / WebCore / html / InputType.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-2018 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) 2009, 2010, 2011, 2012 Google Inc. All rights reserved.
9  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  *
26  */
27
28 #include "config.h"
29 #include "InputType.h"
30
31 #include "AXObjectCache.h"
32 #include "BeforeTextInsertedEvent.h"
33 #include "ButtonInputType.h"
34 #include "CheckboxInputType.h"
35 #include "ColorInputType.h"
36 #include "DOMFormData.h"
37 #include "DateComponents.h"
38 #include "DateInputType.h"
39 #include "DateTimeLocalInputType.h"
40 #include "Decimal.h"
41 #include "DocumentInlines.h"
42 #include "ElementInlines.h"
43 #include "EmailInputType.h"
44 #include "EventNames.h"
45 #include "FileInputType.h"
46 #include "FileList.h"
47 #include "FormController.h"
48 #include "HTMLFormElement.h"
49 #include "HTMLInputElement.h"
50 #include "HTMLNames.h"
51 #include "HTMLParserIdioms.h"
52 #include "HiddenInputType.h"
53 #include "ImageInputType.h"
54 #include "InputTypeNames.h"
55 #include "KeyboardEvent.h"
56 #include "LocalizedStrings.h"
57 #include "MonthInputType.h"
58 #include "NodeRenderStyle.h"
59 #include "NumberInputType.h"
60 #include "Page.h"
61 #include "PasswordInputType.h"
62 #include "PseudoClassChangeInvalidation.h"
63 #include "RadioInputType.h"
64 #include "RangeInputType.h"
65 #include "RenderElement.h"
66 #include "RenderTheme.h"
67 #include "ResetInputType.h"
68 #include "ScopedEventQueue.h"
69 #include "SearchInputType.h"
70 #include "SelectionRestorationMode.h"
71 #include "Settings.h"
72 #include "ShadowRoot.h"
73 #include "StepRange.h"
74 #include "SubmitInputType.h"
75 #include "TelephoneInputType.h"
76 #include "TextControlInnerElements.h"
77 #include "TextInputType.h"
78 #include "TimeInputType.h"
79 #include "URLInputType.h"
80 #include "WeekInputType.h"
81 #include <limits>
82 #include <wtf/Assertions.h>
83 #include <wtf/RobinHoodHashMap.h>
84 #include <wtf/text/StringHash.h>
85 #include <wtf/text/TextBreakIterator.h>
86
87 namespace WebCore {
88
89 using namespace HTMLNames;
90
91 typedef bool (Settings::*InputTypeConditionalFunction)() const;
92 typedef const AtomString& (*InputTypeNameFunction)();
93 typedef Ref<InputType> (*InputTypeFactoryFunction)(HTMLInputElement&);
94 typedef MemoryCompactLookupOnlyRobinHoodHashMap<AtomString, std::pair<InputTypeConditionalFunction, InputTypeFactoryFunction>> InputTypeFactoryMap;
95
96 template<class T> static Ref<InputType> createInputType(HTMLInputElement& element)
97 {
98     return adoptRef(*new T(element));
99 }
100
101 static InputTypeFactoryMap createInputTypeFactoryMap()
102 {
103     static const struct InputTypes {
104         InputTypeConditionalFunction conditionalFunction;
105         InputTypeNameFunction nameFunction;
106         InputTypeFactoryFunction factoryFunction;
107     } inputTypes[] = {
108         { nullptr, &InputTypeNames::button, &createInputType<ButtonInputType> },
109         { nullptr, &InputTypeNames::checkbox, &createInputType<CheckboxInputType> },
110 #if ENABLE(INPUT_TYPE_COLOR)
111         { &Settings::inputTypeColorEnabled, &InputTypeNames::color, &createInputType<ColorInputType> },
112 #endif
113 #if ENABLE(INPUT_TYPE_DATE)
114         { &Settings::inputTypeDateEnabled, &InputTypeNames::date, &createInputType<DateInputType> },
115 #endif
116 #if ENABLE(INPUT_TYPE_DATETIMELOCAL)
117         { &Settings::inputTypeDateTimeLocalEnabled, &InputTypeNames::datetimelocal, &createInputType<DateTimeLocalInputType> },
118 #endif
119         { nullptr, &InputTypeNames::email, &createInputType<EmailInputType> },
120         { nullptr, &InputTypeNames::file, &createInputType<FileInputType> },
121         { nullptr, &InputTypeNames::hidden, &createInputType<HiddenInputType> },
122         { nullptr, &InputTypeNames::image, &createInputType<ImageInputType> },
123 #if ENABLE(INPUT_TYPE_MONTH)
124         { &Settings::inputTypeMonthEnabled, &InputTypeNames::month, &createInputType<MonthInputType> },
125 #endif
126         { nullptr, &InputTypeNames::number, &createInputType<NumberInputType> },
127         { nullptr, &InputTypeNames::password, &createInputType<PasswordInputType> },
128         { nullptr, &InputTypeNames::radio, &createInputType<RadioInputType> },
129         { nullptr, &InputTypeNames::range, &createInputType<RangeInputType> },
130         { nullptr, &InputTypeNames::reset, &createInputType<ResetInputType> },
131         { nullptr, &InputTypeNames::search, &createInputType<SearchInputType> },
132         { nullptr, &InputTypeNames::submit, &createInputType<SubmitInputType> },
133         { nullptr, &InputTypeNames::telephone, &createInputType<TelephoneInputType> },
134         { nullptr, &InputTypeNames::text, &createInputType<TextInputType> },
135 #if ENABLE(INPUT_TYPE_TIME)
136         { &Settings::inputTypeTimeEnabled, &InputTypeNames::time, &createInputType<TimeInputType> },
137 #endif
138         { nullptr, &InputTypeNames::url, &createInputType<URLInputType> },
139 #if ENABLE(INPUT_TYPE_WEEK)
140         { &Settings::inputTypeWeekEnabled, &InputTypeNames::week, &createInputType<WeekInputType> },
141 #endif
142     };
143
144     InputTypeFactoryMap map;
145     for (auto& inputType : inputTypes)
146         map.add(inputType.nameFunction(), std::make_pair(inputType.conditionalFunction, inputType.factoryFunction));
147     return map;
148 }
149
150 static inline std::pair<InputTypeConditionalFunction, InputTypeFactoryFunction> findFactory(const AtomString& typeName)
151 {
152     static NeverDestroyed factoryMap = createInputTypeFactoryMap();
153     auto factory = factoryMap.get().get(typeName);
154     if (UNLIKELY(!factory.second))
155         factory = factoryMap.get().get(typeName.convertToASCIILowercase());
156     return factory;
157 }
158
159 Ref<InputType> InputType::create(HTMLInputElement& element, const AtomString& typeName)
160 {
161     if (!typeName.isEmpty()) {
162         auto [conditional, factory] = findFactory(typeName);
163         if (LIKELY(factory && (!conditional || std::invoke(conditional, element.document().settings()))))
164             return factory(element);
165     }
166     return adoptRef(*new TextInputType(element));
167 }
168
169 Ref<InputType> InputType::createText(HTMLInputElement& element)
170 {
171     return adoptRef(*new TextInputType(element));
172 }
173
174 InputType::~InputType() = default;
175
176 bool InputType::themeSupportsDataListUI(InputType* type)
177 {
178     return RenderTheme::singleton().supportsDataListUI(type->formControlType());
179 }
180
181 template<typename T> static bool validateInputType(const T& inputType, const String& value)
182 {
183     ASSERT(inputType.canSetStringValue());
184     return !inputType.typeMismatchFor(value)
185         && !inputType.stepMismatch(value)
186         && !inputType.rangeUnderflow(value)
187         && !inputType.rangeOverflow(value)
188         && !inputType.patternMismatch(value)
189         && !inputType.valueMissing(value);
190 }
191
192 bool InputType::isValidValue(const String& value) const
193 {
194     switch (m_type) {
195     case Type::Button:
196         return validateInputType(downcast<ButtonInputType>(*this), value);
197     case Type::Checkbox:
198         return validateInputType(downcast<CheckboxInputType>(*this), value);
199 #if ENABLE(INPUT_TYPE_COLOR)
200     case Type::Color:
201         return validateInputType(downcast<ColorInputType>(*this), value);
202 #endif
203 #if ENABLE(INPUT_TYPE_DATE)
204     case Type::Date:
205         return validateInputType(downcast<DateInputType>(*this), value);
206 #endif
207 #if ENABLE(INPUT_TYPE_DATETIMELOCAL)
208     case Type::DateTimeLocal:
209         return validateInputType(downcast<DateTimeLocalInputType>(*this), value);
210 #endif
211     case Type::Email:
212         return validateInputType(downcast<EmailInputType>(*this), value);
213     case Type::File:
214         return validateInputType(downcast<FileInputType>(*this), value);
215     case Type::Hidden:
216         return validateInputType(downcast<HiddenInputType>(*this), value);
217     case Type::Image:
218         return validateInputType(downcast<ImageInputType>(*this), value);
219 #if ENABLE(INPUT_TYPE_MONTH)
220     case Type::Month:
221         return validateInputType(downcast<MonthInputType>(*this), value);
222 #endif
223     case Type::Number:
224         return validateInputType(downcast<NumberInputType>(*this), value);
225     case Type::Password:
226         return validateInputType(downcast<PasswordInputType>(*this), value);
227     case Type::Radio:
228         return validateInputType(downcast<RadioInputType>(*this), value);
229     case Type::Range:
230         return validateInputType(downcast<RangeInputType>(*this), value);
231     case Type::Reset:
232         return validateInputType(downcast<ResetInputType>(*this), value);
233     case Type::Search:
234         return validateInputType(downcast<SearchInputType>(*this), value);
235     case Type::Submit:
236         return validateInputType(downcast<SubmitInputType>(*this), value);
237     case Type::Telephone:
238         return validateInputType(downcast<TelephoneInputType>(*this), value);
239 #if ENABLE(INPUT_TYPE_TIME)
240     case Type::Time:
241         return validateInputType(downcast<TimeInputType>(*this), value);
242 #endif
243     case Type::URL:
244         return validateInputType(downcast<URLInputType>(*this), value);
245 #if ENABLE(INPUT_TYPE_WEEK)
246     case Type::Week:
247         return validateInputType(downcast<WeekInputType>(*this), value);
248 #endif
249     case Type::Text:
250         return validateInputType(downcast<TextInputType>(*this), value);
251     }
252     ASSERT_NOT_REACHED();
253     return false;
254 }
255
256 bool InputType::shouldSaveAndRestoreFormControlState() const
257 {
258     return true;
259 }
260
261 FormControlState InputType::saveFormControlState() const
262 {
263     ASSERT(element());
264     auto currentValue = element()->value();
265     if (currentValue == element()->defaultValue())
266         return { };
267     return { { AtomString { currentValue } } };
268 }
269
270 void InputType::restoreFormControlState(const FormControlState& state)
271 {
272     ASSERT(element());
273     element()->setValue(state[0]);
274 }
275
276 bool InputType::isFormDataAppendable() const
277 {
278     ASSERT(element());
279     // There is no form data unless there's a name for non-image types.
280     return !element()->name().isEmpty();
281 }
282
283 bool InputType::appendFormData(DOMFormData& formData) const
284 {
285     ASSERT(element());
286     // Always successful.
287     formData.append(element()->name(), element()->value());
288     return true;
289 }
290
291 WallTime InputType::valueAsDate() const
292 {
293     return WallTime::nan();
294 }
295
296 ExceptionOr<void> InputType::setValueAsDate(WallTime) const
297 {
298     return Exception { InvalidStateError };
299 }
300
301 double InputType::valueAsDouble() const
302 {
303     return std::numeric_limits<double>::quiet_NaN();
304 }
305
306 ExceptionOr<void> InputType::setValueAsDouble(double doubleValue, TextFieldEventBehavior eventBehavior) const
307 {
308     return setValueAsDecimal(Decimal::fromDouble(doubleValue), eventBehavior);
309 }
310
311 ExceptionOr<void> InputType::setValueAsDecimal(const Decimal&, TextFieldEventBehavior) const
312 {
313     return Exception { InvalidStateError };
314 }
315
316 bool InputType::typeMismatchFor(const String&) const
317 {
318     return false;
319 }
320
321 bool InputType::typeMismatch() const
322 {
323     return false;
324 }
325
326 bool InputType::supportsRequired() const
327 {
328     // Almost all validatable types support @required.
329     return supportsValidation();
330 }
331
332 bool InputType::valueMissing(const String&) const
333 {
334     return false;
335 }
336
337 bool InputType::hasBadInput() const
338 {
339     return false;
340 }
341
342 bool InputType::patternMismatch(const String&) const
343 {
344     return false;
345 }
346
347 bool InputType::rangeUnderflow(const String& value) const
348 {
349     if (!isSteppable())
350         return false;
351
352     const Decimal numericValue = parseToNumberOrNaN(value);
353     if (!numericValue.isFinite())
354         return false;
355
356     auto range = createStepRange(AnyStepHandling::Reject);
357
358     if (range.isReversible() && range.maximum() < range.minimum())
359         return numericValue > range.maximum() && numericValue < range.minimum();
360
361     return numericValue < range.minimum();
362 }
363
364 bool InputType::rangeOverflow(const String& value) const
365 {
366     if (!isSteppable())
367         return false;
368
369     const Decimal numericValue = parseToNumberOrNaN(value);
370     if (!numericValue.isFinite())
371         return false;
372
373     auto range = createStepRange(AnyStepHandling::Reject);
374
375     if (range.isReversible() && range.maximum() < range.minimum())
376         return numericValue > range.maximum() && numericValue < range.minimum();
377
378     return numericValue > range.maximum();
379 }
380
381 bool InputType::isInvalid(const String& value) const
382 {
383     switch (m_type) {
384     case Type::Button:
385         return isInvalidInputType<ButtonInputType>(*this, value);
386     case Type::Checkbox:
387         return isInvalidInputType<CheckboxInputType>(*this, value);
388     case Type::Color:
389 #if ENABLE(INPUT_TYPE_COLOR)
390         return isInvalidInputType<ColorInputType>(*this, value);
391 #else
392         return false;
393 #endif
394     case Type::Date:
395 #if ENABLE(INPUT_TYPE_DATE)
396         return isInvalidInputType<DateInputType>(*this, value);
397 #else
398         return false;
399 #endif
400     case Type::DateTimeLocal:
401 #if ENABLE(INPUT_TYPE_DATETIMELOCAL)
402         return isInvalidInputType<DateTimeLocalInputType>(*this, value);
403 #else
404         return false;
405 #endif
406     case Type::Email:
407         return isInvalidInputType<EmailInputType>(*this, value);
408     case Type::File:
409         return isInvalidInputType<FileInputType>(*this, value);
410     case Type::Hidden:
411         return isInvalidInputType<HiddenInputType>(*this, value);
412     case Type::Image:
413         return isInvalidInputType<ImageInputType>(*this, value);
414     case Type::Month:
415 #if ENABLE(INPUT_TYPE_MONTH)
416         return isInvalidInputType<MonthInputType>(*this, value);
417 #else
418         return false;
419 #endif
420     case Type::Number:
421         return isInvalidInputType<NumberInputType>(*this, value);
422     case Type::Password:
423         return isInvalidInputType<PasswordInputType>(*this, value);
424     case Type::Radio:
425         return isInvalidInputType<RadioInputType>(*this, value);
426     case Type::Range:
427         return isInvalidInputType<RangeInputType>(*this, value);
428     case Type::Reset:
429         return isInvalidInputType<ResetInputType>(*this, value);
430     case Type::Search:
431         return isInvalidInputType<SearchInputType>(*this, value);
432     case Type::Submit:
433         return isInvalidInputType<SubmitInputType>(*this, value);
434     case Type::Telephone:
435         return isInvalidInputType<TelephoneInputType>(*this, value);
436     case Type::Time:
437 #if ENABLE(INPUT_TYPE_TIME)
438         return isInvalidInputType<TimeInputType>(*this, value);
439 #else
440         return false;
441 #endif
442     case Type::URL:
443         return isInvalidInputType<URLInputType>(*this, value);
444     case Type::Week:
445 #if ENABLE(INPUT_TYPE_WEEK)
446         return isInvalidInputType<WeekInputType>(*this, value);
447 #else
448         return false;
449 #endif
450     case Type::Text:
451         return isInvalidInputType<TextInputType>(*this, value);
452     }
453     ASSERT_NOT_REACHED();
454     return false;
455 }
456
457 Decimal InputType::defaultValueForStepUp() const
458 {
459     return 0;
460 }
461
462 double InputType::minimum() const
463 {
464     return createStepRange(AnyStepHandling::Reject).minimum().toDouble();
465 }
466
467 double InputType::maximum() const
468 {
469     return createStepRange(AnyStepHandling::Reject).maximum().toDouble();
470 }
471
472 bool InputType::sizeShouldIncludeDecoration(int, int& preferredSize) const
473 {
474     ASSERT(element());
475     preferredSize = element()->size();
476     return false;
477 }
478
479 float InputType::decorationWidth() const
480 {
481     return 0;
482 }
483
484 bool InputType::isInRange(const String& value) const
485 {
486     if (!isSteppable())
487         return false;
488
489     StepRange stepRange(createStepRange(AnyStepHandling::Reject));
490     if (!stepRange.hasRangeLimitations())
491         return false;
492     
493     const Decimal numericValue = parseToNumberOrNaN(value);
494     if (!numericValue.isFinite())
495         return true;
496
497     return numericValue >= stepRange.minimum() && numericValue <= stepRange.maximum();
498 }
499
500 bool InputType::isOutOfRange(const String& value) const
501 {
502     if (!isSteppable() || value.isEmpty())
503         return false;
504
505     StepRange stepRange(createStepRange(AnyStepHandling::Reject));
506     if (!stepRange.hasRangeLimitations())
507         return false;
508
509     const Decimal numericValue = parseToNumberOrNaN(value);
510     if (!numericValue.isFinite())
511         return true;
512
513     return numericValue < stepRange.minimum() || numericValue > stepRange.maximum();
514 }
515
516 bool InputType::stepMismatch(const String& value) const
517 {
518     if (!isSteppable())
519         return false;
520
521     const Decimal numericValue = parseToNumberOrNaN(value);
522     if (!numericValue.isFinite())
523         return false;
524
525     return createStepRange(AnyStepHandling::Reject).stepMismatch(numericValue);
526 }
527
528 String InputType::badInputText() const
529 {
530     ASSERT_NOT_REACHED();
531     return validationMessageTypeMismatchText();
532 }
533
534 String InputType::typeMismatchText() const
535 {
536     return validationMessageTypeMismatchText();
537 }
538
539 String InputType::valueMissingText() const
540 {
541     return validationMessageValueMissingText();
542 }
543
544 String InputType::validationMessage() const
545 {
546     ASSERT(element());
547     String value = element()->value();
548
549     // The order of the following checks is meaningful. e.g. We'd like to show the
550     // badInput message even if the control has other validation errors.
551     if (hasBadInput())
552         return badInputText();
553
554     if (valueMissing(value))
555         return valueMissingText();
556
557     if (typeMismatch())
558         return typeMismatchText();
559
560     if (patternMismatch(value))
561         return validationMessagePatternMismatchText();
562
563     if (element()->tooShort())
564         return validationMessageTooShortText(numGraphemeClusters(value), element()->minLength());
565
566     if (element()->tooLong())
567         return validationMessageTooLongText(numGraphemeClusters(value), element()->effectiveMaxLength());
568
569     if (!isSteppable())
570         return emptyString();
571
572     const Decimal numericValue = parseToNumberOrNaN(value);
573     if (!numericValue.isFinite())
574         return emptyString();
575
576     StepRange stepRange(createStepRange(AnyStepHandling::Reject));
577
578     if (numericValue < stepRange.minimum())
579         return validationMessageRangeUnderflowText(serialize(stepRange.minimum()));
580
581     if (numericValue > stepRange.maximum())
582         return validationMessageRangeOverflowText(serialize(stepRange.maximum()));
583
584     if (stepRange.stepMismatch(numericValue)) {
585         const String stepString = stepRange.hasStep() ? serializeForNumberType(stepRange.step() / stepRange.stepScaleFactor()) : emptyString();
586         return validationMessageStepMismatchText(serialize(stepRange.stepBase()), stepString);
587     }
588
589     return emptyString();
590 }
591
592 void InputType::handleClickEvent(MouseEvent&)
593 {
594 }
595
596 void InputType::handleMouseDownEvent(MouseEvent&)
597 {
598 }
599
600 void InputType::handleDOMActivateEvent(Event&)
601 {
602 }
603
604 bool InputType::allowsShowPickerAcrossFrames()
605 {
606     return false;
607 }
608
609 void InputType::showPicker()
610 {
611 }
612
613 auto InputType::handleKeydownEvent(KeyboardEvent&) -> ShouldCallBaseEventHandler
614 {
615     return ShouldCallBaseEventHandler::Yes;
616 }
617
618 void InputType::handleKeypressEvent(KeyboardEvent&)
619 {
620 }
621
622 void InputType::handleKeyupEvent(KeyboardEvent&)
623 {
624 }
625
626 void InputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent&)
627 {
628 }
629
630 #if ENABLE(TOUCH_EVENTS)
631 void InputType::handleTouchEvent(TouchEvent&)
632 {
633 }
634 #endif
635
636 void InputType::forwardEvent(Event&)
637 {
638 }
639
640 bool InputType::shouldSubmitImplicitly(Event& event)
641 {
642     return is<KeyboardEvent>(event) && event.type() == eventNames().keypressEvent && downcast<KeyboardEvent>(event).charCode() == '\r';
643 }
644
645 RenderPtr<RenderElement> InputType::createInputRenderer(RenderStyle&& style)
646 {
647     ASSERT(element());
648     return RenderPtr<RenderElement>(RenderElement::createFor(*element(), WTFMove(style)));
649 }
650
651 void InputType::blur()
652 {
653     ASSERT(element());
654     element()->defaultBlur();
655 }
656
657 void InputType::createShadowSubtree()
658 {
659 }
660
661 void InputType::destroyShadowSubtree()
662 {
663     ASSERT(element());
664     RefPtr<ShadowRoot> root = element()->userAgentShadowRoot();
665     if (!root)
666         return;
667
668     root->removeChildren();
669 }
670
671 Decimal InputType::parseToNumber(const String&, const Decimal& defaultValue) const
672 {
673     ASSERT_NOT_REACHED();
674     return defaultValue;
675 }
676
677 Decimal InputType::parseToNumberOrNaN(const String& string) const
678 {
679     return parseToNumber(string, Decimal::nan());
680 }
681
682 String InputType::serialize(const Decimal&) const
683 {
684     ASSERT_NOT_REACHED();
685     return String();
686 }
687
688 DateComponentsType InputType::dateType() const
689 {
690     return DateComponentsType::Invalid;
691 }
692
693 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent& event) const
694 {
695     ASSERT(element());
696     if (element()->active())
697         element()->dispatchSimulatedClick(&event);
698     event.setDefaultHandled();
699 }
700
701 Chrome* InputType::chrome() const
702 {
703     ASSERT(element());
704     if (Page* page = element()->document().page())
705         return &page->chrome();
706     return nullptr;
707 }
708
709 bool InputType::canSetStringValue() const
710 {
711     return true;
712 }
713
714 bool InputType::hasCustomFocusLogic() const
715 {
716     return true;
717 }
718
719 bool InputType::isKeyboardFocusable(KeyboardEvent* event) const
720 {
721     ASSERT(element());
722     return !element()->isReadOnly() && element()->isTextFormControlKeyboardFocusable(event);
723 }
724
725 bool InputType::isMouseFocusable() const
726 {
727     ASSERT(element());
728     return element()->isTextFormControlMouseFocusable();
729 }
730
731 bool InputType::shouldUseInputMethod() const
732 {
733     return false;
734 }
735
736 void InputType::handleFocusEvent(Node*, FocusDirection)
737 {
738 }
739
740 void InputType::handleBlurEvent()
741 {
742 }
743
744 bool InputType::accessKeyAction(bool)
745 {
746     ASSERT(element());
747     element()->focus({ SelectionRestorationMode::SelectAll });
748     return false;
749 }
750
751 void InputType::addSearchResult()
752 {
753 }
754
755 void InputType::attach()
756 {
757 }
758
759 void InputType::detach()
760 {
761 }
762
763 bool InputType::shouldRespectAlignAttribute()
764 {
765     return false;
766 }
767
768 bool InputType::canBeSuccessfulSubmitButton()
769 {
770     return false;
771 }
772
773 HTMLElement* InputType::placeholderElement() const
774 {
775     return nullptr;
776 }
777
778 bool InputType::rendererIsNeeded()
779 {
780     return true;
781 }
782
783 String InputType::fallbackValue() const
784 {
785     return String();
786 }
787
788 String InputType::defaultValue() const
789 {
790     return String();
791 }
792
793 bool InputType::shouldSendChangeEventAfterCheckedChanged()
794 {
795     return true;
796 }
797
798 bool InputType::storesValueSeparateFromAttribute()
799 {
800     return true;
801 }
802
803 void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior, TextControlSetValueSelection)
804 {
805     ASSERT(element());
806     if (!valueChanged) {
807         element()->setValueInternal(sanitizedValue, eventBehavior);
808         return;
809     }
810
811     bool wasInRange = isInRange(element()->value());
812     bool inRange = isInRange(sanitizedValue);
813
814     bool dummy;
815     auto oldDirection = element()->directionalityIfhasDirAutoAttribute(dummy);
816
817     std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
818     if (wasInRange != inRange)
819         emplace(styleInvalidation, *element(), { { CSSSelector::PseudoClassInRange, inRange }, { CSSSelector::PseudoClassOutOfRange, !inRange } });
820
821     element()->setValueInternal(sanitizedValue, eventBehavior);
822
823     if (oldDirection != element()->directionalityIfhasDirAutoAttribute(dummy))
824         element()->invalidateStyleInternal();
825
826     switch (eventBehavior) {
827     case DispatchChangeEvent:
828         element()->dispatchFormControlChangeEvent();
829         break;
830     case DispatchInputAndChangeEvent:
831         element()->dispatchFormControlInputEvent();
832         if (auto element = this->element())
833             element->dispatchFormControlChangeEvent();
834         break;
835     case DispatchNoEvent:
836         break;
837     }
838
839     if (isRangeControl()) {
840         if (auto* cache = element()->document().existingAXObjectCache())
841             cache->postNotification(element(), AXObjectCache::AXValueChanged);
842     }
843 }
844
845 void InputType::willDispatchClick(InputElementClickState&)
846 {
847 }
848
849 void InputType::didDispatchClick(Event&, const InputElementClickState&)
850 {
851 }
852
853 String InputType::localizeValue(const String& proposedValue) const
854 {
855     return proposedValue;
856 }
857
858 String InputType::visibleValue() const
859 {
860     ASSERT(element());
861     return element()->value();
862 }
863
864 bool InputType::isEmptyValue() const
865 {
866     return true;
867 }
868
869 String InputType::sanitizeValue(const String& proposedValue) const
870 {
871     return proposedValue;
872 }
873
874 #if ENABLE(DRAG_SUPPORT)
875
876 bool InputType::receiveDroppedFiles(const DragData&)
877 {
878     ASSERT_NOT_REACHED();
879     return false;
880 }
881
882 #endif
883
884 Icon* InputType::icon() const
885 {
886     ASSERT_NOT_REACHED();
887     return nullptr;
888 }
889
890 String InputType::displayString() const
891 {
892     ASSERT_NOT_REACHED();
893     return String();
894 }
895
896 bool InputType::shouldResetOnDocumentActivation()
897 {
898     return false;
899 }
900
901 bool InputType::shouldRespectListAttribute()
902 {
903     return false;
904 }
905
906 bool InputType::isInteractiveContent() const
907 {
908     return m_type != Type::Hidden;
909 }
910
911 bool InputType::supportLabels() const
912 {
913     return m_type != Type::Hidden;
914 }
915
916 bool InputType::isEnumeratable() const
917 {
918     return m_type != Type::Image;
919 }
920
921 bool InputType::shouldRespectHeightAndWidthAttributes()
922 {
923     return false;
924 }
925
926 bool InputType::supportsPlaceholder() const
927 {
928     return false;
929 }
930
931 bool InputType::supportsReadOnly() const
932 {
933     return false;
934 }
935
936 void InputType::updateInnerTextValue()
937 {
938 }
939
940 void InputType::updatePlaceholderText()
941 {
942 }
943
944 void InputType::capsLockStateMayHaveChanged()
945 {
946 }
947
948 void InputType::updateAutoFillButton()
949 {
950 }
951
952 void InputType::subtreeHasChanged()
953 {
954     ASSERT_NOT_REACHED();
955 }
956
957 #if ENABLE(TOUCH_EVENTS)
958 bool InputType::hasTouchEventHandler() const
959 {
960     return false;
961 }
962 #endif
963
964 String InputType::defaultToolTip() const
965 {
966     return String();
967 }
968
969 #if ENABLE(DATALIST_ELEMENT)
970 void InputType::dataListMayHaveChanged()
971 {
972 }
973
974 std::optional<Decimal> InputType::findClosestTickMarkValue(const Decimal&)
975 {
976     ASSERT_NOT_REACHED();
977     return std::nullopt;
978 }
979 #endif
980
981 bool InputType::matchesIndeterminatePseudoClass() const
982 {
983     return false;
984 }
985
986 bool InputType::shouldAppearIndeterminate() const
987 {
988     return false;
989 }
990
991 bool InputType::isPresentingAttachedView() const
992 {
993     return false;
994 }
995
996 bool InputType::supportsSelectionAPI() const
997 {
998     return false;
999 }
1000
1001 unsigned InputType::height() const
1002 {
1003     return 0;
1004 }
1005
1006 unsigned InputType::width() const
1007 {
1008     return 0;
1009 }
1010
1011 ExceptionOr<void> InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior)
1012 {
1013     // https://html.spec.whatwg.org/C/#dom-input-stepup
1014
1015     StepRange stepRange(createStepRange(anyStepHandling));
1016     if (!stepRange.hasStep())
1017         return Exception { InvalidStateError };
1018
1019     // 3. If the element has a minimum and a maximum and the minimum is greater than the maximum, then abort these steps.
1020     if (stepRange.minimum() > stepRange.maximum())
1021         return { };
1022     
1023     // 4. If the element has a minimum and a maximum and there is no value greater than or equal to the element's minimum and less than or equal to
1024     // the element's maximum that, when subtracted from the step base, is an integral multiple of the allowed value step, then abort these steps.
1025     Decimal alignedMaximum = stepRange.stepSnappedMaximum();
1026     if (!alignedMaximum.isFinite())
1027         return { };
1028
1029     ASSERT(element());
1030     const Decimal current = parseToNumber(element()->value(), 0);
1031     Decimal base = stepRange.stepBase();
1032     Decimal step = stepRange.step();
1033     Decimal newValue = current;
1034
1035     newValue = newValue + stepRange.step() * Decimal::fromDouble(count);
1036     const AtomString& stepString = element()->getAttribute(HTMLNames::stepAttr);
1037     if (!equalLettersIgnoringASCIICase(stepString, "any"_s))
1038         newValue = stepRange.alignValueForStep(current, newValue);
1039
1040     // 8. If the element has a minimum, and value is less than that minimum, then set value to the smallest value that, when subtracted from the step
1041     // base, is an integral multiple of the allowed value step, and that is more than or equal to minimum.
1042     if (newValue < stepRange.minimum()) {
1043         const Decimal alignedMinimum = base + ((stepRange.minimum() - base) / step).ceiling() * step;
1044         ASSERT(alignedMinimum >= stepRange.minimum());
1045         newValue = alignedMinimum;
1046     }
1047
1048     // 9. If the element has a maximum, and value is greater than that maximum, then set value to the largest value that, when subtracted from the step
1049     // base, is an integral multiple of the allowed value step, and that is less than or equal to maximum.
1050     if (newValue > stepRange.maximum())
1051         newValue = alignedMaximum;
1052
1053     // 10. If either the method invoked was the stepDown() method and value is greater than valueBeforeStepping, or the method invoked was the stepUp()
1054     // method and value is less than valueBeforeStepping, then return.
1055     if ((count < 0 && current < newValue) || (count > 0 && current > newValue))
1056         return { };
1057     
1058     Ref protectedThis { *this };
1059     auto result = setValueAsDecimal(newValue, eventBehavior);
1060     if (result.hasException() || !element())
1061         return result;
1062
1063     if (AXObjectCache* cache = element()->document().existingAXObjectCache())
1064         cache->postNotification(element(), AXObjectCache::AXValueChanged);
1065
1066     return result;
1067 }
1068
1069 bool InputType::getAllowedValueStep(Decimal* step) const
1070 {
1071     StepRange stepRange(createStepRange(AnyStepHandling::Reject));
1072     *step = stepRange.step();
1073     return stepRange.hasStep();
1074 }
1075
1076 StepRange InputType::createStepRange(AnyStepHandling) const
1077 {
1078     ASSERT_NOT_REACHED();
1079     return StepRange();
1080 }
1081
1082 ExceptionOr<void> InputType::stepUp(int n)
1083 {
1084     if (!isSteppable())
1085         return Exception { InvalidStateError };
1086     return applyStep(n, AnyStepHandling::Reject, DispatchNoEvent);
1087 }
1088
1089 void InputType::stepUpFromRenderer(int n)
1090 {
1091     // The differences from stepUp()/stepDown():
1092     //
1093     // Difference 1: the current value
1094     // If the current value is not a number, including empty, the current value is assumed as 0.
1095     //   * If 0 is in-range, and matches to step value
1096     //     - The value should be the +step if n > 0
1097     //     - The value should be the -step if n < 0
1098     //     If -step or +step is out of range, new value should be 0.
1099     //   * If 0 is smaller than the minimum value
1100     //     - The value should be the minimum value for any n
1101     //   * If 0 is larger than the maximum value
1102     //     - The value should be the maximum value for any n
1103     //   * If 0 is in-range, but not matched to step value
1104     //     - The value should be the larger matched value nearest to 0 if n > 0
1105     //       e.g. <input type=number min=-100 step=3> -> 2
1106     //     - The value should be the smaller matched value nearest to 0 if n < 0
1107     //       e.g. <input type=number min=-100 step=3> -> -1
1108     //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
1109     //   As for datetime type, the current value is assumed as "the current date/time in UTC".
1110     // If the current value is smaller than the minimum value:
1111     //  - The value should be the minimum value if n > 0
1112     //  - Nothing should happen if n < 0
1113     // If the current value is larger than the maximum value:
1114     //  - The value should be the maximum value if n < 0
1115     //  - Nothing should happen if n > 0
1116     //
1117     // Difference 2: clamping steps
1118     // If the current value is not matched to step value:
1119     // - The value should be the larger matched value nearest to 0 if n > 0
1120     //   e.g. <input type=number value=3 min=-100 step=3> -> 5
1121     // - The value should be the smaller matched value nearest to 0 if n < 0
1122     //   e.g. <input type=number value=3 min=-100 step=3> -> 2
1123     //
1124     // n is assumed as -n if step < 0.
1125
1126     ASSERT(isSteppable());
1127     if (!isSteppable())
1128         return;
1129     ASSERT(n);
1130     if (!n)
1131         return;
1132
1133     StepRange stepRange(createStepRange(AnyStepHandling::Default));
1134
1135     // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
1136     // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
1137     if (!stepRange.hasStep())
1138       return;
1139
1140     EventQueueScope scope;
1141     const Decimal step = stepRange.step();
1142
1143     int sign;
1144     if (step > 0)
1145         sign = n;
1146     else if (step < 0)
1147         sign = -n;
1148     else
1149         sign = 0;
1150
1151     ASSERT(element());
1152     String currentStringValue = element()->value();
1153     Decimal current = parseToNumberOrNaN(currentStringValue);
1154     if (!current.isFinite()) {
1155         current = defaultValueForStepUp();
1156         const Decimal nextDiff = step * n;
1157         if (current < stepRange.minimum() - nextDiff)
1158             current = stepRange.minimum() - nextDiff;
1159         if (current > stepRange.maximum() - nextDiff)
1160             current = stepRange.maximum() - nextDiff;
1161         setValueAsDecimal(current, DispatchNoEvent);
1162     }
1163     if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum()))
1164         setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchInputAndChangeEvent);
1165     else {
1166         if (stepMismatch(element()->value())) {
1167             ASSERT(!step.isZero());
1168             const Decimal base = stepRange.stepBase();
1169             Decimal newValue;
1170             if (sign < 0)
1171                 newValue = base + ((current - base) / step).floor() * step;
1172             else if (sign > 0)
1173                 newValue = base + ((current - base) / step).ceiling() * step;
1174             else
1175                 newValue = current;
1176
1177             if (newValue < stepRange.minimum())
1178                 newValue = stepRange.minimum();
1179             if (newValue > stepRange.maximum())
1180                 newValue = stepRange.maximum();
1181
1182             setValueAsDecimal(newValue, n == 1 || n == -1 ? DispatchInputAndChangeEvent : DispatchNoEvent);
1183             if (n > 1)
1184                 applyStep(n - 1, AnyStepHandling::Default, DispatchInputAndChangeEvent);
1185             else if (n < -1)
1186                 applyStep(n + 1, AnyStepHandling::Default, DispatchInputAndChangeEvent);
1187         } else
1188             applyStep(n, AnyStepHandling::Default, DispatchInputAndChangeEvent);
1189     }
1190 }
1191
1192 RefPtr<TextControlInnerTextElement> InputType::innerTextElement() const
1193 {
1194     return nullptr;
1195 }
1196
1197 RefPtr<TextControlInnerTextElement> InputType::innerTextElementCreatingShadowSubtreeIfNeeded()
1198 {
1199     createShadowSubtreeIfNeeded();
1200     return innerTextElement();
1201 }
1202
1203 String InputType::resultForDialogSubmit() const
1204 {
1205     ASSERT(element());
1206     return element()->value();
1207 }
1208
1209 void InputType::createShadowSubtreeIfNeeded()
1210 {
1211     if (m_hasCreatedShadowSubtree || !needsShadowSubtree())
1212         return;
1213     Ref protectedThis { *this };
1214     element()->ensureUserAgentShadowRoot();
1215     m_hasCreatedShadowSubtree = true;
1216     createShadowSubtree();
1217 }
1218
1219 } // namespace WebCore