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