/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
 * Copyright (C) 2009, 2010, 2011, 2012 Google Inc. All rights reserved.
 * Copyright (C) 2012 Samsung Electronics. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "core/html/forms/InputType.h"

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "core/InputTypeNames.h"
#include "core/dom/AXObjectCache.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/ScopedEventQueue.h"
#include "core/fileapi/FileList.h"
#include "core/frame/FrameHost.h"
#include "core/html/FormData.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLShadowElement.h"
#include "core/html/forms/ButtonInputType.h"
#include "core/html/forms/CheckboxInputType.h"
#include "core/html/forms/ColorChooser.h"
#include "core/html/forms/ColorInputType.h"
#include "core/html/forms/DateInputType.h"
#include "core/html/forms/DateTimeLocalInputType.h"
#include "core/html/forms/EmailInputType.h"
#include "core/html/forms/FileInputType.h"
#include "core/html/forms/HiddenInputType.h"
#include "core/html/forms/ImageInputType.h"
#include "core/html/forms/MonthInputType.h"
#include "core/html/forms/NumberInputType.h"
#include "core/html/forms/PasswordInputType.h"
#include "core/html/forms/RadioInputType.h"
#include "core/html/forms/RangeInputType.h"
#include "core/html/forms/ResetInputType.h"
#include "core/html/forms/SearchInputType.h"
#include "core/html/forms/SubmitInputType.h"
#include "core/html/forms/TelephoneInputType.h"
#include "core/html/forms/TextInputType.h"
#include "core/html/forms/TimeInputType.h"
#include "core/html/forms/URLInputType.h"
#include "core/html/forms/WeekInputType.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/layout/LayoutTheme.h"
#include "platform/JSONValues.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/text/PlatformLocale.h"
#include "platform/text/TextBreakIterator.h"

