Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / forms / 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 "core/html/forms/InputType.h"
30
31 #include "bindings/core/v8/ExceptionMessages.h"
32 #include "bindings/core/v8/ExceptionState.h"
33 #include "core/InputTypeNames.h"
34 #include "core/accessibility/AXObjectCache.h"
35 #include "core/dom/NodeRenderStyle.h"
36 #include "core/events/KeyboardEvent.h"
37 #include "core/events/ScopedEventQueue.h"
38 #include "core/fileapi/FileList.h"
39 #include "core/frame/FrameHost.h"
40 #include "core/html/FormDataList.h"
41 #include "core/html/HTMLInputElement.h"
42 #include "core/html/HTMLShadowElement.h"
43 #include "core/html/forms/ButtonInputType.h"
44 #include "core/html/forms/CheckboxInputType.h"
45 #include "core/html/forms/ColorChooser.h"
46 #include "core/html/forms/ColorInputType.h"
47 #include "core/html/forms/DateInputType.h"
48 #include "core/html/forms/DateTimeLocalInputType.h"
49 #include "core/html/forms/EmailInputType.h"
50 #include "core/html/forms/FileInputType.h"
51 #include "core/html/forms/FormController.h"
52 #include "core/html/forms/HiddenInputType.h"
53 #include "core/html/forms/ImageInputType.h"
54 #include "core/html/forms/MonthInputType.h"
55 #include "core/html/forms/NumberInputType.h"
56 #include "core/html/forms/PasswordInputType.h"
57 #include "core/html/forms/RadioInputType.h"
58 #include "core/html/forms/RangeInputType.h"
59 #include "core/html/forms/ResetInputType.h"
60 #include "core/html/forms/SearchInputType.h"
61 #include "core/html/forms/SubmitInputType.h"
62 #include "core/html/forms/TelephoneInputType.h"
63 #include "core/html/forms/TextInputType.h"
64 #include "core/html/forms/TimeInputType.h"
65 #include "core/html/forms/URLInputType.h"
66 #include "core/html/forms/WeekInputType.h"
67 #include "core/html/parser/HTMLParserIdioms.h"
68 #include "core/rendering/RenderTheme.h"
69 #include "platform/RuntimeEnabledFeatures.h"
70 #include "platform/text/PlatformLocale.h"
71 #include "platform/text/TextBreakIterator.h"
72
73 namespace blink {
74
75 using blink::WebLocalizedString;
76 using namespace HTMLNames;
77
78 typedef PassRefPtrWillBeRawPtr<InputType> (*InputTypeFactoryFunction)(HTMLInputElement&);
79 typedef HashMap<AtomicString, InputTypeFactoryFunction, CaseFoldingHash> InputTypeFactoryMap;
80
81 static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
82 {
83     OwnPtr<InputTypeFactoryMap> map = adoptPtr(new InputTypeFactoryMap);
84     map->add(InputTypeNames::button, ButtonInputType::create);
85     map->add(InputTypeNames::checkbox, CheckboxInputType::create);
86     map->add(InputTypeNames::color, ColorInputType::create);
87     map->add(InputTypeNames::date, DateInputType::create);
88     map->add(InputTypeNames::datetime_local, DateTimeLocalInputType::create);
89     map->add(InputTypeNames::email, EmailInputType::create);
90     map->add(InputTypeNames::file, FileInputType::create);
91     map->add(InputTypeNames::hidden, HiddenInputType::create);
92     map->add(InputTypeNames::image, ImageInputType::create);
93     map->add(InputTypeNames::month, MonthInputType::create);
94     map->add(InputTypeNames::number, NumberInputType::create);
95     map->add(InputTypeNames::password, PasswordInputType::create);
96     map->add(InputTypeNames::radio, RadioInputType::create);
97     map->add(InputTypeNames::range, RangeInputType::create);
98     map->add(InputTypeNames::reset, ResetInputType::create);
99     map->add(InputTypeNames::search, SearchInputType::create);
100     map->add(InputTypeNames::submit, SubmitInputType::create);
101     map->add(InputTypeNames::tel, TelephoneInputType::create);
102     map->add(InputTypeNames::time, TimeInputType::create);
103     map->add(InputTypeNames::url, URLInputType::create);
104     map->add(InputTypeNames::week, WeekInputType::create);
105     // No need to register "text" because it is the default type.
106     return map.release();
107 }
108
109 static const InputTypeFactoryMap* factoryMap()
110 {
111     static const InputTypeFactoryMap* factoryMap = createInputTypeFactoryMap().leakPtr();
112     return factoryMap;
113 }
114
115 PassRefPtrWillBeRawPtr<InputType> InputType::create(HTMLInputElement& element, const AtomicString& typeName)
116 {
117     InputTypeFactoryFunction factory = typeName.isEmpty() ? 0 : factoryMap()->get(typeName);
118     if (!factory)
119         factory = TextInputType::create;
120     return factory(element);
121 }
122
123 PassRefPtrWillBeRawPtr<InputType> InputType::createText(HTMLInputElement& element)
124 {
125     return TextInputType::create(element);
126 }
127
128 const AtomicString& InputType::normalizeTypeName(const AtomicString& typeName)
129 {
130     if (typeName.isEmpty())
131         return InputTypeNames::text;
132     InputTypeFactoryMap::const_iterator it = factoryMap()->find(typeName);
133     return it == factoryMap()->end() ? InputTypeNames::text : it->key;
134 }
135
136 InputType::~InputType()
137 {
138 }
139
140 bool InputType::isTextField() const
141 {
142     return false;
143 }
144
145 bool InputType::shouldSaveAndRestoreFormControlState() const
146 {
147     return true;
148 }
149
150 FormControlState InputType::saveFormControlState() const
151 {
152     String currentValue = element().value();
153     if (currentValue == element().defaultValue())
154         return FormControlState();
155     return FormControlState(currentValue);
156 }
157
158 void InputType::restoreFormControlState(const FormControlState& state)
159 {
160     element().setValue(state[0]);
161 }
162
163 bool InputType::isFormDataAppendable() const
164 {
165     // There is no form data unless there's a name for non-image types.
166     return !element().name().isEmpty();
167 }
168
169 bool InputType::appendFormData(FormDataList& encoding, bool) const
170 {
171     // Always successful.
172     encoding.appendData(element().name(), element().value());
173     return true;
174 }
175
176 String InputType::resultForDialogSubmit() const
177 {
178     return element().fastGetAttribute(valueAttr);
179 }
180
181 double InputType::valueAsDate() const
182 {
183     return DateComponents::invalidMilliseconds();
184 }
185
186 void InputType::setValueAsDate(double, ExceptionState& exceptionState) const
187 {
188     exceptionState.throwDOMException(InvalidStateError, "This input element does not support Date values.");
189 }
190
191 double InputType::valueAsDouble() const
192 {
193     return std::numeric_limits<double>::quiet_NaN();
194 }
195
196 void InputType::setValueAsDouble(double doubleValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const
197 {
198     exceptionState.throwDOMException(InvalidStateError, "This input element does not support Number values.");
199 }
200
201 void InputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState&) const
202 {
203     element().setValue(serialize(newValue), eventBehavior);
204 }
205
206 bool InputType::supportsValidation() const
207 {
208     return true;
209 }
210
211 bool InputType::typeMismatchFor(const String&) const
212 {
213     return false;
214 }
215
216 bool InputType::typeMismatch() const
217 {
218     return false;
219 }
220
221 bool InputType::supportsRequired() const
222 {
223     // Almost all validatable types support @required.
224     return supportsValidation();
225 }
226
227 bool InputType::valueMissing(const String&) const
228 {
229     return false;
230 }
231
232 bool InputType::hasBadInput() const
233 {
234     return false;
235 }
236
237 bool InputType::tooLong(const String&, HTMLTextFormControlElement::NeedsToCheckDirtyFlag) const
238 {
239     return false;
240 }
241
242 bool InputType::patternMismatch(const String&) const
243 {
244     return false;
245 }
246
247 bool InputType::rangeUnderflow(const String& value) const
248 {
249     if (!isSteppable())
250         return false;
251
252     const Decimal numericValue = parseToNumberOrNaN(value);
253     if (!numericValue.isFinite())
254         return false;
255
256     return numericValue < createStepRange(RejectAny).minimum();
257 }
258
259 bool InputType::rangeOverflow(const String& value) const
260 {
261     if (!isSteppable())
262         return false;
263
264     const Decimal numericValue = parseToNumberOrNaN(value);
265     if (!numericValue.isFinite())
266         return false;
267
268     return numericValue > createStepRange(RejectAny).maximum();
269 }
270
271 Decimal InputType::defaultValueForStepUp() const
272 {
273     return 0;
274 }
275
276 double InputType::minimum() const
277 {
278     return createStepRange(RejectAny).minimum().toDouble();
279 }
280
281 double InputType::maximum() const
282 {
283     return createStepRange(RejectAny).maximum().toDouble();
284 }
285
286 bool InputType::isInRange(const String& value) const
287 {
288     if (!isSteppable())
289         return false;
290
291     const Decimal numericValue = parseToNumberOrNaN(value);
292     if (!numericValue.isFinite())
293         return true;
294
295     StepRange stepRange(createStepRange(RejectAny));
296     return numericValue >= stepRange.minimum() && numericValue <= stepRange.maximum();
297 }
298
299 bool InputType::isOutOfRange(const String& value) const
300 {
301     if (!isSteppable())
302         return false;
303
304     const Decimal numericValue = parseToNumberOrNaN(value);
305     if (!numericValue.isFinite())
306         return true;
307
308     StepRange stepRange(createStepRange(RejectAny));
309     return numericValue < stepRange.minimum() || numericValue > stepRange.maximum();
310 }
311
312 bool InputType::stepMismatch(const String& value) const
313 {
314     if (!isSteppable())
315         return false;
316
317     const Decimal numericValue = parseToNumberOrNaN(value);
318     if (!numericValue.isFinite())
319         return false;
320
321     return createStepRange(RejectAny).stepMismatch(numericValue);
322 }
323
324 String InputType::badInputText() const
325 {
326     ASSERT_NOT_REACHED();
327     return locale().queryString(WebLocalizedString::ValidationTypeMismatch);
328 }
329
330 String InputType::rangeOverflowText(const Decimal&) const
331 {
332     ASSERT_NOT_REACHED();
333     return String();
334 }
335
336 String InputType::rangeUnderflowText(const Decimal&) const
337 {
338     ASSERT_NOT_REACHED();
339     return String();
340 }
341
342 String InputType::typeMismatchText() const
343 {
344     return locale().queryString(WebLocalizedString::ValidationTypeMismatch);
345 }
346
347 String InputType::valueMissingText() const
348 {
349     return locale().queryString(WebLocalizedString::ValidationValueMissing);
350 }
351
352 String InputType::validationMessage() const
353 {
354     const String value = element().value();
355
356     // The order of the following checks is meaningful. e.g. We'd like to show the
357     // badInput message even if the control has other validation errors.
358     if (hasBadInput())
359         return badInputText();
360
361     if (valueMissing(value))
362         return valueMissingText();
363
364     if (typeMismatch())
365         return typeMismatchText();
366
367     if (patternMismatch(value))
368         return locale().queryString(WebLocalizedString::ValidationPatternMismatch);
369
370     if (element().tooLong())
371         return locale().validationMessageTooLongText(value.length(), element().maxLength());
372
373     if (!isSteppable())
374         return emptyString();
375
376     const Decimal numericValue = parseToNumberOrNaN(value);
377     if (!numericValue.isFinite())
378         return emptyString();
379
380     StepRange stepRange(createStepRange(RejectAny));
381
382     if (numericValue < stepRange.minimum())
383         return rangeUnderflowText(stepRange.minimum());
384
385     if (numericValue > stepRange.maximum())
386         return rangeOverflowText(stepRange.maximum());
387
388     if (stepRange.stepMismatch(numericValue)) {
389         ASSERT(stepRange.hasStep());
390         Decimal candidate1 = stepRange.clampValue(numericValue);
391         String localizedCandidate1 = localizeValue(serialize(candidate1));
392         Decimal candidate2 = candidate1 < numericValue ? candidate1 + stepRange.step() : candidate1 - stepRange.step();
393         if (!candidate2.isFinite() || candidate2 < stepRange.minimum() || candidate2 > stepRange.maximum())
394             return locale().queryString(WebLocalizedString::ValidationStepMismatchCloseToLimit, localizedCandidate1);
395         String localizedCandidate2 = localizeValue(serialize(candidate2));
396         if (candidate1 < candidate2)
397             return locale().queryString(WebLocalizedString::ValidationStepMismatch, localizedCandidate1, localizedCandidate2);
398         return locale().queryString(WebLocalizedString::ValidationStepMismatch, localizedCandidate2, localizedCandidate1);
399     }
400
401     return emptyString();
402 }
403
404 bool InputType::shouldSubmitImplicitly(Event* event)
405 {
406     return event->isKeyboardEvent() && event->type() == EventTypeNames::keypress && toKeyboardEvent(event)->charCode() == '\r';
407 }
408
409 Decimal InputType::parseToNumber(const String&, const Decimal& defaultValue) const
410 {
411     ASSERT_NOT_REACHED();
412     return defaultValue;
413 }
414
415 Decimal InputType::parseToNumberOrNaN(const String& string) const
416 {
417     return parseToNumber(string, Decimal::nan());
418 }
419
420 String InputType::serialize(const Decimal&) const
421 {
422     ASSERT_NOT_REACHED();
423     return String();
424 }
425
426 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const
427 {
428     if (element().active())
429         element().dispatchSimulatedClick(event);
430     event->setDefaultHandled();
431 }
432
433 Chrome* InputType::chrome() const
434 {
435     if (FrameHost* host = element().document().frameHost())
436         return &host->chrome();
437     return 0;
438 }
439
440 Locale& InputType::locale() const
441 {
442     return element().locale();
443 }
444
445 bool InputType::canSetStringValue() const
446 {
447     return true;
448 }
449
450 bool InputType::hasCustomFocusLogic() const
451 {
452     return true;
453 }
454
455 bool InputType::isKeyboardFocusable() const
456 {
457     return element().isFocusable();
458 }
459
460 bool InputType::shouldShowFocusRingOnMouseFocus() const
461 {
462     return false;
463 }
464
465 void InputType::enableSecureTextInput()
466 {
467 }
468
469 void InputType::disableSecureTextInput()
470 {
471 }
472
473 void InputType::accessKeyAction(bool)
474 {
475     element().focus(false);
476 }
477
478 void InputType::countUsage()
479 {
480 }
481
482 bool InputType::shouldRespectAlignAttribute()
483 {
484     return false;
485 }
486
487 void InputType::sanitizeValueInResponseToMinOrMaxAttributeChange()
488 {
489 }
490
491 bool InputType::canBeSuccessfulSubmitButton()
492 {
493     return false;
494 }
495
496 bool InputType::rendererIsNeeded()
497 {
498     return true;
499 }
500
501 FileList* InputType::files()
502 {
503     return 0;
504 }
505
506 void InputType::setFiles(PassRefPtrWillBeRawPtr<FileList>)
507 {
508 }
509
510 bool InputType::getTypeSpecificValue(String&)
511 {
512     return false;
513 }
514
515 String InputType::fallbackValue() const
516 {
517     return String();
518 }
519
520 String InputType::defaultValue() const
521 {
522     return String();
523 }
524
525 bool InputType::canSetSuggestedValue()
526 {
527     return false;
528 }
529
530 bool InputType::shouldSendChangeEventAfterCheckedChanged()
531 {
532     return true;
533 }
534
535 bool InputType::storesValueSeparateFromAttribute()
536 {
537     return true;
538 }
539
540 bool InputType::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue)
541 {
542     return !equalIgnoringNullity(oldValue, newValue);
543 }
544
545 void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
546 {
547     element().setValueInternal(sanitizedValue, eventBehavior);
548     element().setNeedsStyleRecalc(SubtreeStyleChange);
549     if (!valueChanged)
550         return;
551     switch (eventBehavior) {
552     case DispatchChangeEvent:
553         element().dispatchFormControlChangeEvent();
554         break;
555     case DispatchInputAndChangeEvent:
556         element().dispatchFormControlInputEvent();
557         element().dispatchFormControlChangeEvent();
558         break;
559     case DispatchNoEvent:
560         break;
561     }
562 }
563
564 bool InputType::canSetValue(const String&)
565 {
566     return true;
567 }
568
569 String InputType::localizeValue(const String& proposedValue) const
570 {
571     return proposedValue;
572 }
573
574 String InputType::visibleValue() const
575 {
576     return element().value();
577 }
578
579 String InputType::sanitizeValue(const String& proposedValue) const
580 {
581     return proposedValue;
582 }
583
584 void InputType::warnIfValueIsInvalidAndElementIsVisible(const String& value) const
585 {
586     // Don't warn if the value is set in Modernizr.
587     RenderStyle* style = element().renderStyle();
588     if (style && style->visibility() != HIDDEN)
589         warnIfValueIsInvalid(value);
590 }
591
592 void InputType::warnIfValueIsInvalid(const String&) const
593 {
594 }
595
596 bool InputType::receiveDroppedFiles(const DragData*)
597 {
598     ASSERT_NOT_REACHED();
599     return false;
600 }
601
602 String InputType::droppedFileSystemId()
603 {
604     ASSERT_NOT_REACHED();
605     return String();
606 }
607
608 bool InputType::shouldRespectListAttribute()
609 {
610     return false;
611 }
612
613 bool InputType::shouldRespectSpeechAttribute()
614 {
615     return false;
616 }
617
618 bool InputType::isTextButton() const
619 {
620     return false;
621 }
622
623 bool InputType::isInteractiveContent() const
624 {
625     return true;
626 }
627
628 bool InputType::isEnumeratable()
629 {
630     return true;
631 }
632
633 bool InputType::isCheckable()
634 {
635     return false;
636 }
637
638 bool InputType::isSteppable() const
639 {
640     return false;
641 }
642
643 bool InputType::shouldRespectHeightAndWidthAttributes()
644 {
645     return false;
646 }
647
648 int InputType::maxLength() const
649 {
650     return HTMLInputElement::maximumLength;
651 }
652
653 bool InputType::supportsPlaceholder() const
654 {
655     return false;
656 }
657
658 bool InputType::supportsReadOnly() const
659 {
660     return false;
661 }
662
663 String InputType::defaultToolTip() const
664 {
665     return String();
666 }
667
668 Decimal InputType::findClosestTickMarkValue(const Decimal&)
669 {
670     ASSERT_NOT_REACHED();
671     return Decimal::nan();
672 }
673
674 void InputType::handleDOMActivateEvent(Event*)
675 {
676 }
677
678 bool InputType::hasLegalLinkAttribute(const QualifiedName&) const
679 {
680     return false;
681 }
682
683 const QualifiedName& InputType::subResourceAttributeName() const
684 {
685     return QualifiedName::null();
686 }
687
688 bool InputType::shouldAppearIndeterminate() const
689 {
690     return false;
691 }
692
693 bool InputType::supportsInputModeAttribute() const
694 {
695     return false;
696 }
697
698 bool InputType::supportsSelectionAPI() const
699 {
700     return false;
701 }
702
703 unsigned InputType::height() const
704 {
705     return 0;
706 }
707
708 unsigned InputType::width() const
709 {
710     return 0;
711 }
712
713 TextDirection InputType::computedTextDirection()
714 {
715     return element().computedStyle()->direction();
716 }
717
718 ColorChooserClient* InputType::colorChooserClient()
719 {
720     return 0;
721 }
722
723 void InputType::applyStep(const Decimal& current, int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState)
724 {
725     StepRange stepRange(createStepRange(anyStepHandling));
726     if (!stepRange.hasStep()) {
727         exceptionState.throwDOMException(InvalidStateError, "This form element does not have an allowed value step.");
728         return;
729     }
730
731     EventQueueScope scope;
732     const Decimal step = stepRange.step();
733
734     const AtomicString& stepString = element().fastGetAttribute(stepAttr);
735     if (!equalIgnoringCase(stepString, "any") && stepRange.stepMismatch(current)) {
736         // Snap-to-step / clamping steps
737         // If the current value is not matched to step value:
738         // - The value should be the larger matched value nearest to 0 if count > 0
739         //   e.g. <input type=number value=3 min=-100 step=3> -> 5
740         // - The value should be the smaller matched value nearest to 0 if count < 0
741         //   e.g. <input type=number value=3 min=-100 step=3> -> 2
742         //
743
744         ASSERT(!step.isZero());
745         Decimal newValue;
746         const Decimal base = stepRange.stepBase();
747         if (count < 0)
748             newValue = base + ((current - base) / step).floor() * step;
749         else if (count > 0)
750             newValue = base + ((current - base) / step).ceiling() * step;
751         else
752             newValue = current;
753
754         if (newValue < stepRange.minimum())
755             newValue = stepRange.minimum();
756         if (newValue > stepRange.maximum())
757             newValue = stepRange.maximum();
758
759         setValueAsDecimal(newValue, count == 1 || count == -1 ? DispatchChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION);
760         if (count > 1) {
761             applyStep(newValue, count - 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
762             return;
763         }
764         if (count < -1) {
765             applyStep(newValue, count + 1, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
766             return;
767         }
768     } else {
769         Decimal newValue = current + stepRange.step() * count;
770
771         if (!equalIgnoringCase(stepString, "any"))
772             newValue = stepRange.alignValueForStep(current, newValue);
773
774         if (newValue > stepRange.maximum())
775             newValue = newValue - stepRange.step();
776         else if (newValue < stepRange.minimum())
777             newValue = newValue + stepRange.step();
778
779         setValueAsDecimal(newValue, eventBehavior, exceptionState);
780     }
781     if (AXObjectCache* cache = element().document().existingAXObjectCache())
782         cache->postNotification(&element(), AXObjectCache::AXValueChanged, true);
783 }
784
785 bool InputType::getAllowedValueStep(Decimal* step) const
786 {
787     StepRange stepRange(createStepRange(RejectAny));
788     *step = stepRange.step();
789     return stepRange.hasStep();
790 }
791
792 StepRange InputType::createStepRange(AnyStepHandling) const
793 {
794     ASSERT_NOT_REACHED();
795     return StepRange();
796 }
797
798 void InputType::stepUp(int n, ExceptionState& exceptionState)
799 {
800     if (!isSteppable()) {
801         exceptionState.throwDOMException(InvalidStateError, "This form element is not steppable.");
802         return;
803     }
804     const Decimal current = parseToNumber(element().value(), 0);
805     applyStep(current, n, RejectAny, DispatchNoEvent, exceptionState);
806 }
807
808 void InputType::stepUpFromRenderer(int n)
809 {
810     // The only difference from stepUp()/stepDown() is the extra treatment
811     // of the current value before applying the step:
812     //
813     // If the current value is not a number, including empty, the current value is assumed as 0.
814     //   * If 0 is in-range, and matches to step value
815     //     - The value should be the +step if n > 0
816     //     - The value should be the -step if n < 0
817     //     If -step or +step is out of range, new value should be 0.
818     //   * If 0 is smaller than the minimum value
819     //     - The value should be the minimum value for any n
820     //   * If 0 is larger than the maximum value
821     //     - The value should be the maximum value for any n
822     //   * If 0 is in-range, but not matched to step value
823     //     - The value should be the larger matched value nearest to 0 if n > 0
824     //       e.g. <input type=number min=-100 step=3> -> 2
825     //     - The value should be the smaler matched value nearest to 0 if n < 0
826     //       e.g. <input type=number min=-100 step=3> -> -1
827     //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
828     //   As for datetime type, the current value is assumed as "the current date/time in UTC".
829     // If the current value is smaller than the minimum value:
830     //  - The value should be the minimum value if n > 0
831     //  - Nothing should happen if n < 0
832     // If the current value is larger than the maximum value:
833     //  - The value should be the maximum value if n < 0
834     //  - Nothing should happen if n > 0
835     //
836     // n is assumed as -n if step < 0.
837
838     ASSERT(isSteppable());
839     if (!isSteppable())
840         return;
841     ASSERT(n);
842     if (!n)
843         return;
844
845     StepRange stepRange(createStepRange(AnyIsDefaultStep));
846
847     // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
848     // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
849     if (!stepRange.hasStep())
850         return;
851
852     EventQueueScope scope;
853     const Decimal step = stepRange.step();
854
855     int sign;
856     if (step > 0)
857         sign = n;
858     else if (step < 0)
859         sign = -n;
860     else
861         sign = 0;
862
863     Decimal current = parseToNumberOrNaN(element().value());
864     if (!current.isFinite()) {
865         current = defaultValueForStepUp();
866         const Decimal nextDiff = step * n;
867         if (current < stepRange.minimum() - nextDiff)
868             current = stepRange.minimum() - nextDiff;
869         if (current > stepRange.maximum() - nextDiff)
870             current = stepRange.maximum() - nextDiff;
871         setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION);
872     }
873     if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) {
874         setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION);
875         return;
876     }
877     applyStep(current, n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
878 }
879
880 void InputType::countUsageIfVisible(UseCounter::Feature feature) const
881 {
882     if (RenderStyle* style = element().renderStyle()) {
883         if (style->visibility() != HIDDEN)
884             UseCounter::count(element().document(), feature);
885     }
886 }
887
888 Decimal InputType::findStepBase(const Decimal& defaultValue) const
889 {
890     Decimal stepBase = parseToNumber(element().fastGetAttribute(minAttr), Decimal::nan());
891     if (!stepBase.isFinite())
892         stepBase = parseToNumber(element().fastGetAttribute(valueAttr), defaultValue);
893     return stepBase;
894 }
895
896 StepRange InputType::createStepRange(AnyStepHandling anyStepHandling, const Decimal& stepBaseDefault, const Decimal& minimumDefault, const Decimal& maximumDefault, const StepRange::StepDescription& stepDescription) const
897 {
898     const Decimal stepBase = findStepBase(stepBaseDefault);
899     const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), minimumDefault);
900     const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), maximumDefault);
901     const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
902     return StepRange(stepBase, minimum, maximum, step, stepDescription);
903 }
904
905 } // namespace blink