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