namespace blink {

using blink::WebLocalizedString;
using namespace HTMLNames;

using InputTypeFactoryFunction = InputType* (*)(HTMLInputElement&);
using InputTypeFactoryMap = HashMap<AtomicString, InputTypeFactoryFunction, CaseFoldingHash>;

static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
{
    OwnPtr<InputTypeFactoryMap> map = adoptPtr(new InputTypeFactoryMap);
    map->add(InputTypeNames::button, ButtonInputType::create);
    map->add(InputTypeNames::checkbox, CheckboxInputType::create);
    map->add(InputTypeNames::color, ColorInputType::create);
    map->add(InputTypeNames::date, DateInputType::create);
    map->add(InputTypeNames::datetime_local, DateTimeLocalInputType::create);
    map->add(InputTypeNames::email, EmailInputType::create);
    map->add(InputTypeNames::file, FileInputType::create);
    map->add(InputTypeNames::hidden, HiddenInputType::create);
    map->add(InputTypeNames::image, ImageInputType::create);
    map->add(InputTypeNames::month, MonthInputType::create);
    map->add(InputTypeNames::number, NumberInputType::create);
    map->add(InputTypeNames::password, PasswordInputType::create);
    map->add(InputTypeNames::radio, RadioInputType::create);
    map->add(InputTypeNames::range, RangeInputType::create);
    map->add(InputTypeNames::reset, ResetInputType::create);
    map->add(InputTypeNames::search, SearchInputType::create);
    map->add(InputTypeNames::submit, SubmitInputType::create);
    map->add(InputTypeNames::tel, TelephoneInputType::create);
    map->add(InputTypeNames::time, TimeInputType::create);
    map->add(InputTypeNames::url, URLInputType::create);
    map->add(InputTypeNames::week, WeekInputType::create);
    // No need to register "text" because it is the default type.
    return map;
}

static const InputTypeFactoryMap* factoryMap()
{
    static const InputTypeFactoryMap* factoryMap = createInputTypeFactoryMap().leakPtr();
    return factoryMap;
}

InputType* InputType::create(HTMLInputElement& element, const AtomicString& typeName)
{
    InputTypeFactoryFunction factory = typeName.isEmpty() ? 0 : factoryMap()->get(typeName);
    if (!factory)
        factory = TextInputType::create;
    return factory(element);
}

InputType* InputType::createText(HTMLInputElement& element)
{
    return TextInputType::create(element);
}

const AtomicString& InputType::normalizeTypeName(const AtomicString& typeName)
{
    if (typeName.isEmpty())
        return InputTypeNames::text;
    InputTypeFactoryMap::const_iterator it = factoryMap()->find(typeName);
    return it == factoryMap()->end() ? InputTypeNames::text : it->key;
}

InputType::~InputType()
{
}

DEFINE_TRACE(InputType)
{
    visitor->trace(m_element);
}

bool InputType::isTextField() const
{
    return false;
}

bool InputType::shouldSaveAndRestoreFormControlState() const
{
    return true;
}

bool InputType::isFormDataAppendable() const
{
    // There is no form data unless there's a name for non-image types.
    return !element().name().isEmpty();
}

void InputType::appendToFormData(FormData& formData) const
{
    formData.append(element().name(), element().value());
}

String InputType::resultForDialogSubmit() const
{
    return element().fastGetAttribute(valueAttr);
}

double InputType::valueAsDate() const
{
    return DateComponents::invalidMilliseconds();
}

void InputType::setValueAsDate(double, ExceptionState& exceptionState) const
{
    exceptionState.throwDOMException(InvalidStateError, "This input element does not support Date values.");
}

double InputType::valueAsDouble() const
{
    return std::numeric_limits<double>::quiet_NaN();
}

void InputType::setValueAsDouble(double doubleValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const
{
    exceptionState.throwDOMException(InvalidStateError, "This input element does not support Number values.");
}

void InputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState&) const
{
    element().setValue(serialize(newValue), eventBehavior);
}

void InputType::readingChecked() const
{
}

bool InputType::supportsValidation() const
{
    return true;
}

bool InputType::typeMismatchFor(const String&) const
{
    return false;
}

bool InputType::typeMismatch() const
{
    return false;
}

bool InputType::supportsRequired() const
{
    // Almost all validatable types support @required.
    return supportsValidation();
}

bool InputType::valueMissing(const String&) const
{
    return false;
}

bool InputType::tooLong(const String&, HTMLTextFormControlElement::NeedsToCheckDirtyFlag) const
{
    return false;
}

bool InputType::tooShort(const String&, HTMLTextFormControlElement::NeedsToCheckDirtyFlag) const
{
    return false;
}

bool InputType::patternMismatch(const String&) const
{
    return false;
}

bool InputType::rangeUnderflow(const String& value) const
{
    if (!isSteppable())
        return false;

    const Decimal numericValue = parseToNumberOrNaN(value);
    if (!numericValue.isFinite())
        return false;

    return numericValue < createStepRange(RejectAny).minimum();
}

bool InputType::rangeOverflow(const String& value) const
{
    if (!isSteppable())
        return false;

    const Decimal numericValue = parseToNumberOrNaN(value);
    if (!numericValue.isFinite())
        return false;

    return numericValue > createStepRange(RejectAny).maximum();
}

Decimal InputType::defaultValueForStepUp() const
{
    return 0;
}

double InputType::minimum() const
{
    return createStepRange(RejectAny).minimum().toDouble();
}

double InputType::maximum() const
{
    return createStepRange(RejectAny).maximum().toDouble();
}

bool InputType::isInRange(const String& value) const
{
    if (!isSteppable())
        return false;

    // This function should return true if both of validity.rangeUnderflow and
    // validity.rangeOverflow are false.
    // If the INPUT has no value, they are false.
    const Decimal numericValue = parseToNumberOrNaN(value);
    if (!numericValue.isFinite())
        return true;

    StepRange stepRange(createStepRange(RejectAny));
    return stepRange.hasRangeLimitations() && numericValue >= stepRange.minimum() && numericValue <= stepRange.maximum();
}

bool InputType::isOutOfRange(const String& value) const
{
    if (!isSteppable())
        return false;

    // This function should return true if either validity.rangeUnderflow or
    // validity.rangeOverflow are true.
    // If the INPUT has no value, they are false.
    const Decimal numericValue = parseToNumberOrNaN(value);
    if (!numericValue.isFinite())
        return false;

    StepRange stepRange(createStepRange(RejectAny));
    return stepRange.hasRangeLimitations() && (numericValue < stepRange.minimum() || numericValue > stepRange.maximum());
}

bool InputType::stepMismatch(const String& value) const
{
    if (!isSteppable())
        return false;

    const Decimal numericValue = parseToNumberOrNaN(value);
    if (!numericValue.isFinite())
        return false;

    return createStepRange(RejectAny).stepMismatch(numericValue);
}

String InputType::badInputText() const
{
    ASSERT_NOT_REACHED();
    return locale().queryString(WebLocalizedString::ValidationTypeMismatch);
}

String InputType::rangeOverflowText(const Decimal&) const
{
    ASSERT_NOT_REACHED();
    return String();
}

String InputType::rangeUnderflowText(const Decimal&) const
{
    ASSERT_NOT_REACHED();
    return String();
}

String InputType::typeMismatchText() const
{
    return locale().queryString(WebLocalizedString::ValidationTypeMismatch);
}

String InputType::valueMissingText() const
{
    return locale().queryString(WebLocalizedString::ValidationValueMissing);
}

std::pair<String, String> InputType::validationMessage(const InputTypeView& inputTypeView) const
{
    const String value = element().value();

    // The order of the following checks is meaningful. e.g. We'd like to show the
    // badInput message even if the control has other validation errors.
    if (inputTypeView.hasBadInput())
        return std::make_pair(badInputText(), emptyString());

    if (valueMissing(value))
        return std::make_pair(valueMissingText(), emptyString());

    if (typeMismatch())
        return std::make_pair(typeMismatchText(), emptyString());

    if (patternMismatch(value)) {
        // https://html.spec.whatwg.org/multipage/forms.html#attr-input-pattern
        //   When an input element has a pattern attribute specified, authors
        //   should include a title attribute to give a description of the
        //   pattern. User agents may use the contents of this attribute, if it
        //   is present, when informing the user that the pattern is not matched
        return std::make_pair(locale().queryString(WebLocalizedString::ValidationPatternMismatch), element().fastGetAttribute(titleAttr).getString());
    }

    if (element().tooLong())
        return std::make_pair(locale().validationMessageTooLongText(value.length(), element().maxLength()), emptyString());

    if (element().tooShort())
        return std::make_pair(locale().validationMessageTooShortText(value.length(), element().minLength()), emptyString());

    if (!isSteppable())
        return std::make_pair(emptyString(), emptyString());

    const Decimal numericValue = parseToNumberOrNaN(value);
    if (!numericValue.isFinite())
        return std::make_pair(emptyString(), emptyString());

    StepRange stepRange(createStepRange(RejectAny));

    if (numericValue < stepRange.minimum())
        return std::make_pair(rangeUnderflowText(stepRange.minimum()), emptyString());

    if (numericValue > stepRange.maximum())
        return std::make_pair(rangeOverflowText(stepRange.maximum()), emptyString());

    if (stepRange.stepMismatch(numericValue)) {
        ASSERT(stepRange.hasStep());
        Decimal candidate1 = stepRange.clampValue(numericValue);
        String localizedCandidate1 = localizeValue(serialize(candidate1));
        Decimal candidate2 = candidate1 < numericValue ? candidate1 + stepRange.step() : candidate1 - stepRange.step();
        if (!candidate2.isFinite() || candidate2 < stepRange.minimum() || candidate2 > stepRange.maximum())
            return std::make_pair(locale().queryString(WebLocalizedString::ValidationStepMismatchCloseToLimit, localizedCandidate1), emptyString());
        String localizedCandidate2 = localizeValue(serialize(candidate2));
        if (candidate1 < candidate2)
            return std::make_pair(locale().queryString(WebLocalizedString::ValidationStepMismatch, localizedCandidate1, localizedCandidate2), emptyString());
        return std::make_pair(locale().queryString(WebLocalizedString::ValidationStepMismatch, localizedCandidate2, localizedCandidate1), emptyString());
    }

    return std::make_pair(emptyString(), emptyString());
}

Decimal InputType::parseToNumber(const String&, const Decimal& defaultValue) const
{
    ASSERT_NOT_REACHED();
    return defaultValue;
}

Decimal InputType::parseToNumberOrNaN(const String& string) const
{
    return parseToNumber(string, Decimal::nan());
}

String InputType::serialize(const Decimal&) const
{
    ASSERT_NOT_REACHED();
    return String();
}

ChromeClient* InputType::chromeClient() const
{
    if (FrameHost* host = element().document().frameHost())
        return &host->chromeClient();
    return nullptr;
}

Locale& InputType::locale() const
{
    return element().locale();
}

bool InputType::canSetStringValue() const
{
    return true;
}

bool InputType::isKeyboardFocusable() const
{
    return element().isFocusable();
}

bool InputType::shouldShowFocusRingOnMouseFocus() const
{
    return false;
}

void InputType::enableSecureTextInput()
{
}

void InputType::disableSecureTextInput()
{
}

void InputType::countUsage()
{
}

bool InputType::shouldRespectAlignAttribute()
{
    return false;
}

void InputType::sanitizeValueInResponseToMinOrMaxAttributeChange()
{
}

bool InputType::canBeSuccessfulSubmitButton()
{
    return false;
}

bool InputType::matchesDefaultPseudoClass()
{
    return false;
}

bool InputType::layoutObjectIsNeeded()
{
    return true;
}

FileList* InputType::files()
{
    return nullptr;
}

void InputType::setFiles(FileList*)
{
}

bool InputType::getTypeSpecificValue(String&)
{
    return false;
}

String InputType::fallbackValue() const
{
    return String();
}

String InputType::defaultValue() const
{
    return String();
}

bool InputType::canSetSuggestedValue()
{
    return false;
}

bool InputType::shouldSendChangeEventAfterCheckedChanged()
{
    return true;
}

bool InputType::storesValueSeparateFromAttribute()
{
    return true;
}

bool InputType::shouldDispatchFormControlChangeEvent(String& oldValue, String& newValue)
{
    return !equalIgnoringNullity(oldValue, newValue);
}

void InputType::dispatchSearchEvent()
{
}

void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
    element().setValueInternal(sanitizedValue, eventBehavior);
    if (!valueChanged)
        return;
    switch (eventBehavior) {
    case DispatchChangeEvent:
        element().dispatchFormControlChangeEvent();
        break;
    case DispatchInputAndChangeEvent:
        element().dispatchFormControlInputEvent();
        element().dispatchFormControlChangeEvent();
        break;
    case DispatchNoEvent:
        break;
    }
}

