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