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