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