bool InputType::canSetValue(const String&)
{
    return true;
}

String InputType::localizeValue(const String& proposedValue) const
{
    return proposedValue;
}

String InputType::visibleValue() const
{
    return element().value();
}

String InputType::sanitizeValue(const String& proposedValue) const
{
    return proposedValue;
}

String InputType::sanitizeUserInputValue(const String& proposedValue) const
{
    return sanitizeValue(proposedValue);
}

void InputType::warnIfValueIsInvalidAndElementIsVisible(const String& value) const
{
    // Don't warn if the value is set in Modernizr.
    const ComputedStyle* style = element().computedStyle();
    if (style && style->visibility() != HIDDEN)
        warnIfValueIsInvalid(value);
}

void InputType::warnIfValueIsInvalid(const String&) const
{
}

bool InputType::receiveDroppedFiles(const DragData*)
{
    ASSERT_NOT_REACHED();
    return false;
}

String InputType::droppedFileSystemId()
{
    ASSERT_NOT_REACHED();
    return String();
}

bool InputType::shouldRespectListAttribute()
{
    return false;
}

bool InputType::isTextButton() const
{
    return false;
}

bool InputType::isInteractiveContent() const
{
    return true;
}

bool InputType::isEnumeratable()
{
    return true;
}

bool InputType::isCheckable()
{
    return false;
}

