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