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) 2010 Google Inc. All rights reserved.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB.  If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 *
25 */
26
27#include "config.h"
28#include "HTMLInputElement.h"
29
30#include "AXObjectCache.h"
31#include "Attribute.h"
32#include "BeforeTextInsertedEvent.h"
33#include "CSSPropertyNames.h"
34#include "Document.h"
35#include "EventNames.h"
36#include "ExceptionCode.h"
37#include "FileList.h"
38#include "HTMLCollection.h"
39#include "HTMLDataListElement.h"
40#include "HTMLFormElement.h"
41#include "HTMLNames.h"
42#include "HTMLOptionElement.h"
43#include "HTMLParserIdioms.h"
44#include "InputType.h"
45#include "KeyboardEvent.h"
46#include "LocalizedStrings.h"
47#include "MouseEvent.h"
48#include "PlatformMouseEvent.h"
49#include "RenderTextControlSingleLine.h"
50#include "RenderTheme.h"
51#include "RuntimeEnabledFeatures.h"
52#include "ScriptEventListener.h"
53#include "WheelEvent.h"
54#include <wtf/MathExtras.h>
55#include <wtf/StdLibExtras.h>
56
57#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
58#include "PlatformBridge.h"
59#endif
60
61#if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
62#include "TouchEvent.h"
63#endif
64
65using namespace std;
66
67namespace WebCore {
68
69using namespace HTMLNames;
70
71const int maxSavedResults = 256;
72
73HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
74    : HTMLTextFormControlElement(tagName, document, form)
75    , m_maxResults(-1)
76    , m_isChecked(false)
77    , m_reflectsCheckedAttribute(true)
78    , m_isIndeterminate(false)
79    , m_hasType(false)
80    , m_isActivatedSubmit(false)
81    , m_autocomplete(Uninitialized)
82    , m_isAutofilled(false)
83    , m_stateRestored(false)
84    , m_parsingInProgress(createdByParser)
85    , m_inputType(InputType::createText(this))
86{
87    ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
88}
89
90PassRefPtr<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
91{
92    return adoptRef(new HTMLInputElement(tagName, document, form, createdByParser));
93}
94
95HTMLInputElement::~HTMLInputElement()
96{
97    if (needsActivationCallback())
98        document()->unregisterForDocumentActivationCallbacks(this);
99
100    document()->checkedRadioButtons().removeButton(this);
101
102    // Need to remove this from the form while it is still an HTMLInputElement,
103    // so can't wait for the base class's destructor to do it.
104    removeFromForm();
105}
106
107const AtomicString& HTMLInputElement::formControlName() const
108{
109    return m_data.name();
110}
111
112bool HTMLInputElement::autoComplete() const
113{
114    if (m_autocomplete != Uninitialized)
115        return m_autocomplete == On;
116    return HTMLTextFormControlElement::autoComplete();
117}
118
119void HTMLInputElement::updateCheckedRadioButtons()
120{
121    if (attached() && checked())
122        checkedRadioButtons().addButton(this);
123
124    if (form()) {
125        const Vector<FormAssociatedElement*>& controls = form()->associatedElements();
126        for (unsigned i = 0; i < controls.size(); ++i) {
127            if (!controls[i]->isFormControlElement())
128                continue;
129            HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(controls[i]);
130            if (control->name() != name())
131                continue;
132            if (control->type() != type())
133                continue;
134            control->setNeedsValidityCheck();
135        }
136    } else {
137        // FIXME: Traversing the document is inefficient.
138        for (Node* node = document()->body(); node; node = node->traverseNextNode()) {
139            if (!node->isElementNode())
140                continue;
141            Element* element = static_cast<Element*>(node);
142            if (element->formControlName() != name())
143                continue;
144            if (element->formControlType() != type())
145                continue;
146            HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(element);
147            if (control->form())
148                continue;
149            control->setNeedsValidityCheck();
150        }
151    }
152
153    if (renderer() && renderer()->style()->hasAppearance())
154        renderer()->theme()->stateChanged(renderer(), CheckedState);
155}
156
157bool HTMLInputElement::lastChangeWasUserEdit() const
158{
159    if (!isTextField())
160        return false;
161
162    if (!renderer())
163        return false;
164
165    return toRenderTextControl(renderer())->lastChangeWasUserEdit();
166}
167
168bool HTMLInputElement::isValidValue(const String& value) const
169{
170    if (!m_inputType->canSetStringValue()) {
171        ASSERT_NOT_REACHED();
172        return false;
173    }
174    return !m_inputType->typeMismatchFor(value)
175        && !stepMismatch(value)
176        && !rangeUnderflow(value)
177        && !rangeOverflow(value)
178        && !tooLong(value, IgnoreDirtyFlag)
179        && !patternMismatch(value)
180        && !valueMissing(value);
181}
182
183bool HTMLInputElement::typeMismatch() const
184{
185    return m_inputType->typeMismatch();
186}
187
188bool HTMLInputElement::valueMissing(const String& value) const
189{
190    if (!isRequiredFormControl() || readOnly() || disabled())
191        return false;
192    return m_inputType->valueMissing(value);
193}
194
195bool HTMLInputElement::patternMismatch(const String& value) const
196{
197    return m_inputType->patternMismatch(value);
198}
199
200bool HTMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
201{
202    // We use isTextType() instead of supportsMaxLength() because of the
203    // 'virtual' overhead.
204    if (!isTextType())
205        return false;
206    int max = maxLength();
207    if (max < 0)
208        return false;
209    if (check == CheckDirtyFlag) {
210        // Return false for the default value even if it is longer than maxLength.
211        bool userEdited = !m_data.value().isNull();
212        if (!userEdited)
213            return false;
214    }
215    return numGraphemeClusters(value) > static_cast<unsigned>(max);
216}
217
218bool HTMLInputElement::rangeUnderflow(const String& value) const
219{
220    return m_inputType->rangeUnderflow(value);
221}
222
223bool HTMLInputElement::rangeOverflow(const String& value) const
224{
225    return m_inputType->rangeOverflow(value);
226}
227
228double HTMLInputElement::minimum() const
229{
230    return m_inputType->minimum();
231}
232
233double HTMLInputElement::maximum() const
234{
235    return m_inputType->maximum();
236}
237
238bool HTMLInputElement::stepMismatch(const String& value) const
239{
240    double step;
241    if (!getAllowedValueStep(&step))
242        return false;
243    return m_inputType->stepMismatch(value, step);
244}
245
246String HTMLInputElement::minimumString() const
247{
248    return m_inputType->serialize(minimum());
249}
250
251String HTMLInputElement::maximumString() const
252{
253    return m_inputType->serialize(maximum());
254}
255
256String HTMLInputElement::stepBaseString() const
257{
258    return m_inputType->serialize(m_inputType->stepBase());
259}
260
261String HTMLInputElement::stepString() const
262{
263    double step;
264    if (!getAllowedValueStep(&step)) {
265        // stepString() should be called only if stepMismatch() can be true.
266        ASSERT_NOT_REACHED();
267        return String();
268    }
269    return serializeForNumberType(step / m_inputType->stepScaleFactor());
270}
271
272String HTMLInputElement::typeMismatchText() const
273{
274    return m_inputType->typeMismatchText();
275}
276
277String HTMLInputElement::valueMissingText() const
278{
279    return m_inputType->valueMissingText();
280}
281
282bool HTMLInputElement::getAllowedValueStep(double* step) const
283{
284    return getAllowedValueStepWithDecimalPlaces(step, 0);
285}
286
287bool HTMLInputElement::getAllowedValueStepWithDecimalPlaces(double* step, unsigned* decimalPlaces) const
288{
289    ASSERT(step);
290    double defaultStep = m_inputType->defaultStep();
291    double stepScaleFactor = m_inputType->stepScaleFactor();
292    if (!isfinite(defaultStep) || !isfinite(stepScaleFactor))
293        return false;
294    const AtomicString& stepString = fastGetAttribute(stepAttr);
295    if (stepString.isEmpty()) {
296        *step = defaultStep * stepScaleFactor;
297        if (decimalPlaces)
298            *decimalPlaces = 0;
299        return true;
300    }
301    if (equalIgnoringCase(stepString, "any"))
302        return false;
303    double parsed;
304    if (!decimalPlaces) {
305        if (!parseToDoubleForNumberType(stepString, &parsed) || parsed <= 0.0) {
306            *step = defaultStep * stepScaleFactor;
307            return true;
308        }
309    } else {
310        if (!parseToDoubleForNumberTypeWithDecimalPlaces(stepString, &parsed, decimalPlaces) || parsed <= 0.0) {
311            *step = defaultStep * stepScaleFactor;
312            *decimalPlaces = 0;
313            return true;
314        }
315    }
316    // For date, month, week, the parsed value should be an integer for some types.
317    if (m_inputType->parsedStepValueShouldBeInteger())
318        parsed = max(round(parsed), 1.0);
319    double result = parsed * stepScaleFactor;
320    // For datetime, datetime-local, time, the result should be an integer.
321    if (m_inputType->scaledStepValueShouldBeInteger())
322        result = max(round(result), 1.0);
323    ASSERT(result > 0);
324    *step = result;
325    return true;
326}
327
328void HTMLInputElement::applyStep(double count, ExceptionCode& ec)
329{
330    double step;
331    unsigned stepDecimalPlaces, currentDecimalPlaces;
332    if (!getAllowedValueStepWithDecimalPlaces(&step, &stepDecimalPlaces)) {
333        ec = INVALID_STATE_ERR;
334        return;
335    }
336    const double nan = numeric_limits<double>::quiet_NaN();
337    double current = m_inputType->parseToDoubleWithDecimalPlaces(value(), nan, &currentDecimalPlaces);
338    if (!isfinite(current)) {
339        ec = INVALID_STATE_ERR;
340        return;
341    }
342    double newValue = current + step * count;
343    if (isinf(newValue)) {
344        ec = INVALID_STATE_ERR;
345        return;
346    }
347    double acceptableError = m_inputType->acceptableError(step);
348    if (newValue - m_inputType->minimum() < -acceptableError) {
349        ec = INVALID_STATE_ERR;
350        return;
351    }
352    if (newValue < m_inputType->minimum())
353        newValue = m_inputType->minimum();
354    unsigned baseDecimalPlaces;
355    double base = m_inputType->stepBaseWithDecimalPlaces(&baseDecimalPlaces);
356    baseDecimalPlaces = min(baseDecimalPlaces, 16u);
357    if (newValue < pow(10.0, 21.0)) {
358      if (stepMismatch(value())) {
359            double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, currentDecimalPlaces)));
360            newValue = round(newValue * scale) / scale;
361        } else {
362            double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces)));
363            newValue = round((base + round((newValue - base) / step) * step) * scale) / scale;
364        }
365    }
366    if (newValue - m_inputType->maximum() > acceptableError) {
367        ec = INVALID_STATE_ERR;
368        return;
369    }
370    if (newValue > m_inputType->maximum())
371        newValue = m_inputType->maximum();
372    setValueAsNumber(newValue, ec);
373
374    if (AXObjectCache::accessibilityEnabled())
375         document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
376}
377
378void HTMLInputElement::stepUp(int n, ExceptionCode& ec)
379{
380    applyStep(n, ec);
381}
382
383void HTMLInputElement::stepDown(int n, ExceptionCode& ec)
384{
385    applyStep(-n, ec);
386}
387
388bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
389{
390    if (isTextField())
391        return HTMLFormControlElementWithState::isFocusable();
392    return HTMLFormControlElementWithState::isKeyboardFocusable(event) && m_inputType->isKeyboardFocusable();
393}
394
395bool HTMLInputElement::isMouseFocusable() const
396{
397    if (isTextField())
398        return HTMLFormControlElementWithState::isFocusable();
399    return HTMLFormControlElementWithState::isMouseFocusable();
400}
401
402void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
403{
404    if (isTextField())
405        InputElement::updateFocusAppearance(m_data, this, this, restorePreviousSelection);
406    else
407        HTMLFormControlElementWithState::updateFocusAppearance(restorePreviousSelection);
408}
409
410void HTMLInputElement::aboutToUnload()
411{
412    InputElement::aboutToUnload(this, this);
413}
414
415bool HTMLInputElement::shouldUseInputMethod() const
416{
417    return m_inputType->shouldUseInputMethod();
418}
419
420void HTMLInputElement::handleFocusEvent()
421{
422    InputElement::dispatchFocusEvent(this, this);
423}
424
425void HTMLInputElement::handleBlurEvent()
426{
427    m_inputType->handleBlurEvent();
428    InputElement::dispatchBlurEvent(this, this);
429}
430
431void HTMLInputElement::setType(const String& type)
432{
433    // FIXME: This should just call setAttribute. No reason to handle the empty string specially.
434    // We should write a test case to show that setting to the empty string does not remove the
435    // attribute in other browsers and then fix this. Note that setting to null *does* remove
436    // the attribute and setAttribute implements that.
437    if (type.isEmpty()) {
438        ExceptionCode ec;
439        removeAttribute(typeAttr, ec);
440    } else
441        setAttribute(typeAttr, type);
442}
443
444void HTMLInputElement::updateType()
445{
446    OwnPtr<InputType> newType = InputType::create(this, fastGetAttribute(typeAttr));
447    bool hadType = m_hasType;
448    m_hasType = true;
449    if (m_inputType->formControlType() == newType->formControlType())
450        return;
451
452    if (hadType && !newType->canChangeFromAnotherType()) {
453        // Set the attribute back to the old value.
454        // Useful in case we were called from inside parseMappedAttribute.
455        setAttribute(typeAttr, type());
456        return;
457    }
458
459    checkedRadioButtons().removeButton(this);
460
461    bool wasAttached = attached();
462    if (wasAttached)
463        detach();
464
465    bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
466    bool neededActivationCallback = needsActivationCallback();
467    bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
468
469    m_inputType->destroyShadowSubtree();
470    m_inputType = newType.release();
471    m_inputType->createShadowSubtree();
472
473    setNeedsWillValidateCheck();
474
475    bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
476
477    if (didStoreValue && !willStoreValue && !m_data.value().isNull()) {
478        setAttribute(valueAttr, m_data.value());
479        m_data.setValue(String());
480    }
481    if (!didStoreValue && willStoreValue)
482        m_data.setValue(sanitizeValue(fastGetAttribute(valueAttr)));
483    else
484        InputElement::updateValueIfNeeded(m_data, this);
485
486    if (neededActivationCallback)
487        unregisterForActivationCallbackIfNeeded();
488    else
489        registerForActivationCallbackIfNeeded();
490
491    if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
492        NamedNodeMap* map = attributeMap();
493        ASSERT(map);
494        if (Attribute* height = map->getAttributeItem(heightAttr))
495            attributeChanged(height, false);
496        if (Attribute* width = map->getAttributeItem(widthAttr))
497            attributeChanged(width, false);
498        if (Attribute* align = map->getAttributeItem(alignAttr))
499            attributeChanged(align, false);
500    }
501
502    if (wasAttached) {
503        attach();
504        if (document()->focusedNode() == this)
505            updateFocusAppearance(true);
506    }
507
508    setChangedSinceLastFormControlChangeEvent(false);
509
510    checkedRadioButtons().addButton(this);
511
512    setNeedsValidityCheck();
513    InputElement::notifyFormStateChanged(this);
514}
515
516const AtomicString& HTMLInputElement::formControlType() const
517{
518    return m_inputType->formControlType();
519}
520
521bool HTMLInputElement::saveFormControlState(String& result) const
522{
523    return m_inputType->saveFormControlState(result);
524}
525
526void HTMLInputElement::restoreFormControlState(const String& state)
527{
528    m_inputType->restoreFormControlState(state);
529    m_stateRestored = true;
530}
531
532bool HTMLInputElement::canStartSelection() const
533{
534    if (!isTextField())
535        return false;
536    return HTMLFormControlElementWithState::canStartSelection();
537}
538
539bool HTMLInputElement::canHaveSelection() const
540{
541    return isTextField();
542}
543
544void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
545{
546    m_inputType->accessKeyAction(sendToAnyElement);
547}
548
549bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
550{
551    if (((attrName == heightAttr || attrName == widthAttr) && m_inputType->shouldRespectHeightAndWidthAttributes())
552        || attrName == vspaceAttr
553        || attrName == hspaceAttr) {
554        result = eUniversal;
555        return false;
556    }
557
558    if (attrName == alignAttr && m_inputType->shouldRespectAlignAttribute()) {
559        // Share with <img> since the alignment behavior is the same.
560        result = eReplaced;
561        return false;
562    }
563
564    return HTMLElement::mapToEntry(attrName, result);
565}
566
567void HTMLInputElement::parseMappedAttribute(Attribute* attr)
568{
569    if (attr->name() == nameAttr) {
570        checkedRadioButtons().removeButton(this);
571        m_data.setName(attr->value());
572        checkedRadioButtons().addButton(this);
573        HTMLFormControlElementWithState::parseMappedAttribute(attr);
574    } else if (attr->name() == autocompleteAttr) {
575        if (equalIgnoringCase(attr->value(), "off")) {
576            m_autocomplete = Off;
577            registerForActivationCallbackIfNeeded();
578        } else {
579            bool needsToUnregister = m_autocomplete == Off;
580
581            if (attr->isEmpty())
582                m_autocomplete = Uninitialized;
583            else
584                m_autocomplete = On;
585
586            if (needsToUnregister)
587                unregisterForActivationCallbackIfNeeded();
588        }
589    } else if (attr->name() == typeAttr) {
590        updateType();
591    } else if (attr->name() == valueAttr) {
592        // We only need to setChanged if the form is looking at the default value right now.
593        if (m_data.value().isNull())
594            setNeedsStyleRecalc();
595        setFormControlValueMatchesRenderer(false);
596        setNeedsValidityCheck();
597    } else if (attr->name() == checkedAttr) {
598        // Another radio button in the same group might be checked by state
599        // restore. We shouldn't call setChecked() even if this has the checked
600        // attribute. So, delay the setChecked() call until
601        // finishParsingChildren() is called if parsing is in progress.
602        if (!m_parsingInProgress && m_reflectsCheckedAttribute) {
603            setChecked(!attr->isNull());
604            m_reflectsCheckedAttribute = true;
605        }
606    } else if (attr->name() == maxlengthAttr) {
607        InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
608        setNeedsValidityCheck();
609    } else if (attr->name() == sizeAttr)
610        InputElement::parseSizeAttribute(m_data, this, attr);
611    else if (attr->name() == altAttr)
612        m_inputType->altAttributeChanged();
613    else if (attr->name() == srcAttr)
614        m_inputType->srcAttributeChanged();
615    else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) {
616        // FIXME: ignore for the moment
617    } else if (attr->name() == vspaceAttr) {
618        addCSSLength(attr, CSSPropertyMarginTop, attr->value());
619        addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
620    } else if (attr->name() == hspaceAttr) {
621        addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
622        addCSSLength(attr, CSSPropertyMarginRight, attr->value());
623    } else if (attr->name() == alignAttr) {
624        if (m_inputType->shouldRespectAlignAttribute())
625            addHTMLAlignment(attr);
626    } else if (attr->name() == widthAttr) {
627        if (m_inputType->shouldRespectHeightAndWidthAttributes())
628            addCSSLength(attr, CSSPropertyWidth, attr->value());
629    } else if (attr->name() == heightAttr) {
630        if (m_inputType->shouldRespectHeightAndWidthAttributes())
631            addCSSLength(attr, CSSPropertyHeight, attr->value());
632    } else if (attr->name() == onsearchAttr) {
633        // Search field and slider attributes all just cause updateFromElement to be called through style recalcing.
634        setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
635    } else if (attr->name() == resultsAttr) {
636        int oldResults = m_maxResults;
637        m_maxResults = !attr->isNull() ? std::min(attr->value().toInt(), maxSavedResults) : -1;
638        // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
639        // time to relayout for this change.
640        if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
641            detach();
642            attach();
643        }
644        setNeedsStyleRecalc();
645    } else if (attr->name() == autosaveAttr || attr->name() == incrementalAttr)
646        setNeedsStyleRecalc();
647    else if (attr->name() == minAttr || attr->name() == maxAttr) {
648        m_inputType->minOrMaxAttributeChanged();
649        setNeedsValidityCheck();
650    } else if (attr->name() == multipleAttr || attr->name() == patternAttr || attr->name() == precisionAttr || attr->name() == stepAttr)
651        setNeedsValidityCheck();
652#if ENABLE(DATALIST)
653    else if (attr->name() == listAttr)
654        m_hasNonEmptyList = !attr->isEmpty();
655        // FIXME: we need to tell this change to a renderer if the attribute affects the appearance.
656#endif
657#if ENABLE(INPUT_SPEECH)
658    else if (attr->name() == webkitspeechAttr) {
659        if (renderer()) {
660            // This renderer and its children have quite different layouts and styles depending on
661            // whether the speech button is visible or not. So we reset the whole thing and recreate
662            // to get the right styles and layout.
663            detach();
664            attach();
665        }
666        setNeedsStyleRecalc();
667    } else if (attr->name() == onwebkitspeechchangeAttr)
668        setAttributeEventListener(eventNames().webkitspeechchangeEvent, createAttributeEventListener(this, attr));
669#endif
670    else
671        HTMLTextFormControlElement::parseMappedAttribute(attr);
672}
673
674void HTMLInputElement::finishParsingChildren()
675{
676    m_parsingInProgress = false;
677    HTMLFormControlElementWithState::finishParsingChildren();
678    if (!m_stateRestored) {
679        bool checked = hasAttribute(checkedAttr);
680        if (checked)
681            setChecked(checked);
682        m_reflectsCheckedAttribute = true;
683    }
684}
685
686bool HTMLInputElement::rendererIsNeeded(RenderStyle* style)
687{
688    return m_inputType->rendererIsNeeded() && HTMLFormControlElementWithState::rendererIsNeeded(style);
689}
690
691RenderObject* HTMLInputElement::createRenderer(RenderArena* arena, RenderStyle* style)
692{
693    return m_inputType->createRenderer(arena, style);
694}
695
696void HTMLInputElement::attach()
697{
698    suspendPostAttachCallbacks();
699
700    if (!m_hasType)
701        updateType();
702
703    HTMLFormControlElementWithState::attach();
704
705    m_inputType->attach();
706
707    if (document()->focusedNode() == this)
708        document()->updateFocusAppearanceSoon(true /* restore selection */);
709
710    resumePostAttachCallbacks();
711}
712
713void HTMLInputElement::detach()
714{
715    HTMLFormControlElementWithState::detach();
716    setFormControlValueMatchesRenderer(false);
717}
718
719String HTMLInputElement::altText() const
720{
721    // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
722    // also heavily discussed by Hixie on bugzilla
723    // note this is intentionally different to HTMLImageElement::altText()
724    String alt = fastGetAttribute(altAttr);
725    // fall back to title attribute
726    if (alt.isNull())
727        alt = getAttribute(titleAttr);
728    if (alt.isNull())
729        alt = getAttribute(valueAttr);
730    if (alt.isEmpty())
731        alt = inputElementAltText();
732    return alt;
733}
734
735bool HTMLInputElement::isSuccessfulSubmitButton() const
736{
737    // HTML spec says that buttons must have names to be considered successful.
738    // However, other browsers do not impose this constraint. So we do not.
739    return !disabled() && m_inputType->canBeSuccessfulSubmitButton();
740}
741
742bool HTMLInputElement::isActivatedSubmit() const
743{
744    return m_isActivatedSubmit;
745}
746
747void HTMLInputElement::setActivatedSubmit(bool flag)
748{
749    m_isActivatedSubmit = flag;
750}
751
752bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
753{
754    return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(encoding, multipart);
755}
756
757void HTMLInputElement::reset()
758{
759    if (m_inputType->storesValueSeparateFromAttribute())
760        setValue(String());
761
762    setAutofilled(false);
763    setChecked(hasAttribute(checkedAttr));
764    m_reflectsCheckedAttribute = true;
765}
766
767bool HTMLInputElement::isTextField() const
768{
769    return m_inputType->isTextField();
770}
771
772bool HTMLInputElement::isTextType() const
773{
774    return m_inputType->isTextType();
775}
776
777void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
778{
779    if (checked() == nowChecked)
780        return;
781
782    checkedRadioButtons().removeButton(this);
783
784    m_reflectsCheckedAttribute = false;
785    m_isChecked = nowChecked;
786    setNeedsStyleRecalc();
787
788    updateCheckedRadioButtons();
789    setNeedsValidityCheck();
790
791    // Ideally we'd do this from the render tree (matching
792    // RenderTextView), but it's not possible to do it at the moment
793    // because of the way the code is structured.
794    if (renderer() && AXObjectCache::accessibilityEnabled())
795        renderer()->document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXCheckedStateChanged, true);
796
797    // Only send a change event for items in the document (avoid firing during
798    // parsing) and don't send a change event for a radio button that's getting
799    // unchecked to match other browsers. DOM is not a useful standard for this
800    // because it says only to fire change events at "lose focus" time, which is
801    // definitely wrong in practice for these types of elements.
802    if (sendChangeEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) {
803        setTextAsOfLastFormControlChangeEvent(String());
804        dispatchFormControlChangeEvent();
805    }
806}
807
808void HTMLInputElement::setIndeterminate(bool newValue)
809{
810    if (!m_inputType->isCheckable() || indeterminate() == newValue)
811        return;
812
813    m_isIndeterminate = newValue;
814
815    setNeedsStyleRecalc();
816
817    if (renderer() && renderer()->style()->hasAppearance())
818        renderer()->theme()->stateChanged(renderer(), CheckedState);
819}
820
821int HTMLInputElement::size() const
822{
823    return m_data.size();
824}
825
826void HTMLInputElement::copyNonAttributeProperties(const Element* source)
827{
828    const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
829
830    m_data.setValue(sourceElement->m_data.value());
831    setChecked(sourceElement->m_isChecked);
832    m_reflectsCheckedAttribute = sourceElement->m_reflectsCheckedAttribute;
833    m_isIndeterminate = sourceElement->m_isIndeterminate;
834
835    HTMLFormControlElementWithState::copyNonAttributeProperties(source);
836}
837
838String HTMLInputElement::value() const
839{
840    String value;
841    if (m_inputType->getTypeSpecificValue(value))
842        return value;
843
844    value = m_data.value();
845    if (!value.isNull())
846        return value;
847
848    value = sanitizeValue(fastGetAttribute(valueAttr));
849    if (!value.isNull())
850        return value;
851
852    return m_inputType->fallbackValue();
853}
854
855String HTMLInputElement::valueWithDefault() const
856{
857    String value = this->value();
858    if (!value.isNull())
859        return value;
860
861    return m_inputType->defaultValue();
862}
863
864void HTMLInputElement::setValueForUser(const String& value)
865{
866    // Call setValue and make it send a change event.
867    setValue(value, true);
868}
869
870const String& HTMLInputElement::suggestedValue() const
871{
872    return m_data.suggestedValue();
873}
874
875void HTMLInputElement::setSuggestedValue(const String& value)
876{
877    if (!m_inputType->canSetSuggestedValue())
878        return;
879    setFormControlValueMatchesRenderer(false);
880    m_data.setSuggestedValue(sanitizeValue(value));
881    updatePlaceholderVisibility(false);
882    if (renderer())
883        renderer()->updateFromElement();
884    setNeedsStyleRecalc();
885}
886
887void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
888{
889    if (!m_inputType->canSetValue(value))
890        return;
891
892    setFormControlValueMatchesRenderer(false);
893    if (m_inputType->storesValueSeparateFromAttribute()) {
894        if (files())
895            files()->clear();
896        else {
897            m_data.setValue(sanitizeValue(value));
898            if (isTextField())
899                updatePlaceholderVisibility(false);
900        }
901        setNeedsStyleRecalc();
902    } else
903        setAttribute(valueAttr, sanitizeValue(value));
904
905    setNeedsValidityCheck();
906
907    if (isTextField()) {
908        unsigned max = m_data.value().length();
909#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
910        // Make sure our UI side textfield changes to match the RenderTextControl
911        PlatformBridge::updateTextfield(document()->view(), this, value);
912#endif
913        if (document()->focusedNode() == this)
914            InputElement::updateSelectionRange(this, this, max, max);
915        else
916            cacheSelection(max, max);
917        m_data.setSuggestedValue(String());
918    }
919    m_inputType->valueChanged();
920
921    if (sendChangeEvent) {
922        // If the user is still editing this field, dispatch an input event rather than a change event.
923        // The change event will be dispatched when editing finishes.
924        if (isTextField() && focused())
925            dispatchFormControlInputEvent();
926        else
927            dispatchFormControlChangeEvent();
928    }
929
930    if (isText() && (!focused() || !sendChangeEvent))
931        setTextAsOfLastFormControlChangeEvent(value);
932
933    InputElement::notifyFormStateChanged(this);
934}
935
936double HTMLInputElement::valueAsDate() const
937{
938    return m_inputType->valueAsDate();
939}
940
941void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec)
942{
943    m_inputType->setValueAsDate(value, ec);
944}
945
946double HTMLInputElement::valueAsNumber() const
947{
948    return m_inputType->valueAsNumber();
949}
950
951void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
952{
953    if (!isfinite(newValue)) {
954        ec = NOT_SUPPORTED_ERR;
955        return;
956    }
957    m_inputType->setValueAsNumber(newValue, ec);
958}
959
960String HTMLInputElement::placeholder() const
961{
962    return fastGetAttribute(placeholderAttr).string();
963}
964
965void HTMLInputElement::setPlaceholder(const String& value)
966{
967    setAttribute(placeholderAttr, value);
968}
969
970bool HTMLInputElement::searchEventsShouldBeDispatched() const
971{
972    return hasAttribute(incrementalAttr);
973}
974
975void HTMLInputElement::setValueFromRenderer(const String& value)
976{
977    // File upload controls will always use setFileListFromRenderer.
978    ASSERT(!isFileUpload());
979
980    m_data.setSuggestedValue(String());
981    InputElement::setValueFromRenderer(m_data, this, this, value);
982    updatePlaceholderVisibility(false);
983    setNeedsValidityCheck();
984
985    // Clear autofill flag (and yellow background) on user edit.
986    setAutofilled(false);
987}
988
989void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
990{
991    m_inputType->setFileList(paths);
992
993    setFormControlValueMatchesRenderer(true);
994    InputElement::notifyFormStateChanged(this);
995    setNeedsValidityCheck();
996}
997
998void* HTMLInputElement::preDispatchEventHandler(Event* event)
999{
1000    if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
1001        event->stopPropagation();
1002        return 0;
1003    }
1004    if (event->type() != eventNames().clickEvent)
1005        return 0;
1006    if (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button() != LeftButton)
1007        return 0;
1008    // FIXME: Check whether there are any cases where this actually ends up leaking.
1009    return m_inputType->willDispatchClick().leakPtr();
1010}
1011
1012void HTMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
1013{
1014    OwnPtr<ClickHandlingState> state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch));
1015    if (!state)
1016        return;
1017    m_inputType->didDispatchClick(event, *state);
1018}
1019
1020void HTMLInputElement::defaultEventHandler(Event* evt)
1021{
1022    if (evt->isMouseEvent() && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1023        m_inputType->handleClickEvent(static_cast<MouseEvent*>(evt));
1024        if (evt->defaultHandled())
1025            return;
1026    }
1027
1028    if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
1029        m_inputType->handleKeydownEvent(static_cast<KeyboardEvent*>(evt));
1030        if (evt->defaultHandled())
1031            return;
1032    }
1033
1034    // Call the base event handler before any of our own event handling for almost all events in text fields.
1035    // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
1036    bool callBaseClassEarly = isTextField() && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1037    if (callBaseClassEarly) {
1038        HTMLFormControlElementWithState::defaultEventHandler(evt);
1039        if (evt->defaultHandled())
1040            return;
1041    }
1042
1043    // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
1044    // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
1045    // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
1046    // must dispatch a DOMActivate event - a click event will not do the job.
1047    if (evt->type() == eventNames().DOMActivateEvent) {
1048        m_inputType->handleDOMActivateEvent(evt);
1049        if (evt->defaultHandled())
1050            return;
1051    }
1052
1053    // Use key press event here since sending simulated mouse events
1054    // on key down blocks the proper sending of the key press event.
1055    if (evt->isKeyboardEvent() && evt->type() == eventNames().keypressEvent) {
1056        m_inputType->handleKeypressEvent(static_cast<KeyboardEvent*>(evt));
1057        if (evt->defaultHandled())
1058            return;
1059    }
1060
1061    if (evt->isKeyboardEvent() && evt->type() == eventNames().keyupEvent) {
1062        m_inputType->handleKeyupEvent(static_cast<KeyboardEvent*>(evt));
1063        if (evt->defaultHandled())
1064            return;
1065    }
1066
1067    if (m_inputType->shouldSubmitImplicitly(evt)) {
1068        if (isSearchField()) {
1069            addSearchResult();
1070            onSearch();
1071        }
1072        // Form submission finishes editing, just as loss of focus does.
1073        // If there was a change, send the event now.
1074        if (wasChangedSinceLastFormControlChangeEvent())
1075            dispatchFormControlChangeEvent();
1076
1077        RefPtr<HTMLFormElement> formForSubmission = m_inputType->formForSubmission();
1078        // Form may never have been present, or may have been destroyed by code responding to the change event.
1079        if (formForSubmission)
1080            formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
1081
1082        evt->setDefaultHandled();
1083        return;
1084    }
1085
1086    if (evt->isBeforeTextInsertedEvent())
1087        m_inputType->handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(evt));
1088
1089    if (evt->isWheelEvent()) {
1090        m_inputType->handleWheelEvent(static_cast<WheelEvent*>(evt));
1091        if (evt->defaultHandled())
1092            return;
1093    }
1094
1095    if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
1096        m_inputType->handleMouseDownEvent(static_cast<MouseEvent*>(evt));
1097        if (evt->defaultHandled())
1098            return;
1099    }
1100
1101#if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
1102    if (evt->isTouchEvent() && evt->type() == eventNames().touchstartEvent) {
1103        m_inputType->handleTouchStartEvent(static_cast<TouchEvent*>(evt));
1104        if (evt->defaultHandled())
1105            return;
1106    }
1107#endif
1108
1109    m_inputType->forwardEvent(evt);
1110
1111    if (!callBaseClassEarly && !evt->defaultHandled())
1112        HTMLFormControlElementWithState::defaultEventHandler(evt);
1113}
1114
1115bool HTMLInputElement::isURLAttribute(Attribute *attr) const
1116{
1117    return (attr->name() == srcAttr || attr->name() == formactionAttr);
1118}
1119
1120String HTMLInputElement::defaultValue() const
1121{
1122    return fastGetAttribute(valueAttr);
1123}
1124
1125void HTMLInputElement::setDefaultValue(const String &value)
1126{
1127    setAttribute(valueAttr, value);
1128}
1129
1130void HTMLInputElement::setDefaultName(const AtomicString& name)
1131{
1132    m_data.setName(name);
1133}
1134
1135String HTMLInputElement::accept() const
1136{
1137    return fastGetAttribute(acceptAttr);
1138}
1139
1140String HTMLInputElement::alt() const
1141{
1142    return fastGetAttribute(altAttr);
1143}
1144
1145int HTMLInputElement::maxLength() const
1146{
1147    return m_data.maxLength();
1148}
1149
1150void HTMLInputElement::setMaxLength(int maxLength, ExceptionCode& ec)
1151{
1152    if (maxLength < 0)
1153        ec = INDEX_SIZE_ERR;
1154    else
1155        setAttribute(maxlengthAttr, String::number(maxLength));
1156}
1157
1158bool HTMLInputElement::multiple() const
1159{
1160    return fastHasAttribute(multipleAttr);
1161}
1162
1163void HTMLInputElement::setSize(unsigned size)
1164{
1165    setAttribute(sizeAttr, String::number(size));
1166}
1167
1168KURL HTMLInputElement::src() const
1169{
1170    return document()->completeURL(fastGetAttribute(srcAttr));
1171}
1172
1173void HTMLInputElement::setAutofilled(bool autofilled)
1174{
1175    if (autofilled == m_isAutofilled)
1176        return;
1177
1178    m_isAutofilled = autofilled;
1179    setNeedsStyleRecalc();
1180}
1181
1182FileList* HTMLInputElement::files()
1183{
1184    return m_inputType->files();
1185}
1186
1187String HTMLInputElement::visibleValue() const
1188{
1189    return m_inputType->visibleValue();
1190}
1191
1192String HTMLInputElement::convertFromVisibleValue(const String& visibleValue) const
1193{
1194    return m_inputType->convertFromVisibleValue(visibleValue);
1195}
1196
1197bool HTMLInputElement::isAcceptableValue(const String& proposedValue) const
1198{
1199    return m_inputType->isAcceptableValue(proposedValue);
1200}
1201
1202String HTMLInputElement::sanitizeValue(const String& proposedValue) const
1203{
1204    return m_inputType->sanitizeValue(proposedValue);
1205}
1206
1207bool HTMLInputElement::hasUnacceptableValue() const
1208{
1209    return m_inputType->hasUnacceptableValue();
1210}
1211
1212bool HTMLInputElement::isInRange() const
1213{
1214    return m_inputType->supportsRangeLimitation() && !rangeUnderflow(value()) && !rangeOverflow(value());
1215}
1216
1217bool HTMLInputElement::isOutOfRange() const
1218{
1219    return m_inputType->supportsRangeLimitation() && (rangeUnderflow(value()) || rangeOverflow(value()));
1220}
1221
1222bool HTMLInputElement::needsActivationCallback()
1223{
1224    return m_autocomplete == Off || m_inputType->shouldResetOnDocumentActivation();
1225}
1226
1227void HTMLInputElement::registerForActivationCallbackIfNeeded()
1228{
1229    if (needsActivationCallback())
1230        document()->registerForDocumentActivationCallbacks(this);
1231}
1232
1233void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
1234{
1235    if (!needsActivationCallback())
1236        document()->unregisterForDocumentActivationCallbacks(this);
1237}
1238
1239bool HTMLInputElement::isRequiredFormControl() const
1240{
1241    return m_inputType->supportsRequired() && required();
1242}
1243
1244void HTMLInputElement::cacheSelection(int start, int end)
1245{
1246    m_data.setCachedSelectionStart(start);
1247    m_data.setCachedSelectionEnd(end);
1248}
1249
1250void HTMLInputElement::addSearchResult()
1251{
1252    ASSERT(isSearchField());
1253    if (renderer())
1254        toRenderTextControlSingleLine(renderer())->addSearchResult();
1255}
1256
1257void HTMLInputElement::onSearch()
1258{
1259    ASSERT(isSearchField());
1260    if (renderer())
1261        toRenderTextControlSingleLine(renderer())->stopSearchEventTimer();
1262    dispatchEvent(Event::create(eventNames().searchEvent, true, false));
1263}
1264
1265void HTMLInputElement::documentDidBecomeActive()
1266{
1267    ASSERT(needsActivationCallback());
1268    reset();
1269}
1270
1271void HTMLInputElement::willMoveToNewOwnerDocument()
1272{
1273    m_inputType->willMoveToNewOwnerDocument();
1274
1275    // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
1276    if (needsActivationCallback())
1277        document()->unregisterForDocumentActivationCallbacks(this);
1278
1279    document()->checkedRadioButtons().removeButton(this);
1280
1281    HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
1282}
1283
1284void HTMLInputElement::didMoveToNewOwnerDocument()
1285{
1286    registerForActivationCallbackIfNeeded();
1287
1288    HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
1289}
1290
1291void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
1292{
1293    HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls);
1294
1295    addSubresourceURL(urls, src());
1296}
1297
1298bool HTMLInputElement::recalcWillValidate() const
1299{
1300    return m_inputType->supportsValidation() && HTMLFormControlElementWithState::recalcWillValidate();
1301}
1302
1303#if ENABLE(DATALIST)
1304
1305HTMLElement* HTMLInputElement::list() const
1306{
1307    return dataList();
1308}
1309
1310HTMLDataListElement* HTMLInputElement::dataList() const
1311{
1312    if (!m_hasNonEmptyList)
1313        return 0;
1314
1315    if (!m_inputType->shouldRespectListAttribute())
1316        return 0;
1317
1318    Element* element = document()->getElementById(fastGetAttribute(listAttr));
1319    if (!element)
1320        return 0;
1321    if (!element->hasTagName(datalistTag))
1322        return 0;
1323
1324    return static_cast<HTMLDataListElement*>(element);
1325}
1326
1327HTMLOptionElement* HTMLInputElement::selectedOption() const
1328{
1329    String value = this->value();
1330
1331    // The empty string never matches to a datalist option because it
1332    // doesn't represent a suggestion according to the standard.
1333    if (value.isEmpty())
1334        return 0;
1335
1336    HTMLDataListElement* sourceElement = dataList();
1337    if (!sourceElement)
1338        return 0;
1339    RefPtr<HTMLCollection> options = sourceElement->options();
1340    if (!options)
1341        return 0;
1342    unsigned length = options->length();
1343    for (unsigned i = 0; i < length; ++i) {
1344        HTMLOptionElement* option = static_cast<HTMLOptionElement*>(options->item(i));
1345        if (!option->disabled() && value == option->value())
1346            return option;
1347    }
1348    return 0;
1349}
1350
1351#endif // ENABLE(DATALIST)
1352
1353void HTMLInputElement::stepUpFromRenderer(int n)
1354{
1355    // The differences from stepUp()/stepDown():
1356    //
1357    // Difference 1: the current value
1358    // If the current value is not a number, including empty, the current value is assumed as 0.
1359    //   * If 0 is in-range, and matches to step value
1360    //     - The value should be the +step if n > 0
1361    //     - The value should be the -step if n < 0
1362    //     If -step or +step is out of range, new value should be 0.
1363    //   * If 0 is smaller than the minimum value
1364    //     - The value should be the minimum value for any n
1365    //   * If 0 is larger than the maximum value
1366    //     - The value should be the maximum value for any n
1367    //   * If 0 is in-range, but not matched to step value
1368    //     - The value should be the larger matched value nearest to 0 if n > 0
1369    //       e.g. <input type=number min=-100 step=3> -> 2
1370    //     - The value should be the smaler matched value nearest to 0 if n < 0
1371    //       e.g. <input type=number min=-100 step=3> -> -1
1372    //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
1373    //   As for datetime type, the current value is assumed as "the current date/time in UTC".
1374    // If the current value is smaller than the minimum value:
1375    //  - The value should be the minimum value if n > 0
1376    //  - Nothing should happen if n < 0
1377    // If the current value is larger than the maximum value:
1378    //  - The value should be the maximum value if n < 0
1379    //  - Nothing should happen if n > 0
1380    //
1381    // Difference 2: clamping steps
1382    // If the current value is not matched to step value:
1383    // - The value should be the larger matched value nearest to 0 if n > 0
1384    //   e.g. <input type=number value=3 min=-100 step=3> -> 5
1385    // - The value should be the smaler matched value nearest to 0 if n < 0
1386    //   e.g. <input type=number value=3 min=-100 step=3> -> 2
1387    //
1388    // n is assumed as -n if step < 0.
1389
1390    ASSERT(hasSpinButton() || m_inputType->isRangeControl());
1391    if (!hasSpinButton() && !m_inputType->isRangeControl())
1392        return;
1393    ASSERT(n);
1394    if (!n)
1395        return;
1396
1397    unsigned stepDecimalPlaces, baseDecimalPlaces;
1398    double step, base;
1399    // The value will be the default value after stepping for <input value=(empty/invalid) step="any" />
1400    // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
1401    // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
1402    if (equalIgnoringCase(fastGetAttribute(stepAttr), "any"))
1403        step = 0;
1404    else if (!getAllowedValueStepWithDecimalPlaces(&step, &stepDecimalPlaces))
1405        return;
1406    base = m_inputType->stepBaseWithDecimalPlaces(&baseDecimalPlaces);
1407    baseDecimalPlaces = min(baseDecimalPlaces, 16u);
1408
1409    int sign;
1410    if (step > 0)
1411        sign = n;
1412    else if (step < 0)
1413        sign = -n;
1414    else
1415        sign = 0;
1416
1417    const double nan = numeric_limits<double>::quiet_NaN();
1418    String currentStringValue = value();
1419    double current = m_inputType->parseToDouble(currentStringValue, nan);
1420    if (!isfinite(current)) {
1421        ExceptionCode ec;
1422        current = m_inputType->defaultValueForStepUp();
1423        setValueAsNumber(current, ec);
1424    }
1425    if ((sign > 0 && current < m_inputType->minimum()) || (sign < 0 && current > m_inputType->maximum()))
1426        setValue(m_inputType->serialize(sign > 0 ? m_inputType->minimum() : m_inputType->maximum()));
1427    else {
1428        ExceptionCode ec;
1429        if (stepMismatch(currentStringValue)) {
1430            ASSERT(step);
1431            double newValue;
1432            double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces)));
1433
1434            if (sign < 0)
1435                newValue = round((base + floor((current - base) / step) * step) * scale) / scale;
1436            else if (sign > 0)
1437                newValue = round((base + ceil((current - base) / step) * step) * scale) / scale;
1438            else
1439                newValue = current;
1440
1441            if (newValue < m_inputType->minimum())
1442                newValue = m_inputType->minimum();
1443            if (newValue > m_inputType->maximum())
1444                newValue = m_inputType->maximum();
1445
1446            setValueAsNumber(newValue, ec);
1447            current = newValue;
1448            if (n > 1)
1449                applyStep(n - 1, ec);
1450            else if (n < -1)
1451                applyStep(n + 1, ec);
1452        } else
1453            applyStep(n, ec);
1454    }
1455
1456    if (currentStringValue != value()) {
1457        if (m_inputType->isRangeControl())
1458            dispatchFormControlChangeEvent();
1459        else
1460            dispatchFormControlInputEvent();
1461    }
1462}
1463
1464#if ENABLE(WCSS)
1465
1466void HTMLInputElement::setWapInputFormat(String& mask)
1467{
1468    String validateMask = validateInputMask(m_data, mask);
1469    if (!validateMask.isEmpty())
1470        m_data.setInputFormatMask(validateMask);
1471}
1472
1473#endif
1474
1475#if ENABLE(INPUT_SPEECH)
1476
1477bool HTMLInputElement::isSpeechEnabled() const
1478{
1479    // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types.
1480    return m_inputType->shouldRespectSpeechAttribute() && RuntimeEnabledFeatures::speechInputEnabled() && hasAttribute(webkitspeechAttr);
1481}
1482
1483#endif
1484
1485bool HTMLInputElement::isTextButton() const
1486{
1487    return m_inputType->isTextButton();
1488}
1489
1490bool HTMLInputElement::isRadioButton() const
1491{
1492    return m_inputType->isRadioButton();
1493}
1494
1495bool HTMLInputElement::isSearchField() const
1496{
1497    return m_inputType->isSearchField();
1498}
1499
1500bool HTMLInputElement::isInputTypeHidden() const
1501{
1502    return m_inputType->isHiddenType();
1503}
1504
1505bool HTMLInputElement::isPasswordField() const
1506{
1507    return m_inputType->isPasswordField();
1508}
1509
1510bool HTMLInputElement::isCheckbox() const
1511{
1512    return m_inputType->isCheckbox();
1513}
1514
1515bool HTMLInputElement::isText() const
1516{
1517    return m_inputType->isTextType();
1518}
1519
1520bool HTMLInputElement::isEmailField() const
1521{
1522    return m_inputType->isEmailField();
1523}
1524
1525bool HTMLInputElement::isFileUpload() const
1526{
1527    return m_inputType->isFileUpload();
1528}
1529
1530bool HTMLInputElement::isImageButton() const
1531{
1532    return m_inputType->isImageButton();
1533}
1534
1535bool HTMLInputElement::isNumberField() const
1536{
1537    return m_inputType->isNumberField();
1538}
1539
1540bool HTMLInputElement::isSubmitButton() const
1541{
1542    return m_inputType->isSubmitButton();
1543}
1544
1545bool HTMLInputElement::isTelephoneField() const
1546{
1547    return m_inputType->isTelephoneField();
1548}
1549
1550bool HTMLInputElement::isURLField() const
1551{
1552    return m_inputType->isURLField();
1553}
1554
1555bool HTMLInputElement::isEnumeratable() const
1556{
1557    return m_inputType->isEnumeratable();
1558}
1559
1560bool HTMLInputElement::isChecked() const
1561{
1562    return checked() && m_inputType->isCheckable();
1563}
1564
1565bool HTMLInputElement::hasSpinButton() const
1566{
1567    return m_inputType->hasSpinButton();
1568}
1569
1570bool HTMLInputElement::supportsPlaceholder() const
1571{
1572#if PLATFORM(ANDROID)
1573    return isTextType() || isNumberField();
1574#else
1575    return isTextType();
1576#endif
1577}
1578
1579CheckedRadioButtons& HTMLInputElement::checkedRadioButtons() const
1580{
1581    if (HTMLFormElement* formElement = form())
1582        return formElement->checkedRadioButtons();
1583    return document()->checkedRadioButtons();
1584}
1585
1586void HTMLInputElement::handleBeforeTextInsertedEvent(Event* event)
1587{
1588    InputElement::handleBeforeTextInsertedEvent(m_data, this, this, event);
1589}
1590
1591#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE)
1592String HTMLInputElement::capture() const
1593{
1594    if (!isFileUpload()) {
1595        // capture has no meaning on anything other than file pickers.
1596        return String();
1597    }
1598
1599    String capture = fastGetAttribute(captureAttr).lower();
1600    if (capture == "camera"
1601        || capture == "camcorder"
1602        || capture == "microphone"
1603        || capture == "filesystem")
1604        return capture;
1605    // According to the HTML Media Capture specification, the invalid and
1606    // missing default value is filesystem.
1607    return "filesystem";
1608}
1609#endif
1610
1611} // namespace
1612