bool InputType::isSteppable() const
{
    return false;
}

bool InputType::shouldRespectHeightAndWidthAttributes()
{
    return false;
}

int InputType::maxLength() const
{
    return HTMLInputElement::maximumLength;
}

int InputType::minLength() const
{
    return 0;
}

bool InputType::supportsPlaceholder() const
{
    return false;
}

bool InputType::supportsReadOnly() const
{
    return false;
}

String InputType::defaultToolTip(const InputTypeView& inputTypeView) const
{
    if (element().form() && element().form()->noValidate())
        return String();
    return validationMessage(inputTypeView).first;
}

Decimal InputType::findClosestTickMarkValue(const Decimal&)
{
    ASSERT_NOT_REACHED();
    return Decimal::nan();
}

bool InputType::hasLegalLinkAttribute(const QualifiedName&) const
{
    return false;
}

const QualifiedName& InputType::subResourceAttributeName() const
{
    return QualifiedName::null();
}

bool InputType::supportsAutocapitalize() const
{
    return false;
}

const AtomicString& InputType::defaultAutocapitalize() const
{
    DEFINE_STATIC_LOCAL(const AtomicString, none, ("none"));
    return none;
}

bool InputType::shouldAppearIndeterminate() const
{
    return false;
}

bool InputType::supportsInputModeAttribute() const
{
    return false;
}

