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