Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      6  *           (C) 2006 Alexey Proskuryakov (ap (at) nypop.com)
      7  * Copyright (C) 2007 Samuel Weinig (sam (at) webkit.org)
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  *
     24  */
     25 
     26 #include "config.h"
     27 #include "HTMLInputElement.h"
     28 
     29 #include "AXObjectCache.h"
     30 #include "CSSPropertyNames.h"
     31 #include "ChromeClient.h"
     32 #include "DateComponents.h"
     33 #include "Document.h"
     34 #include "Editor.h"
     35 #include "Event.h"
     36 #include "EventHandler.h"
     37 #include "EventNames.h"
     38 #include "ExceptionCode.h"
     39 #include "File.h"
     40 #include "FileList.h"
     41 #include "FocusController.h"
     42 #include "FormDataList.h"
     43 #include "Frame.h"
     44 #include "HTMLDataListElement.h"
     45 #include "HTMLFormElement.h"
     46 #include "HTMLImageLoader.h"
     47 #include "HTMLNames.h"
     48 #include "HTMLOptionElement.h"
     49 #include "ScriptEventListener.h"
     50 #include "KeyboardEvent.h"
     51 #include "LocalizedStrings.h"
     52 #include "MappedAttribute.h"
     53 #include "MouseEvent.h"
     54 #include "Page.h"
     55 #include "RegularExpression.h"
     56 #include "RenderButton.h"
     57 #include "RenderFileUploadControl.h"
     58 #include "RenderImage.h"
     59 #include "RenderSlider.h"
     60 #include "RenderText.h"
     61 #include "RenderTextControlSingleLine.h"
     62 #include "RenderTheme.h"
     63 #include "StringHash.h"
     64 #include "TextEvent.h"
     65 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
     66 #include "WebViewCore.h"
     67 #endif
     68 #include <wtf/HashMap.h>
     69 #include <wtf/MathExtras.h>
     70 #include <wtf/StdLibExtras.h>
     71 #include <wtf/dtoa.h>
     72 
     73 using namespace std;
     74 
     75 namespace WebCore {
     76 
     77 using namespace HTMLNames;
     78 
     79 const int maxSavedResults = 256;
     80 
     81 // Constant values for getAllowedValueStep().
     82 static const double dateDefaultStep = 1.0;
     83 static const double dateStepScaleFactor = 86400000.0;
     84 static const double dateTimeDefaultStep = 60.0;
     85 static const double dateTimeStepScaleFactor = 1000.0;
     86 static const double monthDefaultStep = 1.0;
     87 static const double monthStepScaleFactor = 1.0;
     88 static const double numberDefaultStep = 1.0;
     89 static const double numberStepScaleFactor = 1.0;
     90 static const double timeDefaultStep = 60.0;
     91 static const double timeStepScaleFactor = 1000.0;
     92 static const double weekDefaultStep = 1.0;
     93 static const double weekStepScaleFactor = 604800000.0;
     94 
     95 // Constant values for minimum().
     96 static const double dateDefaultMinimum = -12219292800000.0; // This means 1582-10-15T00:00Z.
     97 static const double dateTimeDefaultMinimum = -12219292800000.0; // ditto.
     98 static const double monthDefaultMinimum = (1582.0 - 1970) * 12 + 10 - 1; // 1582-10
     99 static const double numberDefaultMinimum = -DBL_MAX;
    100 static const double rangeDefaultMinimum = 0.0;
    101 static const double timeDefaultMinimum = 0.0; // 00:00:00.000
    102 static const double weekDefaultMinimum = -12212380800000.0; // 1583-01-03, the first Monday of 1583.
    103 
    104 // Constant values for maximum().
    105 static const double dateDefaultMaximum = DBL_MAX;
    106 static const double dateTimeDefaultMaximum = DBL_MAX;
    107 // DateComponents::m_year can't represent a year greater than INT_MAX.
    108 static const double monthDefaultMaximum = (INT_MAX - 1970) * 12.0 + 12 - 1;
    109 static const double numberDefaultMaximum = DBL_MAX;
    110 static const double rangeDefaultMaximum = 100.0;
    111 static const double timeDefaultMaximum = 86399999.0; // 23:59:59.999
    112 static const double weekDefaultMaximum = DBL_MAX;
    113 
    114 static const double defaultStepBase = 0.0;
    115 static const double weekDefaultStepBase = -259200000.0; // The first day of 1970-W01.
    116 
    117 static const double msecPerMinute = 60 * 1000;
    118 static const double msecPerSecond = 1000;
    119 
    120 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
    121     : HTMLTextFormControlElement(tagName, doc, f)
    122     , m_xPos(0)
    123     , m_yPos(0)
    124     , m_maxResults(-1)
    125     , m_type(TEXT)
    126     , m_checked(false)
    127     , m_defaultChecked(false)
    128     , m_useDefaultChecked(true)
    129     , m_indeterminate(false)
    130     , m_haveType(false)
    131     , m_activeSubmit(false)
    132     , m_autocomplete(Uninitialized)
    133     , m_autofilled(false)
    134     , m_inited(false)
    135 {
    136     ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
    137 }
    138 
    139 HTMLInputElement::~HTMLInputElement()
    140 {
    141     if (needsActivationCallback())
    142         document()->unregisterForDocumentActivationCallbacks(this);
    143 
    144     document()->checkedRadioButtons().removeButton(this);
    145 
    146     // Need to remove this from the form while it is still an HTMLInputElement,
    147     // so can't wait for the base class's destructor to do it.
    148     removeFromForm();
    149 }
    150 
    151 const AtomicString& HTMLInputElement::formControlName() const
    152 {
    153     return m_data.name();
    154 }
    155 
    156 bool HTMLInputElement::autoComplete() const
    157 {
    158     if (m_autocomplete != Uninitialized)
    159         return m_autocomplete == On;
    160 
    161     // Assuming we're still in a Form, respect the Form's setting
    162     if (HTMLFormElement* form = this->form())
    163         return form->autoComplete();
    164 
    165     // The default is true
    166     return true;
    167 }
    168 
    169 bool HTMLInputElement::valueMissing() const
    170 {
    171     if (!isRequiredFormControl() || readOnly() || disabled())
    172         return false;
    173 
    174     switch (inputType()) {
    175         case DATE:
    176         case DATETIME:
    177         case DATETIMELOCAL:
    178         case EMAIL:
    179         case FILE:
    180         case MONTH:
    181         case NUMBER:
    182         case PASSWORD:
    183         case SEARCH:
    184         case TELEPHONE:
    185         case TEXT:
    186         case TIME:
    187         case URL:
    188         case WEEK:
    189             return value().isEmpty();
    190         case CHECKBOX:
    191             return !checked();
    192         case RADIO:
    193             return !document()->checkedRadioButtons().checkedButtonForGroup(name());
    194         case COLOR:
    195             return false;
    196         case BUTTON:
    197         case HIDDEN:
    198         case IMAGE:
    199         case ISINDEX:
    200         case RANGE:
    201         case RESET:
    202         case SUBMIT:
    203             break;
    204     }
    205 
    206     ASSERT_NOT_REACHED();
    207     return false;
    208 }
    209 
    210 bool HTMLInputElement::patternMismatch() const
    211 {
    212     switch (inputType()) {
    213         case BUTTON:
    214         case CHECKBOX:
    215         case COLOR:
    216         case DATE:
    217         case DATETIME:
    218         case DATETIMELOCAL:
    219         case FILE:
    220         case HIDDEN:
    221         case IMAGE:
    222         case ISINDEX:
    223         case MONTH:
    224         case NUMBER:
    225         case RADIO:
    226         case RANGE:
    227         case RESET:
    228         case SUBMIT:
    229         case TIME:
    230         case WEEK:
    231             return false;
    232         case EMAIL:
    233         case PASSWORD:
    234         case SEARCH:
    235         case TELEPHONE:
    236         case TEXT:
    237         case URL:
    238             const AtomicString& pattern = getAttribute(patternAttr);
    239             String value = this->value();
    240 
    241             // Empty values can't be mismatched
    242             if (pattern.isEmpty() || value.isEmpty())
    243                 return false;
    244 
    245             RegularExpression patternRegExp(pattern, TextCaseSensitive);
    246             int matchLength = 0;
    247             int valueLength = value.length();
    248             int matchOffset = patternRegExp.match(value, 0, &matchLength);
    249 
    250             return matchOffset != 0 || matchLength != valueLength;
    251     }
    252 
    253     ASSERT_NOT_REACHED();
    254     return false;
    255 }
    256 
    257 bool HTMLInputElement::tooLong() const
    258 {
    259     switch (inputType()) {
    260     case EMAIL:
    261     case PASSWORD:
    262     case SEARCH:
    263     case TELEPHONE:
    264     case TEXT:
    265     case URL: {
    266         int max = maxLength();
    267         if (max < 0)
    268             return false;
    269         // Return false for the default value even if it is longer than maxLength.
    270         bool userEdited = !m_data.value().isNull();
    271         if (!userEdited)
    272             return false;
    273         return value().numGraphemeClusters() > static_cast<unsigned>(max);
    274     }
    275     case BUTTON:
    276     case CHECKBOX:
    277     case COLOR:
    278     case DATE:
    279     case DATETIME:
    280     case DATETIMELOCAL:
    281     case FILE:
    282     case HIDDEN:
    283     case IMAGE:
    284     case ISINDEX:
    285     case MONTH:
    286     case NUMBER:
    287     case RADIO:
    288     case RANGE:
    289     case RESET:
    290     case SUBMIT:
    291     case TIME:
    292     case WEEK:
    293         return false;
    294     }
    295     ASSERT_NOT_REACHED();
    296     return false;
    297 }
    298 
    299 bool HTMLInputElement::rangeUnderflow() const
    300 {
    301     const double nan = numeric_limits<double>::quiet_NaN();
    302     switch (inputType()) {
    303     case DATE:
    304     case DATETIME:
    305     case DATETIMELOCAL:
    306     case MONTH:
    307     case NUMBER:
    308     case RANGE:
    309     case TIME:
    310     case WEEK: {
    311         double doubleValue = parseToDouble(value(), nan);
    312         return isfinite(doubleValue) && doubleValue < minimum();
    313     }
    314     case BUTTON:
    315     case CHECKBOX:
    316     case COLOR:
    317     case EMAIL:
    318     case FILE:
    319     case HIDDEN:
    320     case IMAGE:
    321     case ISINDEX:
    322     case PASSWORD:
    323     case RADIO:
    324     case RESET:
    325     case SEARCH:
    326     case SUBMIT:
    327     case TELEPHONE:
    328     case TEXT:
    329     case URL:
    330         break;
    331     }
    332     return false;
    333 }
    334 
    335 bool HTMLInputElement::rangeOverflow() const
    336 {
    337     const double nan = numeric_limits<double>::quiet_NaN();
    338     switch (inputType()) {
    339     case DATE:
    340     case DATETIME:
    341     case DATETIMELOCAL:
    342     case MONTH:
    343     case NUMBER:
    344     case RANGE:
    345     case TIME:
    346     case WEEK: {
    347         double doubleValue = parseToDouble(value(), nan);
    348         return isfinite(doubleValue) && doubleValue >  maximum();
    349     }
    350     case BUTTON:
    351     case CHECKBOX:
    352     case COLOR:
    353     case EMAIL:
    354     case FILE:
    355     case HIDDEN:
    356     case IMAGE:
    357     case ISINDEX:
    358     case PASSWORD:
    359     case RADIO:
    360     case RESET:
    361     case SEARCH:
    362     case SUBMIT:
    363     case TELEPHONE:
    364     case TEXT:
    365     case URL:
    366         break;
    367     }
    368     return false;
    369 }
    370 
    371 double HTMLInputElement::minimum() const
    372 {
    373     switch (inputType()) {
    374     case DATE:
    375         return parseToDouble(getAttribute(minAttr), dateDefaultMinimum);
    376     case DATETIME:
    377     case DATETIMELOCAL:
    378         return parseToDouble(getAttribute(minAttr), dateTimeDefaultMinimum);
    379     case MONTH:
    380         return parseToDouble(getAttribute(minAttr), monthDefaultMinimum);
    381     case NUMBER:
    382         return parseToDouble(getAttribute(minAttr), numberDefaultMinimum);
    383     case RANGE:
    384         return parseToDouble(getAttribute(minAttr), rangeDefaultMinimum);
    385     case TIME:
    386         return parseToDouble(getAttribute(minAttr), timeDefaultMinimum);
    387     case WEEK:
    388         return parseToDouble(getAttribute(minAttr), weekDefaultMinimum);
    389     case BUTTON:
    390     case CHECKBOX:
    391     case COLOR:
    392     case EMAIL:
    393     case FILE:
    394     case HIDDEN:
    395     case IMAGE:
    396     case ISINDEX:
    397     case PASSWORD:
    398     case RADIO:
    399     case RESET:
    400     case SEARCH:
    401     case SUBMIT:
    402     case TELEPHONE:
    403     case TEXT:
    404     case URL:
    405         break;
    406     }
    407     ASSERT_NOT_REACHED();
    408     return 0;
    409 }
    410 
    411 double HTMLInputElement::maximum() const
    412 {
    413     switch (inputType()) {
    414     case DATE:
    415         return parseToDouble(getAttribute(maxAttr), dateDefaultMaximum);
    416     case DATETIME:
    417     case DATETIMELOCAL:
    418         return parseToDouble(getAttribute(maxAttr), dateTimeDefaultMaximum);
    419     case MONTH:
    420         return parseToDouble(getAttribute(maxAttr), monthDefaultMaximum);
    421     case NUMBER:
    422         return parseToDouble(getAttribute(maxAttr), numberDefaultMaximum);
    423     case RANGE: {
    424         double max = parseToDouble(getAttribute(maxAttr), rangeDefaultMaximum);
    425         // A remedy for the inconsistent min/max values for RANGE.
    426         // Sets the maximum to the default or the minimum value.
    427         double min = minimum();
    428         if (max < min)
    429             max = std::max(min, rangeDefaultMaximum);
    430         return max;
    431     }
    432     case TIME:
    433         return parseToDouble(getAttribute(maxAttr), timeDefaultMaximum);
    434     case WEEK:
    435         return parseToDouble(getAttribute(maxAttr), weekDefaultMaximum);
    436     case BUTTON:
    437     case CHECKBOX:
    438     case COLOR:
    439     case EMAIL:
    440     case FILE:
    441     case HIDDEN:
    442     case IMAGE:
    443     case ISINDEX:
    444     case PASSWORD:
    445     case RADIO:
    446     case RESET:
    447     case SEARCH:
    448     case SUBMIT:
    449     case TELEPHONE:
    450     case TEXT:
    451     case URL:
    452         break;
    453     }
    454     ASSERT_NOT_REACHED();
    455     return 0;
    456 }
    457 
    458 double HTMLInputElement::stepBase() const
    459 {
    460     switch (inputType()) {
    461     case RANGE:
    462         return minimum();
    463     case DATE:
    464     case DATETIME:
    465     case DATETIMELOCAL:
    466     case MONTH:
    467     case NUMBER:
    468     case TIME:
    469         return parseToDouble(getAttribute(minAttr), defaultStepBase);
    470     case WEEK:
    471         return parseToDouble(getAttribute(minAttr), weekDefaultStepBase);
    472     case BUTTON:
    473     case CHECKBOX:
    474     case COLOR:
    475     case EMAIL:
    476     case FILE:
    477     case HIDDEN:
    478     case IMAGE:
    479     case ISINDEX:
    480     case PASSWORD:
    481     case RADIO:
    482     case RESET:
    483     case SEARCH:
    484     case SUBMIT:
    485     case TELEPHONE:
    486     case TEXT:
    487     case URL:
    488         break;
    489     }
    490     ASSERT_NOT_REACHED();
    491     return 0.0;
    492 }
    493 
    494 bool HTMLInputElement::stepMismatch() const
    495 {
    496     double step;
    497     if (!getAllowedValueStep(&step))
    498         return false;
    499     switch (inputType()) {
    500     case RANGE:
    501         // stepMismatch doesn't occur for RANGE. RenderSlider guarantees the
    502         // value matches to step.
    503         return false;
    504     case NUMBER: {
    505         double doubleValue;
    506         if (!formStringToDouble(value(), &doubleValue))
    507             return false;
    508         doubleValue = fabs(doubleValue - stepBase());
    509         if (isinf(doubleValue))
    510             return false;
    511         // double's fractional part size is DBL_MAN_DIG-bit.  If the current
    512         // value is greater than step*2^DBL_MANT_DIG, the following fmod() makes
    513         // no sense.
    514         if (doubleValue / pow(2.0, DBL_MANT_DIG) > step)
    515             return false;
    516         double remainder = fmod(doubleValue, step);
    517         // Accepts errors in lower 7-bit.
    518         double acceptableError = step / pow(2.0, DBL_MANT_DIG - 7);
    519         return acceptableError < remainder && remainder < (step - acceptableError);
    520     }
    521     case DATE:
    522     case DATETIME:
    523     case DATETIMELOCAL:
    524     case MONTH:
    525     case TIME:
    526     case WEEK: {
    527         const double nan = numeric_limits<double>::quiet_NaN();
    528         double doubleValue = parseToDouble(value(), nan);
    529         doubleValue = fabs(doubleValue - stepBase());
    530         if (!isfinite(doubleValue))
    531             return false;
    532         ASSERT(round(doubleValue) == doubleValue);
    533         ASSERT(round(step) == step);
    534         return fmod(doubleValue, step);
    535     }
    536     case BUTTON:
    537     case CHECKBOX:
    538     case COLOR:
    539     case EMAIL:
    540     case FILE:
    541     case HIDDEN:
    542     case IMAGE:
    543     case ISINDEX:
    544     case PASSWORD:
    545     case RADIO:
    546     case RESET:
    547     case SEARCH:
    548     case SUBMIT:
    549     case TELEPHONE:
    550     case TEXT:
    551     case URL:
    552         break;
    553     }
    554     // Non-supported types should be rejected by getAllowedValueStep().
    555     ASSERT_NOT_REACHED();
    556     return false;
    557 }
    558 
    559 bool HTMLInputElement::getStepParameters(double* defaultStep, double* stepScaleFactor) const
    560 {
    561     ASSERT(defaultStep);
    562     ASSERT(stepScaleFactor);
    563     switch (inputType()) {
    564     case NUMBER:
    565     case RANGE:
    566         *defaultStep = numberDefaultStep;
    567         *stepScaleFactor = numberStepScaleFactor;
    568         return true;
    569     case DATE:
    570         *defaultStep = dateDefaultStep;
    571         *stepScaleFactor = dateStepScaleFactor;
    572         return true;
    573     case DATETIME:
    574     case DATETIMELOCAL:
    575         *defaultStep = dateTimeDefaultStep;
    576         *stepScaleFactor = dateTimeStepScaleFactor;
    577         return true;
    578     case MONTH:
    579         *defaultStep = monthDefaultStep;
    580         *stepScaleFactor = monthStepScaleFactor;
    581         return true;
    582     case TIME:
    583         *defaultStep = timeDefaultStep;
    584         *stepScaleFactor = timeStepScaleFactor;
    585         return true;
    586     case WEEK:
    587         *defaultStep = weekDefaultStep;
    588         *stepScaleFactor = weekStepScaleFactor;
    589         return true;
    590     case BUTTON:
    591     case CHECKBOX:
    592     case COLOR:
    593     case EMAIL:
    594     case FILE:
    595     case HIDDEN:
    596     case IMAGE:
    597     case ISINDEX:
    598     case PASSWORD:
    599     case RADIO:
    600     case RESET:
    601     case SEARCH:
    602     case SUBMIT:
    603     case TELEPHONE:
    604     case TEXT:
    605     case URL:
    606         return false;
    607     }
    608     ASSERT_NOT_REACHED();
    609     return false;
    610 }
    611 
    612 bool HTMLInputElement::getAllowedValueStep(double* step) const
    613 {
    614     ASSERT(step);
    615     double defaultStep;
    616     double stepScaleFactor;
    617     if (!getStepParameters(&defaultStep, &stepScaleFactor))
    618         return false;
    619     const AtomicString& stepString = getAttribute(stepAttr);
    620     if (stepString.isEmpty()) {
    621         *step = defaultStep * stepScaleFactor;
    622         return true;
    623     }
    624     if (equalIgnoringCase(stepString, "any"))
    625         return false;
    626     double parsed;
    627     if (!formStringToDouble(stepString, &parsed) || parsed <= 0.0) {
    628         *step = defaultStep * stepScaleFactor;
    629         return true;
    630     }
    631     // For DATE, MONTH, WEEK, the parsed value should be an integer.
    632     if (inputType() == DATE || inputType() == MONTH || inputType() == WEEK)
    633         parsed = max(round(parsed), 1.0);
    634     double result = parsed * stepScaleFactor;
    635     // For DATETIME, DATETIMELOCAL, TIME, the result should be an integer.
    636     if (inputType() == DATETIME || inputType() == DATETIMELOCAL || inputType() == TIME)
    637         result = max(round(result), 1.0);
    638     ASSERT(result > 0);
    639     *step = result;
    640     return true;
    641 }
    642 
    643 void HTMLInputElement::applyStep(double count, ExceptionCode& ec)
    644 {
    645     double step;
    646     if (!getAllowedValueStep(&step)) {
    647         ec = INVALID_STATE_ERR;
    648         return;
    649     }
    650     const double nan = numeric_limits<double>::quiet_NaN();
    651     double current = parseToDouble(value(), nan);
    652     if (!isfinite(current)) {
    653         ec = INVALID_STATE_ERR;
    654         return;
    655     }
    656     double newValue = current + step * count;
    657     if (isinf(newValue)) {
    658         ec = INVALID_STATE_ERR;
    659         return;
    660     }
    661     if (newValue < minimum()) {
    662         ec = INVALID_STATE_ERR;
    663         return;
    664     }
    665     double base = stepBase();
    666     newValue = base + round((newValue - base) / step) * step;
    667     if (newValue > maximum()) {
    668         ec = INVALID_STATE_ERR;
    669         return;
    670     }
    671     setValueAsNumber(newValue, ec);
    672 }
    673 
    674 void HTMLInputElement::stepUp(int n, ExceptionCode& ec)
    675 {
    676     applyStep(n, ec);
    677 }
    678 
    679 void HTMLInputElement::stepDown(int n, ExceptionCode& ec)
    680 {
    681     applyStep(-n, ec);
    682 }
    683 
    684 static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement *element)
    685 {
    686     if (HTMLFormElement* form = element->form())
    687         return form->checkedRadioButtons();
    688 
    689     return element->document()->checkedRadioButtons();
    690 }
    691 
    692 bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
    693 {
    694     // If text fields can be focused, then they should always be keyboard focusable
    695     if (isTextField())
    696         return HTMLFormControlElementWithState::isFocusable();
    697 
    698     // If the base class says we can't be focused, then we can stop now.
    699     if (!HTMLFormControlElementWithState::isKeyboardFocusable(event))
    700         return false;
    701 
    702     if (inputType() == RADIO) {
    703 
    704         // Never allow keyboard tabbing to leave you in the same radio group.  Always
    705         // skip any other elements in the group.
    706         Node* currentFocusedNode = document()->focusedNode();
    707         if (currentFocusedNode && currentFocusedNode->hasTagName(inputTag)) {
    708             HTMLInputElement* focusedInput = static_cast<HTMLInputElement*>(currentFocusedNode);
    709             if (focusedInput->inputType() == RADIO && focusedInput->form() == form() &&
    710                 focusedInput->name() == name())
    711                 return false;
    712         }
    713 
    714         // Allow keyboard focus if we're checked or if nothing in the group is checked.
    715         return checked() || !checkedRadioButtons(this).checkedButtonForGroup(name());
    716     }
    717 
    718     return true;
    719 }
    720 
    721 bool HTMLInputElement::isMouseFocusable() const
    722 {
    723     if (isTextField())
    724         return HTMLFormControlElementWithState::isFocusable();
    725     return HTMLFormControlElementWithState::isMouseFocusable();
    726 }
    727 
    728 void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
    729 {
    730     if (isTextField())
    731         InputElement::updateFocusAppearance(m_data, this, this, restorePreviousSelection);
    732     else
    733         HTMLFormControlElementWithState::updateFocusAppearance(restorePreviousSelection);
    734 }
    735 
    736 void HTMLInputElement::aboutToUnload()
    737 {
    738     InputElement::aboutToUnload(this, this);
    739 }
    740 
    741 bool HTMLInputElement::shouldUseInputMethod() const
    742 {
    743     return m_type == TEXT || m_type == SEARCH || m_type == ISINDEX;
    744 }
    745 
    746 void HTMLInputElement::handleFocusEvent()
    747 {
    748     InputElement::dispatchFocusEvent(this, this);
    749 
    750     if (isTextField())
    751         m_autofilled = false;
    752 }
    753 
    754 void HTMLInputElement::handleBlurEvent()
    755 {
    756     InputElement::dispatchBlurEvent(this, this);
    757 }
    758 
    759 void HTMLInputElement::setType(const String& t)
    760 {
    761     if (t.isEmpty()) {
    762         int exccode;
    763         removeAttribute(typeAttr, exccode);
    764     } else
    765         setAttribute(typeAttr, t);
    766 }
    767 
    768 typedef HashMap<String, HTMLInputElement::InputType, CaseFoldingHash> InputTypeMap;
    769 static const InputTypeMap* createTypeMap()
    770 {
    771     InputTypeMap* map = new InputTypeMap;
    772     map->add("button", HTMLInputElement::BUTTON);
    773     map->add("checkbox", HTMLInputElement::CHECKBOX);
    774     map->add("color", HTMLInputElement::COLOR);
    775     map->add("date", HTMLInputElement::DATE);
    776     map->add("datetime", HTMLInputElement::DATETIME);
    777     map->add("datetime-local", HTMLInputElement::DATETIMELOCAL);
    778     map->add("email", HTMLInputElement::EMAIL);
    779     map->add("file", HTMLInputElement::FILE);
    780     map->add("hidden", HTMLInputElement::HIDDEN);
    781     map->add("image", HTMLInputElement::IMAGE);
    782     map->add("khtml_isindex", HTMLInputElement::ISINDEX);
    783     map->add("month", HTMLInputElement::MONTH);
    784     map->add("number", HTMLInputElement::NUMBER);
    785     map->add("password", HTMLInputElement::PASSWORD);
    786     map->add("radio", HTMLInputElement::RADIO);
    787     map->add("range", HTMLInputElement::RANGE);
    788     map->add("reset", HTMLInputElement::RESET);
    789     map->add("search", HTMLInputElement::SEARCH);
    790     map->add("submit", HTMLInputElement::SUBMIT);
    791     map->add("tel", HTMLInputElement::TELEPHONE);
    792     map->add("time", HTMLInputElement::TIME);
    793     map->add("url", HTMLInputElement::URL);
    794     map->add("week", HTMLInputElement::WEEK);
    795     // No need to register "text" because it is the default type.
    796     return map;
    797 }
    798 
    799 void HTMLInputElement::setInputType(const String& t)
    800 {
    801     static const InputTypeMap* typeMap = createTypeMap();
    802     InputType newType = t.isNull() ? TEXT : typeMap->get(t);
    803 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
    804     if (newType == PASSWORD && document()->focusedNode() == this)
    805         android::WebViewCore::getWebViewCore(document()->view())->updateTextfield(this, true, String());
    806 #endif
    807 
    808     // IMPORTANT: Don't allow the type to be changed to FILE after the first
    809     // type change, otherwise a JavaScript programmer would be able to set a text
    810     // field's value to something like /etc/passwd and then change it to a file field.
    811     if (inputType() != newType) {
    812         bool oldWillValidate = willValidate();
    813         if (newType == FILE && m_haveType)
    814             // Set the attribute back to the old value.
    815             // Useful in case we were called from inside parseMappedAttribute.
    816             setAttribute(typeAttr, type());
    817         else {
    818             checkedRadioButtons(this).removeButton(this);
    819 
    820             if (newType == FILE && !m_fileList)
    821                 m_fileList = FileList::create();
    822 
    823             bool wasAttached = attached();
    824             if (wasAttached)
    825                 detach();
    826 
    827             bool didStoreValue = storesValueSeparateFromAttribute();
    828             bool wasPasswordField = inputType() == PASSWORD;
    829             bool didRespectHeightAndWidth = respectHeightAndWidthAttrs();
    830             m_type = newType;
    831             bool willStoreValue = storesValueSeparateFromAttribute();
    832             bool isPasswordField = inputType() == PASSWORD;
    833             bool willRespectHeightAndWidth = respectHeightAndWidthAttrs();
    834 
    835             if (didStoreValue && !willStoreValue && !m_data.value().isNull()) {
    836                 setAttribute(valueAttr, m_data.value());
    837                 m_data.setValue(String());
    838             }
    839             if (!didStoreValue && willStoreValue)
    840                 m_data.setValue(sanitizeValue(getAttribute(valueAttr)));
    841             else
    842                 InputElement::updateValueIfNeeded(m_data, this);
    843 
    844             if (wasPasswordField && !isPasswordField)
    845                 unregisterForActivationCallbackIfNeeded();
    846             else if (!wasPasswordField && isPasswordField)
    847                 registerForActivationCallbackIfNeeded();
    848 
    849             if (didRespectHeightAndWidth != willRespectHeightAndWidth) {
    850                 NamedMappedAttrMap* map = mappedAttributes();
    851                 ASSERT(map);
    852                 if (Attribute* height = map->getAttributeItem(heightAttr))
    853                     attributeChanged(height, false);
    854                 if (Attribute* width = map->getAttributeItem(widthAttr))
    855                     attributeChanged(width, false);
    856                 if (Attribute* align = map->getAttributeItem(alignAttr))
    857                     attributeChanged(align, false);
    858             }
    859 
    860             if (wasAttached) {
    861                 attach();
    862                 if (document()->focusedNode() == this)
    863                     updateFocusAppearance(true);
    864             }
    865 
    866             checkedRadioButtons(this).addButton(this);
    867         }
    868 
    869         setNeedsValidityCheck();
    870         if (oldWillValidate != willValidate())
    871             setNeedsWillValidateCheck();
    872         InputElement::notifyFormStateChanged(this);
    873     }
    874     m_haveType = true;
    875 
    876     if (inputType() != IMAGE && m_imageLoader)
    877         m_imageLoader.clear();
    878 }
    879 
    880 static const AtomicString* createFormControlTypes()
    881 {
    882     AtomicString* types = new AtomicString[HTMLInputElement::numberOfTypes];
    883     // The values must be lowercased because they will be the return values of
    884     //  input.type and it must be lowercase according to DOM Level 2.
    885     types[HTMLInputElement::BUTTON] = "button";
    886     types[HTMLInputElement::CHECKBOX] = "checkbox";
    887     types[HTMLInputElement::COLOR] = "color";
    888     types[HTMLInputElement::DATE] = "date";
    889     types[HTMLInputElement::DATETIME] = "datetime";
    890     types[HTMLInputElement::DATETIMELOCAL] = "datetime-local";
    891     types[HTMLInputElement::EMAIL] = "email";
    892     types[HTMLInputElement::FILE] = "file";
    893     types[HTMLInputElement::HIDDEN] = "hidden";
    894     types[HTMLInputElement::IMAGE] = "image";
    895     types[HTMLInputElement::ISINDEX] = emptyAtom;
    896     types[HTMLInputElement::MONTH] = "month";
    897     types[HTMLInputElement::NUMBER] = "number";
    898     types[HTMLInputElement::PASSWORD] = "password";
    899     types[HTMLInputElement::RADIO] = "radio";
    900     types[HTMLInputElement::RANGE] = "range";
    901     types[HTMLInputElement::RESET] = "reset";
    902     types[HTMLInputElement::SEARCH] = "search";
    903     types[HTMLInputElement::SUBMIT] = "submit";
    904     types[HTMLInputElement::TELEPHONE] = "tel";
    905     types[HTMLInputElement::TEXT] = "text";
    906     types[HTMLInputElement::TIME] = "time";
    907     types[HTMLInputElement::URL] = "url";
    908     types[HTMLInputElement::WEEK] = "week";
    909     return types;
    910 }
    911 
    912 const AtomicString& HTMLInputElement::formControlType() const
    913 {
    914     static const AtomicString* formControlTypes = createFormControlTypes();
    915     return formControlTypes[inputType()];
    916 }
    917 
    918 bool HTMLInputElement::saveFormControlState(String& result) const
    919 {
    920     if (!autoComplete())
    921         return false;
    922 
    923     switch (inputType()) {
    924         case BUTTON:
    925         case COLOR:
    926         case DATE:
    927         case DATETIME:
    928         case DATETIMELOCAL:
    929         case EMAIL:
    930         case FILE:
    931         case HIDDEN:
    932         case IMAGE:
    933         case ISINDEX:
    934         case MONTH:
    935         case NUMBER:
    936         case RANGE:
    937         case RESET:
    938         case SEARCH:
    939         case SUBMIT:
    940         case TELEPHONE:
    941         case TEXT:
    942         case TIME:
    943         case URL:
    944         case WEEK:
    945             result = value();
    946             return true;
    947         case CHECKBOX:
    948         case RADIO:
    949             result = checked() ? "on" : "off";
    950             return true;
    951         case PASSWORD:
    952             return false;
    953     }
    954     ASSERT_NOT_REACHED();
    955     return false;
    956 }
    957 
    958 void HTMLInputElement::restoreFormControlState(const String& state)
    959 {
    960     ASSERT(inputType() != PASSWORD); // should never save/restore password fields
    961     switch (inputType()) {
    962         case BUTTON:
    963         case COLOR:
    964         case DATE:
    965         case DATETIME:
    966         case DATETIMELOCAL:
    967         case EMAIL:
    968         case FILE:
    969         case HIDDEN:
    970         case IMAGE:
    971         case ISINDEX:
    972         case MONTH:
    973         case NUMBER:
    974         case RANGE:
    975         case RESET:
    976         case SEARCH:
    977         case SUBMIT:
    978         case TELEPHONE:
    979         case TEXT:
    980         case TIME:
    981         case URL:
    982         case WEEK:
    983             setValue(state);
    984             break;
    985         case CHECKBOX:
    986         case RADIO:
    987             setChecked(state == "on");
    988             break;
    989         case PASSWORD:
    990             break;
    991     }
    992 }
    993 
    994 bool HTMLInputElement::canStartSelection() const
    995 {
    996     if (!isTextField())
    997         return false;
    998     return HTMLFormControlElementWithState::canStartSelection();
    999 }
   1000 
   1001 bool HTMLInputElement::canHaveSelection() const
   1002 {
   1003     return isTextField();
   1004 }
   1005 
   1006 void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
   1007 {
   1008     switch (inputType()) {
   1009         case BUTTON:
   1010         case CHECKBOX:
   1011         case FILE:
   1012         case IMAGE:
   1013         case RADIO:
   1014         case RANGE:
   1015         case RESET:
   1016         case SUBMIT:
   1017             focus(false);
   1018             // send the mouse button events iff the caller specified sendToAnyElement
   1019             dispatchSimulatedClick(0, sendToAnyElement);
   1020             break;
   1021         case HIDDEN:
   1022             // a no-op for this type
   1023             break;
   1024         case COLOR:
   1025         case DATE:
   1026         case DATETIME:
   1027         case DATETIMELOCAL:
   1028         case EMAIL:
   1029         case ISINDEX:
   1030         case MONTH:
   1031         case NUMBER:
   1032         case PASSWORD:
   1033         case SEARCH:
   1034         case TELEPHONE:
   1035         case TEXT:
   1036         case TIME:
   1037         case URL:
   1038         case WEEK:
   1039             // should never restore previous selection here
   1040             focus(false);
   1041             break;
   1042     }
   1043 }
   1044 
   1045 bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
   1046 {
   1047     if (((attrName == heightAttr || attrName == widthAttr) && respectHeightAndWidthAttrs()) ||
   1048         attrName == vspaceAttr ||
   1049         attrName == hspaceAttr) {
   1050         result = eUniversal;
   1051         return false;
   1052     }
   1053 
   1054     if (attrName == alignAttr) {
   1055         if (inputType() == IMAGE) {
   1056             // Share with <img> since the alignment behavior is the same.
   1057             result = eReplaced;
   1058             return false;
   1059         }
   1060     }
   1061 
   1062     return HTMLElement::mapToEntry(attrName, result);
   1063 }
   1064 
   1065 void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
   1066 {
   1067     if (attr->name() == nameAttr) {
   1068         checkedRadioButtons(this).removeButton(this);
   1069         m_data.setName(attr->value());
   1070         checkedRadioButtons(this).addButton(this);
   1071         HTMLFormControlElementWithState::parseMappedAttribute(attr);
   1072     } else if (attr->name() == autocompleteAttr) {
   1073         if (equalIgnoringCase(attr->value(), "off")) {
   1074             m_autocomplete = Off;
   1075             registerForActivationCallbackIfNeeded();
   1076         } else {
   1077             bool needsToUnregister = m_autocomplete == Off;
   1078 
   1079             if (attr->isEmpty())
   1080                 m_autocomplete = Uninitialized;
   1081             else
   1082                 m_autocomplete = On;
   1083 
   1084             if (needsToUnregister)
   1085                 unregisterForActivationCallbackIfNeeded();
   1086         }
   1087     } else if (attr->name() == typeAttr) {
   1088         setInputType(attr->value());
   1089     } else if (attr->name() == valueAttr) {
   1090         // We only need to setChanged if the form is looking at the default value right now.
   1091         if (m_data.value().isNull())
   1092             setNeedsStyleRecalc();
   1093         setFormControlValueMatchesRenderer(false);
   1094         setNeedsValidityCheck();
   1095     } else if (attr->name() == checkedAttr) {
   1096         m_defaultChecked = !attr->isNull();
   1097         if (m_useDefaultChecked) {
   1098             setChecked(m_defaultChecked);
   1099             m_useDefaultChecked = true;
   1100         }
   1101         setNeedsValidityCheck();
   1102     } else if (attr->name() == maxlengthAttr) {
   1103         InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
   1104         setNeedsValidityCheck();
   1105     } else if (attr->name() == sizeAttr)
   1106         InputElement::parseSizeAttribute(m_data, this, attr);
   1107     else if (attr->name() == altAttr) {
   1108         if (renderer() && inputType() == IMAGE)
   1109             toRenderImage(renderer())->updateAltText();
   1110     } else if (attr->name() == srcAttr) {
   1111         if (renderer() && inputType() == IMAGE) {
   1112             if (!m_imageLoader)
   1113                 m_imageLoader.set(new HTMLImageLoader(this));
   1114             m_imageLoader->updateFromElementIgnoringPreviousError();
   1115         }
   1116     } else if (attr->name() == usemapAttr ||
   1117                attr->name() == accesskeyAttr) {
   1118         // FIXME: ignore for the moment
   1119     } else if (attr->name() == vspaceAttr) {
   1120         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
   1121         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
   1122     } else if (attr->name() == hspaceAttr) {
   1123         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
   1124         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
   1125     } else if (attr->name() == alignAttr) {
   1126         if (inputType() == IMAGE)
   1127             addHTMLAlignment(attr);
   1128     } else if (attr->name() == widthAttr) {
   1129         if (respectHeightAndWidthAttrs())
   1130             addCSSLength(attr, CSSPropertyWidth, attr->value());
   1131     } else if (attr->name() == heightAttr) {
   1132         if (respectHeightAndWidthAttrs())
   1133             addCSSLength(attr, CSSPropertyHeight, attr->value());
   1134     }
   1135     // Search field and slider attributes all just cause updateFromElement to be called through style
   1136     // recalcing.
   1137     else if (attr->name() == onsearchAttr) {
   1138         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
   1139     } else if (attr->name() == resultsAttr) {
   1140         int oldResults = m_maxResults;
   1141         m_maxResults = !attr->isNull() ? std::min(attr->value().toInt(), maxSavedResults) : -1;
   1142         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
   1143         // time to relayout for this change.
   1144         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
   1145             detach();
   1146             attach();
   1147         }
   1148         setNeedsStyleRecalc();
   1149     } else if (attr->name() == autosaveAttr
   1150                || attr->name() == incrementalAttr)
   1151         setNeedsStyleRecalc();
   1152     else if (attr->name() == minAttr
   1153              || attr->name() == maxAttr
   1154              || attr->name() == multipleAttr
   1155              || attr->name() == patternAttr
   1156              || attr->name() == precisionAttr
   1157              || attr->name() == stepAttr)
   1158         setNeedsValidityCheck();
   1159 #if ENABLE(DATALIST)
   1160     else if (attr->name() == listAttr)
   1161         m_hasNonEmptyList = !attr->isEmpty();
   1162         // FIXME: we need to tell this change to a renderer if the attribute affects the appearance.
   1163 #endif
   1164     else
   1165         HTMLTextFormControlElement::parseMappedAttribute(attr);
   1166 }
   1167 
   1168 bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
   1169 {
   1170     if (inputType() == HIDDEN)
   1171         return false;
   1172     return HTMLFormControlElementWithState::rendererIsNeeded(style);
   1173 }
   1174 
   1175 RenderObject *HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle *style)
   1176 {
   1177     switch (inputType()) {
   1178         case BUTTON:
   1179         case RESET:
   1180         case SUBMIT:
   1181             return new (arena) RenderButton(this);
   1182         case CHECKBOX:
   1183         case RADIO:
   1184             return RenderObject::createObject(this, style);
   1185         case FILE:
   1186             return new (arena) RenderFileUploadControl(this);
   1187         case HIDDEN:
   1188             break;
   1189         case IMAGE:
   1190             return new (arena) RenderImage(this);
   1191         case RANGE:
   1192             return new (arena) RenderSlider(this);
   1193         case COLOR:
   1194         case DATE:
   1195         case DATETIME:
   1196         case DATETIMELOCAL:
   1197         case EMAIL:
   1198         case ISINDEX:
   1199         case MONTH:
   1200         case NUMBER:
   1201         case PASSWORD:
   1202         case SEARCH:
   1203         case TELEPHONE:
   1204         case TEXT:
   1205         case TIME:
   1206         case URL:
   1207         case WEEK:
   1208             return new (arena) RenderTextControlSingleLine(this, placeholderShouldBeVisible());
   1209     }
   1210     ASSERT(false);
   1211     return 0;
   1212 }
   1213 
   1214 void HTMLInputElement::attach()
   1215 {
   1216     if (!m_inited) {
   1217         if (!m_haveType)
   1218             setInputType(getAttribute(typeAttr));
   1219         m_inited = true;
   1220     }
   1221 
   1222     HTMLFormControlElementWithState::attach();
   1223 
   1224     if (inputType() == IMAGE) {
   1225         if (!m_imageLoader)
   1226             m_imageLoader.set(new HTMLImageLoader(this));
   1227         m_imageLoader->updateFromElement();
   1228         if (renderer() && m_imageLoader->haveFiredBeforeLoadEvent()) {
   1229             RenderImage* imageObj = toRenderImage(renderer());
   1230             imageObj->setCachedImage(m_imageLoader->image());
   1231 
   1232             // If we have no image at all because we have no src attribute, set
   1233             // image height and width for the alt text instead.
   1234             if (!m_imageLoader->image() && !imageObj->cachedImage())
   1235                 imageObj->setImageSizeForAltText();
   1236         }
   1237     }
   1238 
   1239     if (document()->focusedNode() == this)
   1240         document()->updateFocusAppearanceSoon(true /* restore selection */);
   1241 }
   1242 
   1243 void HTMLInputElement::detach()
   1244 {
   1245     HTMLFormControlElementWithState::detach();
   1246     setFormControlValueMatchesRenderer(false);
   1247 }
   1248 
   1249 String HTMLInputElement::altText() const
   1250 {
   1251     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
   1252     // also heavily discussed by Hixie on bugzilla
   1253     // note this is intentionally different to HTMLImageElement::altText()
   1254     String alt = getAttribute(altAttr);
   1255     // fall back to title attribute
   1256     if (alt.isNull())
   1257         alt = getAttribute(titleAttr);
   1258     if (alt.isNull())
   1259         alt = getAttribute(valueAttr);
   1260     if (alt.isEmpty())
   1261         alt = inputElementAltText();
   1262     return alt;
   1263 }
   1264 
   1265 bool HTMLInputElement::isSuccessfulSubmitButton() const
   1266 {
   1267     // HTML spec says that buttons must have names to be considered successful.
   1268     // However, other browsers do not impose this constraint. So we do likewise.
   1269     return !disabled() && (inputType() == IMAGE || inputType() == SUBMIT);
   1270 }
   1271 
   1272 bool HTMLInputElement::isActivatedSubmit() const
   1273 {
   1274     return m_activeSubmit;
   1275 }
   1276 
   1277 void HTMLInputElement::setActivatedSubmit(bool flag)
   1278 {
   1279     m_activeSubmit = flag;
   1280 }
   1281 
   1282 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
   1283 {
   1284     // image generates its own names, but for other types there is no form data unless there's a name
   1285     if (name().isEmpty() && inputType() != IMAGE)
   1286         return false;
   1287 
   1288     switch (inputType()) {
   1289         case COLOR:
   1290         case DATE:
   1291         case DATETIME:
   1292         case DATETIMELOCAL:
   1293         case EMAIL:
   1294         case HIDDEN:
   1295         case ISINDEX:
   1296         case MONTH:
   1297         case NUMBER:
   1298         case PASSWORD:
   1299         case RANGE:
   1300         case SEARCH:
   1301         case TELEPHONE:
   1302         case TEXT:
   1303         case TIME:
   1304         case URL:
   1305         case WEEK:
   1306             // always successful
   1307             encoding.appendData(name(), value());
   1308             return true;
   1309 
   1310         case CHECKBOX:
   1311         case RADIO:
   1312             if (checked()) {
   1313                 encoding.appendData(name(), value());
   1314                 return true;
   1315             }
   1316             break;
   1317 
   1318         case BUTTON:
   1319         case RESET:
   1320             // these types of buttons are never successful
   1321             return false;
   1322 
   1323         case IMAGE:
   1324             if (m_activeSubmit) {
   1325                 encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), m_xPos);
   1326                 encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), m_yPos);
   1327                 if (!name().isEmpty() && !value().isEmpty())
   1328                     encoding.appendData(name(), value());
   1329                 return true;
   1330             }
   1331             break;
   1332 
   1333         case SUBMIT:
   1334             if (m_activeSubmit) {
   1335                 String enc_str = valueWithDefault();
   1336                 encoding.appendData(name(), enc_str);
   1337                 return true;
   1338             }
   1339             break;
   1340 
   1341         case FILE: {
   1342             unsigned numFiles = m_fileList->length();
   1343             if (!multipart) {
   1344                 // Send only the basenames.
   1345                 // 4.10.16.4 and 4.10.16.6 sections in HTML5.
   1346 
   1347                 // Unlike the multipart case, we have no special
   1348                 // handling for the empty fileList because Netscape
   1349                 // doesn't support for non-multipart submission of
   1350                 // file inputs, and Firefox doesn't add "name=" query
   1351                 // parameter.
   1352 
   1353                 for (unsigned i = 0; i < numFiles; ++i) {
   1354                     encoding.appendData(name(), m_fileList->item(i)->fileName());
   1355                 }
   1356                 return true;
   1357             }
   1358 
   1359             // If no filename at all is entered, return successful but empty.
   1360             // Null would be more logical, but Netscape posts an empty file. Argh.
   1361             if (!numFiles) {
   1362                 encoding.appendFile(name(), File::create(""));
   1363                 return true;
   1364             }
   1365 
   1366             for (unsigned i = 0; i < numFiles; ++i)
   1367                 encoding.appendFile(name(), m_fileList->item(i));
   1368             return true;
   1369         }
   1370     }
   1371     return false;
   1372 }
   1373 
   1374 void HTMLInputElement::reset()
   1375 {
   1376     if (storesValueSeparateFromAttribute())
   1377         setValue(String());
   1378 
   1379     setChecked(m_defaultChecked);
   1380     m_useDefaultChecked = true;
   1381 }
   1382 
   1383 bool HTMLInputElement::isTextField() const
   1384 {
   1385     switch (inputType()) {
   1386     case COLOR:
   1387     case DATE:
   1388     case DATETIME:
   1389     case DATETIMELOCAL:
   1390     case EMAIL:
   1391     case ISINDEX:
   1392     case MONTH:
   1393     case NUMBER:
   1394     case PASSWORD:
   1395     case SEARCH:
   1396     case TELEPHONE:
   1397     case TEXT:
   1398     case TIME:
   1399     case URL:
   1400     case WEEK:
   1401         return true;
   1402     case BUTTON:
   1403     case CHECKBOX:
   1404     case FILE:
   1405     case HIDDEN:
   1406     case IMAGE:
   1407     case RADIO:
   1408     case RANGE:
   1409     case RESET:
   1410     case SUBMIT:
   1411         return false;
   1412     }
   1413     ASSERT_NOT_REACHED();
   1414     return false;
   1415 }
   1416 
   1417 void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
   1418 {
   1419     if (checked() == nowChecked)
   1420         return;
   1421 
   1422     checkedRadioButtons(this).removeButton(this);
   1423 
   1424     m_useDefaultChecked = false;
   1425     m_checked = nowChecked;
   1426     setNeedsStyleRecalc();
   1427 
   1428     checkedRadioButtons(this).addButton(this);
   1429 
   1430     if (renderer() && renderer()->style()->hasAppearance())
   1431         renderer()->theme()->stateChanged(renderer(), CheckedState);
   1432 
   1433     // Ideally we'd do this from the render tree (matching
   1434     // RenderTextView), but it's not possible to do it at the moment
   1435     // because of the way the code is structured.
   1436     if (renderer() && AXObjectCache::accessibilityEnabled())
   1437         renderer()->document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXCheckedStateChanged, true);
   1438 
   1439     // Only send a change event for items in the document (avoid firing during
   1440     // parsing) and don't send a change event for a radio button that's getting
   1441     // unchecked to match other browsers. DOM is not a useful standard for this
   1442     // because it says only to fire change events at "lose focus" time, which is
   1443     // definitely wrong in practice for these types of elements.
   1444     if (sendChangeEvent && inDocument() && (inputType() != RADIO || nowChecked))
   1445         dispatchFormControlChangeEvent();
   1446 }
   1447 
   1448 void HTMLInputElement::setIndeterminate(bool _indeterminate)
   1449 {
   1450     // Only checkboxes honor indeterminate.
   1451     if (inputType() != CHECKBOX || indeterminate() == _indeterminate)
   1452         return;
   1453 
   1454     m_indeterminate = _indeterminate;
   1455 
   1456     setNeedsStyleRecalc();
   1457 
   1458     if (renderer() && renderer()->style()->hasAppearance())
   1459         renderer()->theme()->stateChanged(renderer(), CheckedState);
   1460 }
   1461 
   1462 int HTMLInputElement::size() const
   1463 {
   1464     return m_data.size();
   1465 }
   1466 
   1467 void HTMLInputElement::copyNonAttributeProperties(const Element* source)
   1468 {
   1469     const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
   1470 
   1471     m_data.setValue(sourceElement->m_data.value());
   1472     setChecked(sourceElement->m_checked);
   1473     m_defaultChecked = sourceElement->m_defaultChecked;
   1474     m_useDefaultChecked = sourceElement->m_useDefaultChecked;
   1475     m_indeterminate = sourceElement->m_indeterminate;
   1476 
   1477     HTMLFormControlElementWithState::copyNonAttributeProperties(source);
   1478 }
   1479 
   1480 String HTMLInputElement::value() const
   1481 {
   1482     // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
   1483     // but we don't want to break existing websites, who may be relying on being able to get the file name as a value.
   1484     if (inputType() == FILE) {
   1485         if (!m_fileList->isEmpty())
   1486             return m_fileList->item(0)->fileName();
   1487         return String();
   1488     }
   1489 
   1490     String value = m_data.value();
   1491     if (value.isNull()) {
   1492         value = sanitizeValue(getAttribute(valueAttr));
   1493 
   1494         // If no attribute exists, then just use "on" or "" based off the checked() state of the control.
   1495         if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO))
   1496             return checked() ? "on" : "";
   1497     }
   1498 
   1499     return value;
   1500 }
   1501 
   1502 String HTMLInputElement::valueWithDefault() const
   1503 {
   1504     String v = value();
   1505     if (v.isNull()) {
   1506         switch (inputType()) {
   1507             case BUTTON:
   1508             case CHECKBOX:
   1509             case COLOR:
   1510             case DATE:
   1511             case DATETIME:
   1512             case DATETIMELOCAL:
   1513             case EMAIL:
   1514             case FILE:
   1515             case HIDDEN:
   1516             case IMAGE:
   1517             case ISINDEX:
   1518             case MONTH:
   1519             case NUMBER:
   1520             case PASSWORD:
   1521             case RADIO:
   1522             case RANGE:
   1523             case SEARCH:
   1524             case TELEPHONE:
   1525             case TEXT:
   1526             case TIME:
   1527             case URL:
   1528             case WEEK:
   1529                 break;
   1530             case RESET:
   1531                 v = resetButtonDefaultLabel();
   1532                 break;
   1533             case SUBMIT:
   1534                 v = submitButtonDefaultLabel();
   1535                 break;
   1536         }
   1537     }
   1538     return v;
   1539 }
   1540 
   1541 void HTMLInputElement::setValueForUser(const String& value)
   1542 {
   1543     // Call setValue and make it send a change event.
   1544     setValue(value, true);
   1545 }
   1546 
   1547 const String& HTMLInputElement::suggestedValue() const
   1548 {
   1549     return m_data.suggestedValue();
   1550 }
   1551 
   1552 void HTMLInputElement::setSuggestedValue(const String& value)
   1553 {
   1554     if (inputType() != TEXT)
   1555         return;
   1556     setFormControlValueMatchesRenderer(false);
   1557     m_data.setSuggestedValue(sanitizeValue(value));
   1558     updatePlaceholderVisibility(false);
   1559     if (renderer())
   1560         renderer()->updateFromElement();
   1561     setNeedsStyleRecalc();
   1562 }
   1563 
   1564 void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
   1565 {
   1566     // For security reasons, we don't allow setting the filename, but we do allow clearing it.
   1567     // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
   1568     // but we don't want to break existing websites, who may be relying on this method to clear things.
   1569     if (inputType() == FILE && !value.isEmpty())
   1570         return;
   1571 
   1572     setFormControlValueMatchesRenderer(false);
   1573     if (storesValueSeparateFromAttribute()) {
   1574         if (inputType() == FILE)
   1575             m_fileList->clear();
   1576         else {
   1577             m_data.setValue(sanitizeValue(value));
   1578             if (isTextField()) {
   1579                 updatePlaceholderVisibility(false);
   1580                 if (inDocument())
   1581                     document()->updateStyleIfNeeded();
   1582             }
   1583         }
   1584         if (renderer())
   1585             renderer()->updateFromElement();
   1586         setNeedsStyleRecalc();
   1587     } else
   1588         setAttribute(valueAttr, sanitizeValue(value));
   1589 
   1590     if (isTextField()) {
   1591         unsigned max = m_data.value().length();
   1592 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
   1593         // Make sure our UI side textfield changes to match the RenderTextControl
   1594         android::WebViewCore::getWebViewCore(document()->view())->updateTextfield(this, false, value);
   1595 #endif
   1596         if (document()->focusedNode() == this)
   1597             InputElement::updateSelectionRange(this, this, max, max);
   1598         else
   1599             cacheSelection(max, max);
   1600         m_data.setSuggestedValue(String());
   1601     }
   1602 
   1603     // Don't dispatch the change event when focused, it will be dispatched
   1604     // when the control loses focus.
   1605     if (sendChangeEvent && document()->focusedNode() != this)
   1606         dispatchFormControlChangeEvent();
   1607 
   1608     InputElement::notifyFormStateChanged(this);
   1609     setNeedsValidityCheck();
   1610 }
   1611 
   1612 double HTMLInputElement::parseToDouble(const String& src, double defaultValue) const
   1613 {
   1614     switch (inputType()) {
   1615     case DATE:
   1616     case DATETIME:
   1617     case DATETIMELOCAL:
   1618     case TIME:
   1619     case WEEK: {
   1620         DateComponents date;
   1621         if (!formStringToDateComponents(inputType(), src, &date))
   1622             return defaultValue;
   1623         double msec = date.millisecondsSinceEpoch();
   1624         ASSERT(isfinite(msec));
   1625         return msec;
   1626     }
   1627     case MONTH: {
   1628         DateComponents date;
   1629         if (!formStringToDateComponents(inputType(), src, &date))
   1630             return defaultValue;
   1631         double months = date.monthsSinceEpoch();
   1632         ASSERT(isfinite(months));
   1633         return months;
   1634     }
   1635     case NUMBER:
   1636     case RANGE: {
   1637         double numberValue;
   1638         if (!formStringToDouble(src, &numberValue))
   1639             return defaultValue;
   1640         ASSERT(isfinite(numberValue));
   1641         return numberValue;
   1642     }
   1643 
   1644     case BUTTON:
   1645     case CHECKBOX:
   1646     case COLOR:
   1647     case EMAIL:
   1648     case FILE:
   1649     case HIDDEN:
   1650     case IMAGE:
   1651     case ISINDEX:
   1652     case PASSWORD:
   1653     case RADIO:
   1654     case RESET:
   1655     case SEARCH:
   1656     case SUBMIT:
   1657     case TELEPHONE:
   1658     case TEXT:
   1659     case URL:
   1660         return defaultValue;
   1661     }
   1662     ASSERT_NOT_REACHED();
   1663     return defaultValue;
   1664 }
   1665 
   1666 double HTMLInputElement::valueAsDate() const
   1667 {
   1668     switch (inputType()) {
   1669     case DATE:
   1670     case DATETIME:
   1671     case TIME:
   1672     case WEEK:
   1673         return parseToDouble(value(), DateComponents::invalidMilliseconds());
   1674     case MONTH: {
   1675         DateComponents date;
   1676         if (!formStringToDateComponents(inputType(), value(), &date))
   1677             return DateComponents::invalidMilliseconds();
   1678         double msec = date.millisecondsSinceEpoch();
   1679         ASSERT(isfinite(msec));
   1680         return msec;
   1681     }
   1682 
   1683     case BUTTON:
   1684     case CHECKBOX:
   1685     case COLOR:
   1686     case DATETIMELOCAL: // valueAsDate doesn't work for the DATETIMELOCAL type according to the standard.
   1687     case EMAIL:
   1688     case FILE:
   1689     case HIDDEN:
   1690     case IMAGE:
   1691     case ISINDEX:
   1692     case NUMBER:
   1693     case PASSWORD:
   1694     case RADIO:
   1695     case RANGE:
   1696     case RESET:
   1697     case SEARCH:
   1698     case SUBMIT:
   1699     case TELEPHONE:
   1700     case TEXT:
   1701     case URL:
   1702         return DateComponents::invalidMilliseconds();
   1703     }
   1704     ASSERT_NOT_REACHED();
   1705     return DateComponents::invalidMilliseconds();
   1706 }
   1707 
   1708 void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec)
   1709 {
   1710     DateComponents date;
   1711     bool success;
   1712     switch (inputType()) {
   1713     case DATE:
   1714         success = date.setMillisecondsSinceEpochForDate(value);
   1715         break;
   1716     case DATETIME:
   1717         success = date.setMillisecondsSinceEpochForDateTime(value);
   1718         break;
   1719     case MONTH:
   1720         success = date.setMillisecondsSinceEpochForMonth(value);
   1721         break;
   1722     case TIME:
   1723         success = date.setMillisecondsSinceMidnight(value);
   1724         break;
   1725     case WEEK:
   1726         success = date.setMillisecondsSinceEpochForWeek(value);
   1727         break;
   1728     case BUTTON:
   1729     case CHECKBOX:
   1730     case COLOR:
   1731     case DATETIMELOCAL: // valueAsDate doesn't work for the DATETIMELOCAL type according to the standard.
   1732     case EMAIL:
   1733     case FILE:
   1734     case HIDDEN:
   1735     case IMAGE:
   1736     case ISINDEX:
   1737     case NUMBER:
   1738     case PASSWORD:
   1739     case RADIO:
   1740     case RANGE:
   1741     case RESET:
   1742     case SEARCH:
   1743     case SUBMIT:
   1744     case TELEPHONE:
   1745     case TEXT:
   1746     case URL:
   1747         ec = INVALID_STATE_ERR;
   1748         return;
   1749     default:
   1750         ASSERT_NOT_REACHED();
   1751         success = false;
   1752     }
   1753     if (!success) {
   1754         setValue(String());
   1755         return;
   1756     }
   1757     setDateValue(date);
   1758 }
   1759 
   1760 void HTMLInputElement::setDateValue(const DateComponents& date)
   1761 {
   1762     double step;
   1763     if (!getAllowedValueStep(&step)) {
   1764         setValue(date.toString());
   1765         return;
   1766     }
   1767     if (!fmod(step, msecPerMinute)) {
   1768         setValue(date.toString(DateComponents::None));
   1769         return;
   1770     }
   1771     if (!fmod(step, msecPerSecond)) {
   1772         setValue(date.toString(DateComponents::Second));
   1773         return;
   1774     }
   1775     setValue(date.toString(DateComponents::Millisecond));
   1776 }
   1777 
   1778 double HTMLInputElement::valueAsNumber() const
   1779 {
   1780     const double nan = numeric_limits<double>::quiet_NaN();
   1781     switch (inputType()) {
   1782     case DATE:
   1783     case DATETIME:
   1784     case DATETIMELOCAL:
   1785     case MONTH:
   1786     case NUMBER:
   1787     case RANGE:
   1788     case TIME:
   1789     case WEEK:
   1790         return parseToDouble(value(), nan);
   1791 
   1792     case BUTTON:
   1793     case CHECKBOX:
   1794     case COLOR:
   1795     case EMAIL:
   1796     case FILE:
   1797     case HIDDEN:
   1798     case IMAGE:
   1799     case ISINDEX:
   1800     case PASSWORD:
   1801     case RADIO:
   1802     case RESET:
   1803     case SEARCH:
   1804     case SUBMIT:
   1805     case TELEPHONE:
   1806     case TEXT:
   1807     case URL:
   1808         return nan;
   1809     }
   1810     ASSERT_NOT_REACHED();
   1811     return nan;
   1812 }
   1813 
   1814 void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
   1815 {
   1816     if (!isfinite(newValue)) {
   1817         ec = NOT_SUPPORTED_ERR;
   1818         return;
   1819     }
   1820     switch (inputType()) {
   1821     case DATE:
   1822     case DATETIME:
   1823     case TIME:
   1824     case WEEK:
   1825         setValueAsDate(newValue, ec);
   1826         return;
   1827     case MONTH: {
   1828         DateComponents date;
   1829         if (!date.setMonthsSinceEpoch(newValue)) {
   1830             setValue(String());
   1831             return;
   1832         }
   1833         setValue(date.toString());
   1834         return;
   1835     }
   1836     case DATETIMELOCAL: {
   1837         DateComponents date;
   1838         if (!date.setMillisecondsSinceEpochForDateTimeLocal(newValue)) {
   1839             setValue(String());
   1840             return;
   1841         }
   1842         setDateValue(date);
   1843         return;
   1844     }
   1845     case NUMBER:
   1846     case RANGE:
   1847         setValue(formStringFromDouble(newValue));
   1848         return;
   1849 
   1850     case BUTTON:
   1851     case CHECKBOX:
   1852     case COLOR:
   1853     case EMAIL:
   1854     case FILE:
   1855     case HIDDEN:
   1856     case IMAGE:
   1857     case ISINDEX:
   1858     case PASSWORD:
   1859     case RADIO:
   1860     case RESET:
   1861     case SEARCH:
   1862     case SUBMIT:
   1863     case TELEPHONE:
   1864     case TEXT:
   1865     case URL:
   1866         ec = INVALID_STATE_ERR;
   1867         return;
   1868     }
   1869     ASSERT_NOT_REACHED();
   1870     return;
   1871 }
   1872 
   1873 String HTMLInputElement::placeholder() const
   1874 {
   1875     return getAttribute(placeholderAttr).string();
   1876 }
   1877 
   1878 void HTMLInputElement::setPlaceholder(const String& value)
   1879 {
   1880     setAttribute(placeholderAttr, value);
   1881 }
   1882 
   1883 bool HTMLInputElement::searchEventsShouldBeDispatched() const
   1884 {
   1885     return hasAttribute(incrementalAttr);
   1886 }
   1887 
   1888 void HTMLInputElement::setValueFromRenderer(const String& value)
   1889 {
   1890     // File upload controls will always use setFileListFromRenderer.
   1891     ASSERT(inputType() != FILE);
   1892     m_data.setSuggestedValue(String());
   1893     updatePlaceholderVisibility(false);
   1894     InputElement::setValueFromRenderer(m_data, this, this, value);
   1895     setNeedsValidityCheck();
   1896 }
   1897 
   1898 void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
   1899 {
   1900     m_fileList->clear();
   1901     int size = paths.size();
   1902     for (int i = 0; i < size; i++)
   1903         m_fileList->append(File::create(paths[i]));
   1904 
   1905     setFormControlValueMatchesRenderer(true);
   1906     InputElement::notifyFormStateChanged(this);
   1907     setNeedsValidityCheck();
   1908 }
   1909 
   1910 bool HTMLInputElement::storesValueSeparateFromAttribute() const
   1911 {
   1912     switch (inputType()) {
   1913         case BUTTON:
   1914         case CHECKBOX:
   1915         case HIDDEN:
   1916         case IMAGE:
   1917         case RADIO:
   1918         case RESET:
   1919         case SUBMIT:
   1920             return false;
   1921         case COLOR:
   1922         case DATE:
   1923         case DATETIME:
   1924         case DATETIMELOCAL:
   1925         case EMAIL:
   1926         case FILE:
   1927         case ISINDEX:
   1928         case MONTH:
   1929         case NUMBER:
   1930         case PASSWORD:
   1931         case RANGE:
   1932         case SEARCH:
   1933         case TELEPHONE:
   1934         case TEXT:
   1935         case TIME:
   1936         case URL:
   1937         case WEEK:
   1938             return true;
   1939     }
   1940     return false;
   1941 }
   1942 
   1943 void* HTMLInputElement::preDispatchEventHandler(Event *evt)
   1944 {
   1945     // preventDefault or "return false" are used to reverse the automatic checking/selection we do here.
   1946     // This result gives us enough info to perform the "undo" in postDispatch of the action we take here.
   1947     void* result = 0;
   1948     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
   1949             && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
   1950         if (inputType() == CHECKBOX) {
   1951             // As a way to store the state, we return 0 if we were unchecked, 1 if we were checked, and 2 for
   1952             // indeterminate.
   1953             if (indeterminate()) {
   1954                 result = (void*)0x2;
   1955                 setIndeterminate(false);
   1956             } else {
   1957                 if (checked())
   1958                     result = (void*)0x1;
   1959                 setChecked(!checked(), true);
   1960             }
   1961         } else {
   1962             // For radio buttons, store the current selected radio object.
   1963             // We really want radio groups to end up in sane states, i.e., to have something checked.
   1964             // Therefore if nothing is currently selected, we won't allow this action to be "undone", since
   1965             // we want some object in the radio group to actually get selected.
   1966             HTMLInputElement* currRadio = checkedRadioButtons(this).checkedButtonForGroup(name());
   1967             if (currRadio) {
   1968                 // We have a radio button selected that is not us.  Cache it in our result field and ref it so
   1969                 // that it can't be destroyed.
   1970                 currRadio->ref();
   1971                 result = currRadio;
   1972             }
   1973             setChecked(true, true);
   1974         }
   1975     }
   1976     return result;
   1977 }
   1978 
   1979 void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data)
   1980 {
   1981     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
   1982             && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
   1983         if (inputType() == CHECKBOX) {
   1984             // Reverse the checking we did in preDispatch.
   1985             if (evt->defaultPrevented() || evt->defaultHandled()) {
   1986                 if (data == (void*)0x2)
   1987                     setIndeterminate(true);
   1988                 else
   1989                     setChecked(data);
   1990             }
   1991         } else if (data) {
   1992             HTMLInputElement* input = static_cast<HTMLInputElement*>(data);
   1993             if (evt->defaultPrevented() || evt->defaultHandled()) {
   1994                 // Restore the original selected radio button if possible.
   1995                 // Make sure it is still a radio button and only do the restoration if it still
   1996                 // belongs to our group.
   1997 
   1998                 if (input->form() == form() && input->inputType() == RADIO && input->name() == name()) {
   1999                     // Ok, the old radio button is still in our form and in our group and is still a
   2000                     // radio button, so it's safe to restore selection to it.
   2001                     input->setChecked(true);
   2002                 }
   2003             }
   2004             input->deref();
   2005         }
   2006 
   2007         // Left clicks on radio buttons and check boxes already performed default actions in preDispatchEventHandler().
   2008         evt->setDefaultHandled();
   2009     }
   2010 }
   2011 
   2012 void HTMLInputElement::defaultEventHandler(Event* evt)
   2013 {
   2014     // FIXME: It would be better to refactor this for the different types of input element.
   2015     // Having them all in one giant function makes this hard to read, and almost all the handling is type-specific.
   2016 
   2017     bool clickDefaultFormButton = false;
   2018 
   2019     if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n")
   2020         clickDefaultFormButton = true;
   2021 
   2022     if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == eventNames().clickEvent) {
   2023         // record the mouse position for when we get the DOMActivate event
   2024         MouseEvent* me = static_cast<MouseEvent*>(evt);
   2025         // FIXME: We could just call offsetX() and offsetY() on the event,
   2026         // but that's currently broken, so for now do the computation here.
   2027         if (me->isSimulated() || !renderer()) {
   2028             m_xPos = 0;
   2029             m_yPos = 0;
   2030         } else {
   2031             // FIXME: This doesn't work correctly with transforms.
   2032             // FIXME: pageX/pageY need adjusting for pageZoomFactor(). Use actualPageLocation()?
   2033             IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute());
   2034             m_xPos = me->pageX() - absOffset.x();
   2035             m_yPos = me->pageY() - absOffset.y();
   2036         }
   2037     }
   2038 
   2039     if (isTextField()
   2040             && evt->type() == eventNames().keydownEvent
   2041             && evt->isKeyboardEvent()
   2042             && focused()
   2043             && document()->frame()
   2044             && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
   2045         evt->setDefaultHandled();
   2046         return;
   2047     }
   2048 
   2049     if (inputType() == RADIO
   2050             && evt->isMouseEvent()
   2051             && evt->type() == eventNames().clickEvent
   2052             && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
   2053         evt->setDefaultHandled();
   2054         return;
   2055     }
   2056 
   2057     // Call the base event handler before any of our own event handling for almost all events in text fields.
   2058     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
   2059     bool callBaseClassEarly = isTextField() && !clickDefaultFormButton
   2060         && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
   2061     if (callBaseClassEarly) {
   2062         HTMLFormControlElementWithState::defaultEventHandler(evt);
   2063         if (evt->defaultHandled())
   2064             return;
   2065     }
   2066 
   2067     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
   2068     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
   2069     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
   2070     // must dispatch a DOMActivate event - a click event will not do the job.
   2071     if (evt->type() == eventNames().DOMActivateEvent && !disabled()) {
   2072         if (inputType() == IMAGE || inputType() == SUBMIT || inputType() == RESET) {
   2073             if (!form())
   2074                 return;
   2075             if (inputType() == RESET)
   2076                 form()->reset();
   2077             else {
   2078                 m_activeSubmit = true;
   2079                 // FIXME: Would be cleaner to get m_xPos and m_yPos out of the underlying mouse
   2080                 // event (if any) here instead of relying on the variables set above when
   2081                 // processing the click event. Even better, appendFormData could pass the
   2082                 // event in, and then we could get rid of m_xPos and m_yPos altogether!
   2083                 if (!form()->prepareSubmit(evt)) {
   2084                     m_xPos = 0;
   2085                     m_yPos = 0;
   2086                 }
   2087                 m_activeSubmit = false;
   2088             }
   2089         } else if (inputType() == FILE && renderer())
   2090             toRenderFileUploadControl(renderer())->click();
   2091     }
   2092 
   2093     // Use key press event here since sending simulated mouse events
   2094     // on key down blocks the proper sending of the key press event.
   2095     if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) {
   2096         bool clickElement = false;
   2097 
   2098         int charCode = static_cast<KeyboardEvent*>(evt)->charCode();
   2099 
   2100         if (charCode == '\r') {
   2101             switch (inputType()) {
   2102                 case CHECKBOX:
   2103                 case COLOR:
   2104                 case DATE:
   2105                 case DATETIME:
   2106                 case DATETIMELOCAL:
   2107                 case EMAIL:
   2108                 case HIDDEN:
   2109                 case ISINDEX:
   2110                 case MONTH:
   2111                 case NUMBER:
   2112                 case PASSWORD:
   2113                 case RANGE:
   2114                 case SEARCH:
   2115                 case TELEPHONE:
   2116                 case TEXT:
   2117                 case TIME:
   2118                 case URL:
   2119                 case WEEK:
   2120                     // Simulate mouse click on the default form button for enter for these types of elements.
   2121                     clickDefaultFormButton = true;
   2122                     break;
   2123                 case BUTTON:
   2124                 case FILE:
   2125                 case IMAGE:
   2126                 case RESET:
   2127                 case SUBMIT:
   2128                     // Simulate mouse click for enter for these types of elements.
   2129                     clickElement = true;
   2130                     break;
   2131                 case RADIO:
   2132                     break; // Don't do anything for enter on a radio button.
   2133             }
   2134         } else if (charCode == ' ') {
   2135             switch (inputType()) {
   2136                 case BUTTON:
   2137                 case CHECKBOX:
   2138                 case FILE:
   2139                 case IMAGE:
   2140                 case RESET:
   2141                 case SUBMIT:
   2142                 case RADIO:
   2143                     // Prevent scrolling down the page.
   2144                     evt->setDefaultHandled();
   2145                     return;
   2146                 default:
   2147                     break;
   2148             }
   2149         }
   2150 
   2151         if (clickElement) {
   2152             dispatchSimulatedClick(evt);
   2153             evt->setDefaultHandled();
   2154             return;
   2155         }
   2156     }
   2157 
   2158     if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent()) {
   2159         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
   2160 
   2161         if (key == "U+0020") {
   2162             switch (inputType()) {
   2163                 case BUTTON:
   2164                 case CHECKBOX:
   2165                 case FILE:
   2166                 case IMAGE:
   2167                 case RESET:
   2168                 case SUBMIT:
   2169                 case RADIO:
   2170                     setActive(true, true);
   2171                     // No setDefaultHandled(), because IE dispatches a keypress in this case
   2172                     // and the caller will only dispatch a keypress if we don't call setDefaultHandled.
   2173                     return;
   2174                 default:
   2175                     break;
   2176             }
   2177         }
   2178 
   2179 // allow enter to change state of radio
   2180         if (inputType() == RADIO && (key == "Up" || key == "Down" || key == "Left" || key == "Right")) {
   2181             // Left and up mean "previous radio button".
   2182             // Right and down mean "next radio button".
   2183             // Tested in WinIE, and even for RTL, left still means previous radio button (and so moves
   2184             // to the right).  Seems strange, but we'll match it.
   2185             bool forward = (key == "Down" || key == "Right");
   2186 
   2187             // We can only stay within the form's children if the form hasn't been demoted to a leaf because
   2188             // of malformed HTML.
   2189             Node* n = this;
   2190             while ((n = (forward ? n->traverseNextNode() : n->traversePreviousNode()))) {
   2191                 // Once we encounter a form element, we know we're through.
   2192                 if (n->hasTagName(formTag))
   2193                     break;
   2194 
   2195                 // Look for more radio buttons.
   2196                 if (n->hasTagName(inputTag)) {
   2197                     HTMLInputElement* elt = static_cast<HTMLInputElement*>(n);
   2198                     if (elt->form() != form())
   2199                         break;
   2200                     if (n->hasTagName(inputTag)) {
   2201                         HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n);
   2202                         if (inputElt->inputType() == RADIO && inputElt->name() == name() && inputElt->isFocusable()) {
   2203                             inputElt->setChecked(true);
   2204                             document()->setFocusedNode(inputElt);
   2205                             inputElt->dispatchSimulatedClick(evt, false, false);
   2206                             evt->setDefaultHandled();
   2207                             break;
   2208                         }
   2209                     }
   2210                 }
   2211             }
   2212         }
   2213     }
   2214 
   2215     if (evt->type() == eventNames().keyupEvent && evt->isKeyboardEvent()) {
   2216         bool clickElement = false;
   2217 
   2218         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
   2219 
   2220         if (key == "U+0020") {
   2221             switch (inputType()) {
   2222                 case BUTTON:
   2223                 case CHECKBOX:
   2224                 case FILE:
   2225                 case IMAGE:
   2226                 case RESET:
   2227                 case SUBMIT:
   2228                     // Simulate mouse click for spacebar for these types of elements.
   2229                     // The AppKit already does this for some, but not all, of them.
   2230                     clickElement = true;
   2231                     break;
   2232                 case RADIO:
   2233                     // If an unselected radio is tabbed into (because the entire group has nothing
   2234                     // checked, or because of some explicit .focus() call), then allow space to check it.
   2235                     if (!checked())
   2236                         clickElement = true;
   2237                     break;
   2238                 case COLOR:
   2239                 case DATE:
   2240                 case DATETIME:
   2241                 case DATETIMELOCAL:
   2242                 case EMAIL:
   2243                 case HIDDEN:
   2244                 case ISINDEX:
   2245                 case MONTH:
   2246                 case NUMBER:
   2247                 case PASSWORD:
   2248                 case RANGE:
   2249                 case SEARCH:
   2250                 case TELEPHONE:
   2251                 case TEXT:
   2252                 case TIME:
   2253                 case URL:
   2254                 case WEEK:
   2255                     break;
   2256             }
   2257         }
   2258 
   2259         if (clickElement) {
   2260             if (active())
   2261                 dispatchSimulatedClick(evt);
   2262             evt->setDefaultHandled();
   2263             return;
   2264         }
   2265     }
   2266 
   2267     if (clickDefaultFormButton) {
   2268         if (isSearchField()) {
   2269             addSearchResult();
   2270             onSearch();
   2271         }
   2272         // Fire onChange for text fields.
   2273         RenderObject* r = renderer();
   2274         if (r && r->isTextField() && toRenderTextControl(r)->wasChangedSinceLastChangeEvent()) {
   2275             dispatchFormControlChangeEvent();
   2276             // Refetch the renderer since arbitrary JS code run during onchange can do anything, including destroying it.
   2277             r = renderer();
   2278             if (r && r->isTextField())
   2279                 toRenderTextControl(r)->setChangedSinceLastChangeEvent(false);
   2280         }
   2281 
   2282         RefPtr<HTMLFormElement> formForSubmission = form();
   2283         // If there is no form and the element is an <isindex>, then create a temporary form just to be used for submission.
   2284         if (!formForSubmission && inputType() == ISINDEX)
   2285             formForSubmission = createTemporaryFormForIsIndex();
   2286 
   2287         // Form may never have been present, or may have been destroyed by code responding to the change event.
   2288         if (formForSubmission)
   2289             formForSubmission->submitClick(evt);
   2290 
   2291         evt->setDefaultHandled();
   2292         return;
   2293     }
   2294 
   2295     if (evt->isBeforeTextInsertedEvent())
   2296         InputElement::handleBeforeTextInsertedEvent(m_data, this, this, evt);
   2297 
   2298     if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent))
   2299         toRenderTextControlSingleLine(renderer())->forwardEvent(evt);
   2300 
   2301     if (inputType() == RANGE && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent()))
   2302         toRenderSlider(renderer())->forwardEvent(evt);
   2303 
   2304     if (!callBaseClassEarly && !evt->defaultHandled())
   2305         HTMLFormControlElementWithState::defaultEventHandler(evt);
   2306 }
   2307 
   2308 PassRefPtr<HTMLFormElement> HTMLInputElement::createTemporaryFormForIsIndex()
   2309 {
   2310     RefPtr<HTMLFormElement> form = new HTMLFormElement(formTag, document());
   2311     form->registerFormElement(this);
   2312     form->setMethod("GET");
   2313     if (!document()->baseURL().isEmpty()) {
   2314         // We treat the href property of the <base> element as the form action, as per section 7.5
   2315         // "Queries and Indexes" of the HTML 2.0 spec. <http://www.w3.org/MarkUp/html-spec/html-spec_7.html#SEC7.5>.
   2316         form->setAction(document()->baseURL().string());
   2317     }
   2318     return form.release();
   2319 }
   2320 
   2321 bool HTMLInputElement::isURLAttribute(Attribute *attr) const
   2322 {
   2323     return (attr->name() == srcAttr);
   2324 }
   2325 
   2326 String HTMLInputElement::defaultValue() const
   2327 {
   2328     return getAttribute(valueAttr);
   2329 }
   2330 
   2331 void HTMLInputElement::setDefaultValue(const String &value)
   2332 {
   2333     setAttribute(valueAttr, value);
   2334 }
   2335 
   2336 bool HTMLInputElement::defaultChecked() const
   2337 {
   2338     return !getAttribute(checkedAttr).isNull();
   2339 }
   2340 
   2341 void HTMLInputElement::setDefaultChecked(bool defaultChecked)
   2342 {
   2343     setAttribute(checkedAttr, defaultChecked ? "" : 0);
   2344 }
   2345 
   2346 void HTMLInputElement::setDefaultName(const AtomicString& name)
   2347 {
   2348     m_data.setName(name);
   2349 }
   2350 
   2351 String HTMLInputElement::accept() const
   2352 {
   2353     return getAttribute(acceptAttr);
   2354 }
   2355 
   2356 void HTMLInputElement::setAccept(const String &value)
   2357 {
   2358     setAttribute(acceptAttr, value);
   2359 }
   2360 
   2361 String HTMLInputElement::accessKey() const
   2362 {
   2363     return getAttribute(accesskeyAttr);
   2364 }
   2365 
   2366 void HTMLInputElement::setAccessKey(const String &value)
   2367 {
   2368     setAttribute(accesskeyAttr, value);
   2369 }
   2370 
   2371 String HTMLInputElement::align() const
   2372 {
   2373     return getAttribute(alignAttr);
   2374 }
   2375 
   2376 void HTMLInputElement::setAlign(const String &value)
   2377 {
   2378     setAttribute(alignAttr, value);
   2379 }
   2380 
   2381 String HTMLInputElement::alt() const
   2382 {
   2383     return getAttribute(altAttr);
   2384 }
   2385 
   2386 void HTMLInputElement::setAlt(const String &value)
   2387 {
   2388     setAttribute(altAttr, value);
   2389 }
   2390 
   2391 int HTMLInputElement::maxLength() const
   2392 {
   2393     return m_data.maxLength();
   2394 }
   2395 
   2396 void HTMLInputElement::setMaxLength(int maxLength, ExceptionCode& ec)
   2397 {
   2398     if (maxLength < 0)
   2399         ec = INDEX_SIZE_ERR;
   2400     else
   2401         setAttribute(maxlengthAttr, String::number(maxLength));
   2402 }
   2403 
   2404 bool HTMLInputElement::multiple() const
   2405 {
   2406     return !getAttribute(multipleAttr).isNull();
   2407 }
   2408 
   2409 void HTMLInputElement::setMultiple(bool multiple)
   2410 {
   2411     setAttribute(multipleAttr, multiple ? "" : 0);
   2412 }
   2413 
   2414 void HTMLInputElement::setSize(unsigned _size)
   2415 {
   2416     setAttribute(sizeAttr, String::number(_size));
   2417 }
   2418 
   2419 KURL HTMLInputElement::src() const
   2420 {
   2421     return document()->completeURL(getAttribute(srcAttr));
   2422 }
   2423 
   2424 void HTMLInputElement::setSrc(const String &value)
   2425 {
   2426     setAttribute(srcAttr, value);
   2427 }
   2428 
   2429 String HTMLInputElement::useMap() const
   2430 {
   2431     return getAttribute(usemapAttr);
   2432 }
   2433 
   2434 void HTMLInputElement::setUseMap(const String &value)
   2435 {
   2436     setAttribute(usemapAttr, value);
   2437 }
   2438 
   2439 void HTMLInputElement::setAutofilled(bool b)
   2440 {
   2441     if (b == m_autofilled)
   2442         return;
   2443 
   2444     m_autofilled = b;
   2445     setNeedsStyleRecalc();
   2446 }
   2447 
   2448 FileList* HTMLInputElement::files()
   2449 {
   2450     if (inputType() != FILE)
   2451         return 0;
   2452     return m_fileList.get();
   2453 }
   2454 
   2455 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
   2456 {
   2457     if (isTextField())
   2458         return InputElement::sanitizeValue(this, proposedValue);
   2459     return proposedValue;
   2460 }
   2461 
   2462 bool HTMLInputElement::needsActivationCallback()
   2463 {
   2464     return inputType() == PASSWORD || m_autocomplete == Off;
   2465 }
   2466 
   2467 void HTMLInputElement::registerForActivationCallbackIfNeeded()
   2468 {
   2469     if (needsActivationCallback())
   2470         document()->registerForDocumentActivationCallbacks(this);
   2471 }
   2472 
   2473 void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
   2474 {
   2475     if (!needsActivationCallback())
   2476         document()->unregisterForDocumentActivationCallbacks(this);
   2477 }
   2478 
   2479 bool HTMLInputElement::isRequiredFormControl() const
   2480 {
   2481     if (!required())
   2482         return false;
   2483 
   2484     switch (inputType()) {
   2485         case CHECKBOX:
   2486         case DATE:
   2487         case DATETIME:
   2488         case DATETIMELOCAL:
   2489         case EMAIL:
   2490         case FILE:
   2491         case MONTH:
   2492         case NUMBER:
   2493         case PASSWORD:
   2494         case RADIO:
   2495         case SEARCH:
   2496         case TELEPHONE:
   2497         case TEXT:
   2498         case TIME:
   2499         case URL:
   2500         case WEEK:
   2501             return true;
   2502         case BUTTON:
   2503         case COLOR:
   2504         case HIDDEN:
   2505         case IMAGE:
   2506         case ISINDEX:
   2507         case RANGE:
   2508         case RESET:
   2509         case SUBMIT:
   2510             return false;
   2511     }
   2512 
   2513     ASSERT_NOT_REACHED();
   2514     return false;
   2515 }
   2516 
   2517 void HTMLInputElement::cacheSelection(int start, int end)
   2518 {
   2519     m_data.setCachedSelectionStart(start);
   2520     m_data.setCachedSelectionEnd(end);
   2521 }
   2522 
   2523 void HTMLInputElement::addSearchResult()
   2524 {
   2525     ASSERT(isSearchField());
   2526     if (renderer())
   2527         toRenderTextControlSingleLine(renderer())->addSearchResult();
   2528 }
   2529 
   2530 void HTMLInputElement::onSearch()
   2531 {
   2532     ASSERT(isSearchField());
   2533     if (renderer())
   2534         toRenderTextControlSingleLine(renderer())->stopSearchEventTimer();
   2535     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
   2536 }
   2537 
   2538 void HTMLInputElement::documentDidBecomeActive()
   2539 {
   2540     ASSERT(needsActivationCallback());
   2541     reset();
   2542 }
   2543 
   2544 void HTMLInputElement::willMoveToNewOwnerDocument()
   2545 {
   2546     // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
   2547     if (needsActivationCallback())
   2548         document()->unregisterForDocumentActivationCallbacks(this);
   2549 
   2550     document()->checkedRadioButtons().removeButton(this);
   2551 
   2552     HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
   2553 }
   2554 
   2555 void HTMLInputElement::didMoveToNewOwnerDocument()
   2556 {
   2557     registerForActivationCallbackIfNeeded();
   2558 
   2559     HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
   2560 }
   2561 
   2562 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
   2563 {
   2564     HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls);
   2565 
   2566     addSubresourceURL(urls, src());
   2567 }
   2568 
   2569 bool HTMLInputElement::willValidate() const
   2570 {
   2571     // FIXME: This shall check for new WF2 input types too
   2572     return HTMLFormControlElementWithState::willValidate() && inputType() != HIDDEN &&
   2573            inputType() != BUTTON && inputType() != RESET;
   2574 }
   2575 
   2576 String HTMLInputElement::formStringFromDouble(double number)
   2577 {
   2578     // According to HTML5, "the best representation of the number n as a floating
   2579     // point number" is a string produced by applying ToString() to n.
   2580     DtoaBuffer buffer;
   2581     unsigned length;
   2582     doubleToStringInJavaScriptFormat(number, buffer, &length);
   2583     return String(buffer, length);
   2584 }
   2585 
   2586 bool HTMLInputElement::formStringToDouble(const String& src, double* out)
   2587 {
   2588     // See HTML5 2.4.4.3 `Real numbers.'
   2589 
   2590     if (src.isEmpty())
   2591         return false;
   2592     // String::toDouble() accepts leading + \t \n \v \f \r and SPACE, which are invalid in HTML5.
   2593     // So, check the first character.
   2594     if (src[0] != '-' && (src[0] < '0' || src[0] > '9'))
   2595         return false;
   2596 
   2597     bool valid = false;
   2598     double value = src.toDouble(&valid);
   2599     if (!valid)
   2600         return false;
   2601     // NaN and Infinity are not valid numbers according to the standard.
   2602     if (!isfinite(value))
   2603         return false;
   2604     // -0 -> 0
   2605     if (!value)
   2606         value = 0;
   2607     if (out)
   2608         *out = value;
   2609     return true;
   2610 }
   2611 
   2612 bool HTMLInputElement::formStringToDateComponents(InputType type, const String& formString, DateComponents* out)
   2613 {
   2614     if (formString.isEmpty())
   2615         return false;
   2616     DateComponents ignoredResult;
   2617     if (!out)
   2618         out = &ignoredResult;
   2619     const UChar* characters = formString.characters();
   2620     unsigned length = formString.length();
   2621     unsigned end;
   2622 
   2623     switch (type) {
   2624     case DATE:
   2625         return out->parseDate(characters, length, 0, end) && end == length;
   2626     case DATETIME:
   2627         return out->parseDateTime(characters, length, 0, end) && end == length;
   2628     case DATETIMELOCAL:
   2629         return out->parseDateTimeLocal(characters, length, 0, end) && end == length;
   2630     case MONTH:
   2631         return out->parseMonth(characters, length, 0, end) && end == length;
   2632     case WEEK:
   2633         return out->parseWeek(characters, length, 0, end) && end == length;
   2634     case TIME:
   2635         return out->parseTime(characters, length, 0, end) && end == length;
   2636     default:
   2637         ASSERT_NOT_REACHED();
   2638         return false;
   2639     }
   2640 }
   2641 
   2642 #if ENABLE(DATALIST)
   2643 HTMLElement* HTMLInputElement::list() const
   2644 {
   2645     return dataList();
   2646 }
   2647 
   2648 HTMLDataListElement* HTMLInputElement::dataList() const
   2649 {
   2650     if (!m_hasNonEmptyList)
   2651         return 0;
   2652 
   2653     switch (inputType()) {
   2654     case COLOR:
   2655     case DATE:
   2656     case DATETIME:
   2657     case DATETIMELOCAL:
   2658     case EMAIL:
   2659     case MONTH:
   2660     case NUMBER:
   2661     case RANGE:
   2662     case SEARCH:
   2663     case TELEPHONE:
   2664     case TEXT:
   2665     case TIME:
   2666     case URL:
   2667     case WEEK: {
   2668         Element* element = document()->getElementById(getAttribute(listAttr));
   2669         if (element && element->hasTagName(datalistTag))
   2670             return static_cast<HTMLDataListElement*>(element);
   2671         break;
   2672     }
   2673     case BUTTON:
   2674     case CHECKBOX:
   2675     case FILE:
   2676     case HIDDEN:
   2677     case IMAGE:
   2678     case ISINDEX:
   2679     case PASSWORD:
   2680     case RADIO:
   2681     case RESET:
   2682     case SUBMIT:
   2683         break;
   2684     }
   2685     return 0;
   2686 }
   2687 
   2688 HTMLOptionElement* HTMLInputElement::selectedOption() const
   2689 {
   2690     String currentValue = value();
   2691     // The empty value never matches to a datalist option because it
   2692     // doesn't represent a suggestion according to the standard.
   2693     if (currentValue.isEmpty())
   2694         return 0;
   2695 
   2696     HTMLDataListElement* sourceElement = dataList();
   2697     if (!sourceElement)
   2698         return 0;
   2699     RefPtr<HTMLCollection> options = sourceElement->options();
   2700     for (unsigned i = 0; options && i < options->length(); ++i) {
   2701         HTMLOptionElement* option = static_cast<HTMLOptionElement*>(options->item(i));
   2702         if (!option->disabled() && currentValue == option->value())
   2703             return option;
   2704     }
   2705     return 0;
   2706 }
   2707 #endif  // ENABLE(DATALIST)
   2708 
   2709 } // namespace
   2710