bool InputType::supportsSelectionAPI() const
{
    return false;
}

unsigned InputType::height() const
{
    return 0;
}

unsigned InputType::width() const
{
    return 0;
}

ColorChooserClient* InputType::colorChooserClient()
{
    return nullptr;
}

void InputType::applyStep(const Decimal& current, int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState)
{
    // https://html.spec.whatwg.org/multipage/forms.html#dom-input-stepup

    StepRange stepRange(createStepRange(anyStepHandling));
    // 2. If the element has no allowed value step, then throw an
    // InvalidStateError exception, and abort these steps.
    if (!stepRange.hasStep()) {
        exceptionState.throwDOMException(InvalidStateError, "This form element does not have an allowed value step.");
        return;
    }

    // 3. If the element has a minimum and a maximum and the minimum is greater
    // than the maximum, then abort these steps.
    if (stepRange.minimum() > stepRange.maximum())
        return;

    // 4. If the element has a minimum and a maximum and there is no value
    // greater than or equal to the element's minimum and less than or equal to
    // the element's maximum that, when subtracted from the step base, is an
    // integral multiple of the allowed value step, then abort these steps.
    const Decimal base = stepRange.stepBase();
    const Decimal step = stepRange.step();
    const Decimal alignedMaximum = base + ((stepRange.maximum() - base) / step).floor() * step;
    ASSERT(alignedMaximum <= stepRange.maximum());
    if (alignedMaximum < stepRange.minimum())
        return;

    EventQueueScope scope;
    Decimal newValue = current;
    const AtomicString& stepString = element().fastGetAttribute(stepAttr);
    if (!equalIgnoringCase(stepString, "any") && stepRange.stepMismatch(current)) {
        // Snap-to-step / clamping steps
        // If the current value is not matched to step value:
        // - The value should be the larger matched value nearest to 0 if count > 0
        //   e.g. <input type=number value=3 min=-100 step=3> -> 5
        // - The value should be the smaller matched value nearest to 0 if count < 0
        //   e.g. <input type=number value=3 min=-100 step=3> -> 2
        //

        ASSERT(!step.isZero());
        if (count < 0) {
            newValue = base + ((newValue - base) / step).floor() * step;
            ++count;
        } else if (count > 0) {
            newValue = base + ((newValue - base) / step).ceil() * step;
            --count;
        }
    }
    newValue = newValue + stepRange.step() * count;

    if (!equalIgnoringCase(stepString, "any"))
        newValue = stepRange.alignValueForStep(current, newValue);

    // 7. If the element has a minimum, and value is less than that minimum,
    // then set value to the smallest value that, when subtracted from the step
    // base, is an integral multiple of the allowed value step, and that is more
    // than or equal to minimum.
    // 8. If the element has a maximum, and value is greater than that maximum,
    // then set value to the largest value that, when subtracted from the step
    // base, is an integral multiple of the allowed value step, and that is less
    // than or equal to maximum.
    if (newValue > stepRange.maximum()) {
        newValue = alignedMaximum;
    } else if (newValue < stepRange.minimum()) {
        const Decimal alignedMinimum = base + ((stepRange.minimum() - base) / step).ceil() * step;
        ASSERT(alignedMinimum >= stepRange.minimum());
        newValue = alignedMinimum;
    }

    // 9. Let value as string be the result of running the algorithm to convert
    // a number to a string, as defined for the input element's type attribute's
    // current state, on value.
    // 10. Set the value of the element to value as string.
    setValueAsDecimal(newValue, eventBehavior, exceptionState);

    if (AXObjectCache* cache = element().document().existingAXObjectCache())
        cache->handleValueChanged(&element());
}

bool InputType::getAllowedValueStep(Decimal* step) const
{
    StepRange stepRange(createStepRange(RejectAny));
    *step = stepRange.step();
    return stepRange.hasStep();
}

StepRange InputType::createStepRange(AnyStepHandling) const
{
    ASSERT_NOT_REACHED();
    return StepRange();
}

void InputType::stepUp(int n, ExceptionState& exceptionState)
{
    if (!isSteppable()) {
        exceptionState.throwDOMException(InvalidStateError, "This form element is not steppable.");
        return;
    }
    const Decimal current = parseToNumber(element().value(), 0);
    applyStep(current, n, RejectAny, DispatchNoEvent, exceptionState);
}

void InputType::stepUpFromLayoutObject(int n)
{
    // The only difference from stepUp()/stepDown() is the extra treatment
    // of the current value before applying the step:
    //
    // If the current value is not a number, including empty, the current value is assumed as 0.
    //   * If 0 is in-range, and matches to step value
    //     - The value should be the +step if n > 0
    //     - The value should be the -step if n < 0
    //     If -step or +step is out of range, new value should be 0.
    //   * If 0 is smaller than the minimum value
    //     - The value should be the minimum value for any n
    //   * If 0 is larger than the maximum value
    //     - The value should be the maximum value for any n
    //   * If 0 is in-range, but not matched to step value
    //     - The value should be the larger matched value nearest to 0 if n > 0
    //       e.g. <input type=number min=-100 step=3> -> 2
    //     - The value should be the smaler matched value nearest to 0 if n < 0
    //       e.g. <input type=number min=-100 step=3> -> -1
    //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
    //   As for datetime type, the current value is assumed as "the current date/time in UTC".
    // If the current value is smaller than the minimum value:
    //  - The value should be the minimum value if n > 0
    //  - Nothing should happen if n < 0
    // If the current value is larger than the maximum value:
    //  - The value should be the maximum value if n < 0
    //  - Nothing should happen if n > 0
    //
    // n is assumed as -n if step < 0.

    ASSERT(isSteppable());
    if (!isSteppable())
        return;
    ASSERT(n);
    if (!n)
        return;

    StepRange stepRange(createStepRange(AnyIsDefaultStep));

    // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
    // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
    if (!stepRange.hasStep())
        return;

    EventQueueScope scope;
    const Decimal step = stepRange.step();

    int sign;
    if (step > 0)
        sign = n;
    else if (step < 0)
        sign = -n;
    else
        sign = 0;

    Decimal current = parseToNumberOrNaN(element().value());
    if (!current.isFinite()) {
        current = defaultValueForStepUp();
        const Decimal nextDiff = step * n;
        if (current < stepRange.minimum() - nextDiff)
            current = stepRange.minimum() - nextDiff;
        if (current > stepRange.maximum() - nextDiff)
            current = stepRange.maximum() - nextDiff;
        setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION);
    }
    if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) {
        setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION);
        return;
    }
    if ((sign > 0 && current >= stepRange.maximum()) || (sign < 0 && current <= stepRange.minimum()))
        return;
    applyStep(current, n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION);
}

void InputType::countUsageIfVisible(UseCounter::Feature feature) const
{
    if (const ComputedStyle* style = element().computedStyle()) {
        if (style->visibility() != HIDDEN)
            UseCounter::count(element().document(), feature);
    }
}

Decimal InputType::findStepBase(const Decimal& defaultValue) const
{
    Decimal stepBase = parseToNumber(element().fastGetAttribute(minAttr), Decimal::nan());
    if (!stepBase.isFinite())
        stepBase = parseToNumber(element().fastGetAttribute(valueAttr), defaultValue);
    return stepBase;
}

StepRange InputType::createStepRange(AnyStepHandling anyStepHandling, const Decimal& stepBaseDefault, const Decimal& minimumDefault, const Decimal& maximumDefault, const StepRange::StepDescription& stepDescription) const
{
    bool hasRangeLimitations = false;
    const Decimal stepBase = findStepBase(stepBaseDefault);
    Decimal minimum = parseToNumberOrNaN(element().fastGetAttribute(minAttr));
    if (minimum.isFinite())
        hasRangeLimitations = true;
    else
        minimum = minimumDefault;
    Decimal maximum = parseToNumberOrNaN(element().fastGetAttribute(maxAttr));
    if (maximum.isFinite())
        hasRangeLimitations = true;
    else
        maximum = maximumDefault;
    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    return StepRange(stepBase, minimum, maximum, hasRangeLimitations, step, stepDescription);
}

void InputType::addWarningToConsole(const char* messageFormat, const String& value) const
{
    element().document().addConsoleMessage(ConsoleMessage::create(RenderingMessageSource, WarningMessageLevel,
        String::format(messageFormat, JSONValue::quoteString(value).utf8().data())));
}

} // namespace blink
