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, 2009, 2010, 2011 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  * Copyright (C) 2010 Google Inc. All rights reserved.
      9  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
     10  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
     11  *
     12  * This library is free software; you can redistribute it and/or
     13  * modify it under the terms of the GNU Library General Public
     14  * License as published by the Free Software Foundation; either
     15  * version 2 of the License, or (at your option) any later version.
     16  *
     17  * This library is distributed in the hope that it will be useful,
     18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20  * Library General Public License for more details.
     21  *
     22  * You should have received a copy of the GNU Library General Public License
     23  * along with this library; see the file COPYING.LIB.  If not, write to
     24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     25  * Boston, MA 02110-1301, USA.
     26  *
     27  */
     28 
     29 #include "config.h"
     30 #include "core/html/HTMLInputElement.h"
     31 
     32 #include "CSSPropertyNames.h"
     33 #include "HTMLNames.h"
     34 #include "RuntimeEnabledFeatures.h"
     35 #include "bindings/v8/ExceptionState.h"
     36 #include "bindings/v8/ScriptEventListener.h"
     37 #include "core/accessibility/AXObjectCache.h"
     38 #include "core/dom/BeforeTextInsertedEvent.h"
     39 #include "core/dom/Document.h"
     40 #include "core/dom/EventNames.h"
     41 #include "core/dom/ExceptionCode.h"
     42 #include "core/dom/IdTargetObserver.h"
     43 #include "core/dom/KeyboardEvent.h"
     44 #include "core/dom/MouseEvent.h"
     45 #include "core/dom/ScopedEventQueue.h"
     46 #include "core/dom/TouchEvent.h"
     47 #include "core/dom/shadow/ElementShadow.h"
     48 #include "core/dom/shadow/InsertionPoint.h"
     49 #include "core/dom/shadow/ShadowRoot.h"
     50 #include "core/editing/Editor.h"
     51 #include "core/editing/FrameSelection.h"
     52 #include "core/fileapi/FileList.h"
     53 #include "core/html/ColorInputType.h"
     54 #include "core/html/FileInputType.h"
     55 #include "core/html/FormController.h"
     56 #include "core/html/HTMLCollection.h"
     57 #include "core/html/HTMLDataListElement.h"
     58 #include "core/html/HTMLFormElement.h"
     59 #include "core/html/HTMLImageLoader.h"
     60 #include "core/html/HTMLOptionElement.h"
     61 #include "core/html/InputType.h"
     62 #include "core/html/SearchInputType.h"
     63 #include "core/html/parser/HTMLParserIdioms.h"
     64 #include "core/page/Frame.h"
     65 #include "core/page/FrameView.h"
     66 #include "core/page/UseCounter.h"
     67 #include "core/platform/DateTimeChooser.h"
     68 #include "core/platform/Language.h"
     69 #include "core/platform/LocalizedStrings.h"
     70 #include "core/platform/PlatformMouseEvent.h"
     71 #include "core/rendering/RenderTextControlSingleLine.h"
     72 #include "core/rendering/RenderTheme.h"
     73 #include "wtf/MathExtras.h"
     74 
     75 using namespace std;
     76 
     77 namespace WebCore {
     78 
     79 using namespace HTMLNames;
     80 
     81 class ListAttributeTargetObserver : IdTargetObserver {
     82     WTF_MAKE_FAST_ALLOCATED;
     83 public:
     84     static PassOwnPtr<ListAttributeTargetObserver> create(const AtomicString& id, HTMLInputElement*);
     85     virtual void idTargetChanged() OVERRIDE;
     86 
     87 private:
     88     ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement*);
     89 
     90     HTMLInputElement* m_element;
     91 };
     92 
     93 // FIXME: According to HTML4, the length attribute's value can be arbitrarily
     94 // large. However, due to https://bugs.webkit.org/show_bug.cgi?id=14536 things
     95 // get rather sluggish when a text field has a larger number of characters than
     96 // this, even when just clicking in the text field.
     97 const unsigned HTMLInputElement::maximumLength = 524288;
     98 const int defaultSize = 20;
     99 const int maxSavedResults = 256;
    100 
    101 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
    102     : HTMLTextFormControlElement(tagName, document, form)
    103     , m_size(defaultSize)
    104     , m_maxLength(maximumLength)
    105     , m_maxResults(-1)
    106     , m_isChecked(false)
    107     , m_reflectsCheckedAttribute(true)
    108     , m_isIndeterminate(false)
    109     , m_hasType(false)
    110     , m_isActivatedSubmit(false)
    111     , m_autocomplete(Uninitialized)
    112     , m_isAutofilled(false)
    113     , m_hasNonEmptyList(false)
    114     , m_stateRestored(false)
    115     , m_parsingInProgress(createdByParser)
    116     , m_valueAttributeWasUpdatedAfterParsing(false)
    117     , m_wasModifiedByUser(false)
    118     , m_canReceiveDroppedFiles(false)
    119     , m_hasTouchEventHandler(false)
    120     , m_inputType(InputType::createText(this))
    121 {
    122     ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
    123 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    124     setHasCustomStyleCallbacks();
    125 #endif
    126     ScriptWrappable::init(this);
    127 }
    128 
    129 PassRefPtr<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
    130 {
    131     RefPtr<HTMLInputElement> inputElement = adoptRef(new HTMLInputElement(tagName, document, form, createdByParser));
    132     inputElement->ensureUserAgentShadowRoot();
    133     return inputElement.release();
    134 }
    135 
    136 HTMLImageLoader* HTMLInputElement::imageLoader()
    137 {
    138     if (!m_imageLoader)
    139         m_imageLoader = adoptPtr(new HTMLImageLoader(this));
    140     return m_imageLoader.get();
    141 }
    142 
    143 void HTMLInputElement::didAddUserAgentShadowRoot(ShadowRoot*)
    144 {
    145     m_inputType->createShadowSubtree();
    146 }
    147 
    148 HTMLInputElement::~HTMLInputElement()
    149 {
    150     // Need to remove form association while this is still an HTMLInputElement
    151     // so that virtual functions are called correctly.
    152     setForm(0);
    153     // setForm(0) may register this to a document-level radio button group.
    154     // We should unregister it to avoid accessing a deleted object.
    155     if (isRadioButton())
    156         document()->formController()->checkedRadioButtons().removeButton(this);
    157     if (m_hasTouchEventHandler)
    158         document()->didRemoveEventTargetNode(this);
    159 }
    160 
    161 const AtomicString& HTMLInputElement::name() const
    162 {
    163     return m_name.isNull() ? emptyAtom : m_name;
    164 }
    165 
    166 Vector<FileChooserFileInfo> HTMLInputElement::filesFromFileInputFormControlState(const FormControlState& state)
    167 {
    168     return FileInputType::filesFromFormControlState(state);
    169 }
    170 
    171 HTMLElement* HTMLInputElement::containerElement() const
    172 {
    173     return m_inputType->containerElement();
    174 }
    175 
    176 HTMLElement* HTMLInputElement::innerTextElement() const
    177 {
    178     return m_inputType->innerTextElement();
    179 }
    180 
    181 HTMLElement* HTMLInputElement::innerBlockElement() const
    182 {
    183     return m_inputType->innerBlockElement();
    184 }
    185 
    186 HTMLElement* HTMLInputElement::innerSpinButtonElement() const
    187 {
    188     return m_inputType->innerSpinButtonElement();
    189 }
    190 
    191 #if ENABLE(INPUT_SPEECH)
    192 HTMLElement* HTMLInputElement::speechButtonElement() const
    193 {
    194     return m_inputType->speechButtonElement();
    195 }
    196 #endif
    197 
    198 HTMLElement* HTMLInputElement::passwordGeneratorButtonElement() const
    199 {
    200     return m_inputType->passwordGeneratorButtonElement();
    201 }
    202 
    203 HTMLElement* HTMLInputElement::sliderThumbElement() const
    204 {
    205     return m_inputType->sliderThumbElement();
    206 }
    207 
    208 HTMLElement* HTMLInputElement::sliderTrackElement() const
    209 {
    210     return m_inputType->sliderTrackElement();
    211 }
    212 
    213 HTMLElement* HTMLInputElement::placeholderElement() const
    214 {
    215     return m_inputType->placeholderElement();
    216 }
    217 
    218 bool HTMLInputElement::shouldAutocomplete() const
    219 {
    220     if (m_autocomplete != Uninitialized)
    221         return m_autocomplete == On;
    222     return HTMLTextFormControlElement::shouldAutocomplete();
    223 }
    224 
    225 bool HTMLInputElement::isValidValue(const String& value) const
    226 {
    227     if (!m_inputType->canSetStringValue()) {
    228         ASSERT_NOT_REACHED();
    229         return false;
    230     }
    231     return !m_inputType->typeMismatchFor(value)
    232         && !m_inputType->stepMismatch(value)
    233         && !m_inputType->rangeUnderflow(value)
    234         && !m_inputType->rangeOverflow(value)
    235         && !tooLong(value, IgnoreDirtyFlag)
    236         && !m_inputType->patternMismatch(value)
    237         && !m_inputType->valueMissing(value);
    238 }
    239 
    240 bool HTMLInputElement::tooLong() const
    241 {
    242     return willValidate() && tooLong(value(), CheckDirtyFlag);
    243 }
    244 
    245 bool HTMLInputElement::typeMismatch() const
    246 {
    247     return willValidate() && m_inputType->typeMismatch();
    248 }
    249 
    250 bool HTMLInputElement::valueMissing() const
    251 {
    252     return willValidate() && m_inputType->valueMissing(value());
    253 }
    254 
    255 bool HTMLInputElement::hasBadInput() const
    256 {
    257     return willValidate() && m_inputType->hasBadInput();
    258 }
    259 
    260 bool HTMLInputElement::patternMismatch() const
    261 {
    262     return willValidate() && m_inputType->patternMismatch(value());
    263 }
    264 
    265 bool HTMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
    266 {
    267     // We use isTextType() instead of supportsMaxLength() because of the
    268     // 'virtual' overhead.
    269     if (!isTextType())
    270         return false;
    271     int max = maxLength();
    272     if (max < 0)
    273         return false;
    274     if (check == CheckDirtyFlag) {
    275         // Return false for the default value or a value set by a script even if
    276         // it is longer than maxLength.
    277         if (!hasDirtyValue() || !m_wasModifiedByUser)
    278             return false;
    279     }
    280     return numGraphemeClusters(value) > static_cast<unsigned>(max);
    281 }
    282 
    283 bool HTMLInputElement::rangeUnderflow() const
    284 {
    285     return willValidate() && m_inputType->rangeUnderflow(value());
    286 }
    287 
    288 bool HTMLInputElement::rangeOverflow() const
    289 {
    290     return willValidate() && m_inputType->rangeOverflow(value());
    291 }
    292 
    293 String HTMLInputElement::validationMessage() const
    294 {
    295     if (!willValidate())
    296         return String();
    297 
    298     if (customError())
    299         return customValidationMessage();
    300 
    301     return m_inputType->validationMessage();
    302 }
    303 
    304 double HTMLInputElement::minimum() const
    305 {
    306     return m_inputType->minimum();
    307 }
    308 
    309 double HTMLInputElement::maximum() const
    310 {
    311     return m_inputType->maximum();
    312 }
    313 
    314 bool HTMLInputElement::stepMismatch() const
    315 {
    316     return willValidate() && m_inputType->stepMismatch(value());
    317 }
    318 
    319 bool HTMLInputElement::getAllowedValueStep(Decimal* step) const
    320 {
    321     return m_inputType->getAllowedValueStep(step);
    322 }
    323 
    324 StepRange HTMLInputElement::createStepRange(AnyStepHandling anyStepHandling) const
    325 {
    326     return m_inputType->createStepRange(anyStepHandling);
    327 }
    328 
    329 Decimal HTMLInputElement::findClosestTickMarkValue(const Decimal& value)
    330 {
    331     return m_inputType->findClosestTickMarkValue(value);
    332 }
    333 
    334 void HTMLInputElement::stepUp(int n, ExceptionState& es)
    335 {
    336     m_inputType->stepUp(n, es);
    337 }
    338 
    339 void HTMLInputElement::stepDown(int n, ExceptionState& es)
    340 {
    341     m_inputType->stepUp(-n, es);
    342 }
    343 
    344 void HTMLInputElement::blur()
    345 {
    346     m_inputType->blur();
    347 }
    348 
    349 void HTMLInputElement::defaultBlur()
    350 {
    351     HTMLTextFormControlElement::blur();
    352 }
    353 
    354 bool HTMLInputElement::hasCustomFocusLogic() const
    355 {
    356     return m_inputType->hasCustomFocusLogic();
    357 }
    358 
    359 bool HTMLInputElement::isKeyboardFocusable() const
    360 {
    361     return m_inputType->isKeyboardFocusable();
    362 }
    363 
    364 bool HTMLInputElement::shouldShowFocusRingOnMouseFocus() const
    365 {
    366     return m_inputType->shouldShowFocusRingOnMouseFocus();
    367 }
    368 
    369 void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
    370 {
    371     if (isTextField()) {
    372         if (!restorePreviousSelection || !hasCachedSelection())
    373             select();
    374         else
    375             restoreCachedSelection();
    376         if (document()->frame())
    377             document()->frame()->selection()->revealSelection();
    378     } else
    379         HTMLTextFormControlElement::updateFocusAppearance(restorePreviousSelection);
    380 }
    381 
    382 void HTMLInputElement::beginEditing()
    383 {
    384     if (!isTextField())
    385         return;
    386 
    387     if (Frame* frame = document()->frame())
    388         frame->editor()->textFieldDidBeginEditing(this);
    389 }
    390 
    391 void HTMLInputElement::endEditing()
    392 {
    393     if (!isTextField())
    394         return;
    395 
    396     if (Frame* frame = document()->frame())
    397         frame->editor()->textFieldDidEndEditing(this);
    398 }
    399 
    400 bool HTMLInputElement::shouldUseInputMethod()
    401 {
    402     return m_inputType->shouldUseInputMethod();
    403 }
    404 
    405 void HTMLInputElement::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction)
    406 {
    407     m_inputType->handleFocusEvent(oldFocusedElement, direction);
    408 }
    409 
    410 void HTMLInputElement::handleBlurEvent()
    411 {
    412     m_inputType->handleBlurEvent();
    413 }
    414 
    415 void HTMLInputElement::setType(const String& type)
    416 {
    417     // FIXME: This should just call setAttribute. No reason to handle the empty string specially.
    418     // We should write a test case to show that setting to the empty string does not remove the
    419     // attribute in other browsers and then fix this. Note that setting to null *does* remove
    420     // the attribute and setAttribute implements that.
    421     if (type.isEmpty())
    422         removeAttribute(typeAttr);
    423     else
    424         setAttribute(typeAttr, type);
    425 }
    426 
    427 void HTMLInputElement::updateType()
    428 {
    429     OwnPtr<InputType> newType = InputType::create(this, fastGetAttribute(typeAttr));
    430     bool hadType = m_hasType;
    431     m_hasType = true;
    432     if (m_inputType->formControlType() == newType->formControlType())
    433         return;
    434 
    435     if (hadType && !newType->canChangeFromAnotherType()) {
    436         // Set the attribute back to the old value.
    437         // Useful in case we were called from inside parseAttribute.
    438         setAttribute(typeAttr, type());
    439         return;
    440     }
    441 
    442     removeFromRadioButtonGroup();
    443 
    444     bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
    445     bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
    446 
    447     m_inputType->destroyShadowSubtree();
    448 
    449     bool wasAttached = attached();
    450     if (wasAttached)
    451         detach();
    452 
    453     m_inputType = newType.release();
    454     m_inputType->createShadowSubtree();
    455 
    456     bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();
    457     if (hasTouchEventHandler != m_hasTouchEventHandler) {
    458         if (hasTouchEventHandler)
    459             document()->didAddTouchEventHandler(this);
    460         else
    461             document()->didRemoveTouchEventHandler(this);
    462         m_hasTouchEventHandler = hasTouchEventHandler;
    463     }
    464 
    465     setNeedsWillValidateCheck();
    466 
    467     bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
    468 
    469     if (didStoreValue && !willStoreValue && hasDirtyValue()) {
    470         setAttribute(valueAttr, m_valueIfDirty);
    471         m_valueIfDirty = String();
    472     }
    473     if (!didStoreValue && willStoreValue) {
    474         AtomicString valueString = fastGetAttribute(valueAttr);
    475         m_valueIfDirty = sanitizeValue(valueString);
    476     } else
    477         updateValueIfNeeded();
    478 
    479     setFormControlValueMatchesRenderer(false);
    480     m_inputType->updateInnerTextValue();
    481 
    482     m_wasModifiedByUser = false;
    483 
    484     if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
    485         ASSERT(elementData());
    486         if (const Attribute* height = getAttributeItem(heightAttr))
    487             attributeChanged(heightAttr, height->value());
    488         if (const Attribute* width = getAttributeItem(widthAttr))
    489             attributeChanged(widthAttr, width->value());
    490         if (const Attribute* align = getAttributeItem(alignAttr))
    491             attributeChanged(alignAttr, align->value());
    492     }
    493 
    494     if (wasAttached) {
    495         lazyAttach();
    496         if (document()->focusedElement() == this)
    497             document()->updateFocusAppearanceSoon(true /* restore selection */);
    498     }
    499 
    500     setChangedSinceLastFormControlChangeEvent(false);
    501 
    502     addToRadioButtonGroup();
    503 
    504     setNeedsValidityCheck();
    505     notifyFormStateChanged();
    506 }
    507 
    508 void HTMLInputElement::subtreeHasChanged()
    509 {
    510     m_inputType->subtreeHasChanged();
    511     // When typing in an input field, childrenChanged is not called, so we need to force the directionality check.
    512     calculateAndAdjustDirectionality();
    513 }
    514 
    515 const AtomicString& HTMLInputElement::formControlType() const
    516 {
    517     return m_inputType->formControlType();
    518 }
    519 
    520 bool HTMLInputElement::shouldSaveAndRestoreFormControlState() const
    521 {
    522     if (!m_inputType->shouldSaveAndRestoreFormControlState())
    523         return false;
    524     return HTMLTextFormControlElement::shouldSaveAndRestoreFormControlState();
    525 }
    526 
    527 FormControlState HTMLInputElement::saveFormControlState() const
    528 {
    529     return m_inputType->saveFormControlState();
    530 }
    531 
    532 void HTMLInputElement::restoreFormControlState(const FormControlState& state)
    533 {
    534     m_inputType->restoreFormControlState(state);
    535     m_stateRestored = true;
    536 }
    537 
    538 bool HTMLInputElement::canStartSelection() const
    539 {
    540     if (!isTextField())
    541         return false;
    542     return HTMLTextFormControlElement::canStartSelection();
    543 }
    544 
    545 bool HTMLInputElement::canHaveSelection() const
    546 {
    547     return isTextField();
    548 }
    549 
    550 int HTMLInputElement::selectionStartForBinding(ExceptionState& es) const
    551 {
    552     if (!canHaveSelection()) {
    553         es.throwDOMException(InvalidStateError);
    554         return 0;
    555     }
    556     return HTMLTextFormControlElement::selectionStart();
    557 }
    558 
    559 int HTMLInputElement::selectionEndForBinding(ExceptionState& es) const
    560 {
    561     if (!canHaveSelection()) {
    562         es.throwDOMException(InvalidStateError);
    563         return 0;
    564     }
    565     return HTMLTextFormControlElement::selectionEnd();
    566 }
    567 
    568 String HTMLInputElement::selectionDirectionForBinding(ExceptionState& es) const
    569 {
    570     if (!canHaveSelection()) {
    571         es.throwDOMException(InvalidStateError);
    572         return String();
    573     }
    574     return HTMLTextFormControlElement::selectionDirection();
    575 }
    576 
    577 void HTMLInputElement::setSelectionStartForBinding(int start, ExceptionState& es)
    578 {
    579     if (!canHaveSelection()) {
    580         es.throwDOMException(InvalidStateError);
    581         return;
    582     }
    583     HTMLTextFormControlElement::setSelectionStart(start);
    584 }
    585 
    586 void HTMLInputElement::setSelectionEndForBinding(int end, ExceptionState& es)
    587 {
    588     if (!canHaveSelection()) {
    589         es.throwDOMException(InvalidStateError);
    590         return;
    591     }
    592     HTMLTextFormControlElement::setSelectionEnd(end);
    593 }
    594 
    595 void HTMLInputElement::setSelectionDirectionForBinding(const String& direction, ExceptionState& es)
    596 {
    597     if (!canHaveSelection()) {
    598         es.throwDOMException(InvalidStateError);
    599         return;
    600     }
    601     HTMLTextFormControlElement::setSelectionDirection(direction);
    602 }
    603 
    604 void HTMLInputElement::setSelectionRangeForBinding(int start, int end, ExceptionState& es)
    605 {
    606     if (!canHaveSelection()) {
    607         es.throwDOMException(InvalidStateError);
    608         return;
    609     }
    610     HTMLTextFormControlElement::setSelectionRange(start, end);
    611 }
    612 
    613 void HTMLInputElement::setSelectionRangeForBinding(int start, int end, const String& direction, ExceptionState& es)
    614 {
    615     if (!canHaveSelection()) {
    616         es.throwDOMException(InvalidStateError);
    617         return;
    618     }
    619     HTMLTextFormControlElement::setSelectionRange(start, end, direction);
    620 }
    621 
    622 void HTMLInputElement::accessKeyAction(bool sendMouseEvents)
    623 {
    624     m_inputType->accessKeyAction(sendMouseEvents);
    625 }
    626 
    627 bool HTMLInputElement::isPresentationAttribute(const QualifiedName& name) const
    628 {
    629     if (name == vspaceAttr || name == hspaceAttr || name == alignAttr || name == widthAttr || name == heightAttr || (name == borderAttr && isImageButton()))
    630         return true;
    631     return HTMLTextFormControlElement::isPresentationAttribute(name);
    632 }
    633 
    634 void HTMLInputElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
    635 {
    636     if (name == vspaceAttr) {
    637         addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
    638         addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
    639     } else if (name == hspaceAttr) {
    640         addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
    641         addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
    642     } else if (name == alignAttr) {
    643         if (m_inputType->shouldRespectAlignAttribute())
    644             applyAlignmentAttributeToStyle(value, style);
    645     } else if (name == widthAttr) {
    646         if (m_inputType->shouldRespectHeightAndWidthAttributes())
    647             addHTMLLengthToStyle(style, CSSPropertyWidth, value);
    648     } else if (name == heightAttr) {
    649         if (m_inputType->shouldRespectHeightAndWidthAttributes())
    650             addHTMLLengthToStyle(style, CSSPropertyHeight, value);
    651     } else if (name == borderAttr && isImageButton())
    652         applyBorderAttributeToStyle(value, style);
    653     else
    654         HTMLTextFormControlElement::collectStyleForPresentationAttribute(name, value, style);
    655 }
    656 
    657 void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    658 {
    659     if (name == nameAttr) {
    660         removeFromRadioButtonGroup();
    661         m_name = value;
    662         addToRadioButtonGroup();
    663         HTMLTextFormControlElement::parseAttribute(name, value);
    664     } else if (name == autocompleteAttr) {
    665         if (equalIgnoringCase(value, "off"))
    666             m_autocomplete = Off;
    667         else {
    668             if (value.isEmpty())
    669                 m_autocomplete = Uninitialized;
    670             else
    671                 m_autocomplete = On;
    672         }
    673     } else if (name == typeAttr)
    674         updateType();
    675     else if (name == valueAttr) {
    676         // We only need to setChanged if the form is looking at the default value right now.
    677         if (!hasDirtyValue()) {
    678             updatePlaceholderVisibility(false);
    679             setNeedsStyleRecalc();
    680         }
    681         setFormControlValueMatchesRenderer(false);
    682         setNeedsValidityCheck();
    683         m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress;
    684         m_inputType->valueAttributeChanged();
    685     } else if (name == checkedAttr) {
    686         // Another radio button in the same group might be checked by state
    687         // restore. We shouldn't call setChecked() even if this has the checked
    688         // attribute. So, delay the setChecked() call until
    689         // finishParsingChildren() is called if parsing is in progress.
    690         if (!m_parsingInProgress && m_reflectsCheckedAttribute) {
    691             setChecked(!value.isNull());
    692             m_reflectsCheckedAttribute = true;
    693         }
    694     } else if (name == maxlengthAttr)
    695         parseMaxLengthAttribute(value);
    696     else if (name == sizeAttr) {
    697         int oldSize = m_size;
    698         int valueAsInteger = value.toInt();
    699         m_size = valueAsInteger > 0 ? valueAsInteger : defaultSize;
    700         if (m_size != oldSize && renderer())
    701             renderer()->setNeedsLayoutAndPrefWidthsRecalc();
    702     } else if (name == altAttr)
    703         m_inputType->altAttributeChanged();
    704     else if (name == srcAttr)
    705         m_inputType->srcAttributeChanged();
    706     else if (name == usemapAttr || name == accesskeyAttr) {
    707         // FIXME: ignore for the moment
    708     } else if (name == onsearchAttr) {
    709         // Search field and slider attributes all just cause updateFromElement to be called through style recalcing.
    710         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, name, value));
    711     } else if (name == resultsAttr) {
    712         int oldResults = m_maxResults;
    713         m_maxResults = !value.isNull() ? std::min(value.toInt(), maxSavedResults) : -1;
    714         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
    715         // time to relayout for this change.
    716         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0))
    717             lazyReattachIfAttached();
    718         setNeedsStyleRecalc();
    719         UseCounter::count(document(), UseCounter::ResultsAttribute);
    720     } else if (name == incrementalAttr) {
    721         setNeedsStyleRecalc();
    722         UseCounter::count(document(), UseCounter::IncrementalAttribute);
    723     } else if (name == minAttr) {
    724         m_inputType->minOrMaxAttributeChanged();
    725         setNeedsValidityCheck();
    726         UseCounter::count(document(), UseCounter::MinAttribute);
    727     } else if (name == maxAttr) {
    728         m_inputType->minOrMaxAttributeChanged();
    729         setNeedsValidityCheck();
    730         UseCounter::count(document(), UseCounter::MaxAttribute);
    731     } else if (name == multipleAttr) {
    732         m_inputType->multipleAttributeChanged();
    733         setNeedsValidityCheck();
    734     } else if (name == stepAttr) {
    735         m_inputType->stepAttributeChanged();
    736         setNeedsValidityCheck();
    737         UseCounter::count(document(), UseCounter::StepAttribute);
    738     } else if (name == patternAttr) {
    739         setNeedsValidityCheck();
    740         UseCounter::count(document(), UseCounter::PatternAttribute);
    741     } else if (name == precisionAttr) {
    742         setNeedsValidityCheck();
    743         UseCounter::count(document(), UseCounter::PrecisionAttribute);
    744     } else if (name == disabledAttr) {
    745         HTMLTextFormControlElement::parseAttribute(name, value);
    746         m_inputType->disabledAttributeChanged();
    747     } else if (name == readonlyAttr) {
    748         HTMLTextFormControlElement::parseAttribute(name, value);
    749         m_inputType->readonlyAttributeChanged();
    750     } else if (name == listAttr) {
    751         m_hasNonEmptyList = !value.isEmpty();
    752         if (m_hasNonEmptyList) {
    753             resetListAttributeTargetObserver();
    754             listAttributeTargetChanged();
    755         }
    756         UseCounter::count(document(), UseCounter::ListAttribute);
    757     }
    758 #if ENABLE(INPUT_SPEECH)
    759     else if (name == webkitspeechAttr) {
    760         if (RuntimeEnabledFeatures::speechInputEnabled() && m_inputType->shouldRespectSpeechAttribute()) {
    761             // This renderer and its children have quite different layouts and
    762             // styles depending on whether the speech button is visible or
    763             // not. So we reset the whole thing and recreate to get the right
    764             // styles and layout.
    765             m_inputType->destroyShadowSubtree();
    766             lazyReattachIfAttached();
    767             m_inputType->createShadowSubtree();
    768             setFormControlValueMatchesRenderer(false);
    769         }
    770         UseCounter::count(document(), UseCounter::PrefixedSpeechAttribute);
    771     } else if (name == onwebkitspeechchangeAttr)
    772         setAttributeEventListener(eventNames().webkitspeechchangeEvent, createAttributeEventListener(this, name, value));
    773 #endif
    774     else if (name == webkitdirectoryAttr) {
    775         HTMLTextFormControlElement::parseAttribute(name, value);
    776         UseCounter::count(document(), UseCounter::PrefixedDirectoryAttribute);
    777     }
    778     else
    779         HTMLTextFormControlElement::parseAttribute(name, value);
    780     m_inputType->attributeChanged();
    781 }
    782 
    783 void HTMLInputElement::finishParsingChildren()
    784 {
    785     m_parsingInProgress = false;
    786     HTMLTextFormControlElement::finishParsingChildren();
    787     if (!m_stateRestored) {
    788         bool checked = hasAttribute(checkedAttr);
    789         if (checked)
    790             setChecked(checked);
    791         m_reflectsCheckedAttribute = true;
    792     }
    793 }
    794 
    795 bool HTMLInputElement::rendererIsNeeded(const NodeRenderingContext& context)
    796 {
    797     return m_inputType->rendererIsNeeded() && HTMLTextFormControlElement::rendererIsNeeded(context);
    798 }
    799 
    800 RenderObject* HTMLInputElement::createRenderer(RenderStyle* style)
    801 {
    802     return m_inputType->createRenderer(style);
    803 }
    804 
    805 void HTMLInputElement::attach(const AttachContext& context)
    806 {
    807     PostAttachCallbackDisabler disabler(this);
    808 
    809     if (!m_hasType)
    810         updateType();
    811 
    812     HTMLTextFormControlElement::attach(context);
    813 
    814     m_inputType->attach();
    815 
    816     if (document()->focusedElement() == this)
    817         document()->updateFocusAppearanceSoon(true /* restore selection */);
    818 }
    819 
    820 void HTMLInputElement::detach(const AttachContext& context)
    821 {
    822     HTMLTextFormControlElement::detach(context);
    823     setFormControlValueMatchesRenderer(false);
    824     m_inputType->detach();
    825 }
    826 
    827 String HTMLInputElement::altText() const
    828 {
    829     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
    830     // also heavily discussed by Hixie on bugzilla
    831     // note this is intentionally different to HTMLImageElement::altText()
    832     String alt = fastGetAttribute(altAttr);
    833     // fall back to title attribute
    834     if (alt.isNull())
    835         alt = getAttribute(titleAttr);
    836     if (alt.isNull())
    837         alt = getAttribute(valueAttr);
    838     if (alt.isEmpty())
    839         alt = inputElementAltText();
    840     return alt;
    841 }
    842 
    843 bool HTMLInputElement::isSuccessfulSubmitButton() const
    844 {
    845     // HTML spec says that buttons must have names to be considered successful.
    846     // However, other browsers do not impose this constraint. So we do not.
    847     return !isDisabledFormControl() && m_inputType->canBeSuccessfulSubmitButton();
    848 }
    849 
    850 bool HTMLInputElement::isActivatedSubmit() const
    851 {
    852     return m_isActivatedSubmit;
    853 }
    854 
    855 void HTMLInputElement::setActivatedSubmit(bool flag)
    856 {
    857     m_isActivatedSubmit = flag;
    858 }
    859 
    860 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
    861 {
    862     return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(encoding, multipart);
    863 }
    864 
    865 void HTMLInputElement::reset()
    866 {
    867     if (m_inputType->storesValueSeparateFromAttribute())
    868         setValue(String());
    869 
    870     setAutofilled(false);
    871     setChecked(hasAttribute(checkedAttr));
    872     m_reflectsCheckedAttribute = true;
    873 }
    874 
    875 bool HTMLInputElement::isTextField() const
    876 {
    877     return m_inputType->isTextField();
    878 }
    879 
    880 bool HTMLInputElement::isTextType() const
    881 {
    882     return m_inputType->isTextType();
    883 }
    884 
    885 void HTMLInputElement::setChecked(bool nowChecked, TextFieldEventBehavior eventBehavior)
    886 {
    887     if (checked() == nowChecked)
    888         return;
    889 
    890     m_reflectsCheckedAttribute = false;
    891     m_isChecked = nowChecked;
    892     setNeedsStyleRecalc();
    893 
    894     if (CheckedRadioButtons* buttons = checkedRadioButtons())
    895             buttons->updateCheckedState(this);
    896     if (renderer() && renderer()->style()->hasAppearance())
    897         renderer()->theme()->stateChanged(renderer(), CheckedState);
    898     setNeedsValidityCheck();
    899 
    900     // Ideally we'd do this from the render tree (matching
    901     // RenderTextView), but it's not possible to do it at the moment
    902     // because of the way the code is structured.
    903     if (renderer()) {
    904         if (AXObjectCache* cache = renderer()->document()->existingAXObjectCache())
    905             cache->checkedStateChanged(this);
    906     }
    907 
    908     // Only send a change event for items in the document (avoid firing during
    909     // parsing) and don't send a change event for a radio button that's getting
    910     // unchecked to match other browsers. DOM is not a useful standard for this
    911     // because it says only to fire change events at "lose focus" time, which is
    912     // definitely wrong in practice for these types of elements.
    913     if (eventBehavior != DispatchNoEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) {
    914         setTextAsOfLastFormControlChangeEvent(String());
    915         dispatchFormControlChangeEvent();
    916     }
    917 
    918     didAffectSelector(AffectedSelectorChecked);
    919 }
    920 
    921 void HTMLInputElement::setIndeterminate(bool newValue)
    922 {
    923     if (indeterminate() == newValue)
    924         return;
    925 
    926     m_isIndeterminate = newValue;
    927 
    928     didAffectSelector(AffectedSelectorIndeterminate);
    929 
    930     if (renderer() && renderer()->style()->hasAppearance())
    931         renderer()->theme()->stateChanged(renderer(), CheckedState);
    932 }
    933 
    934 int HTMLInputElement::size() const
    935 {
    936     return m_size;
    937 }
    938 
    939 bool HTMLInputElement::sizeShouldIncludeDecoration(int& preferredSize) const
    940 {
    941     return m_inputType->sizeShouldIncludeDecoration(defaultSize, preferredSize);
    942 }
    943 
    944 void HTMLInputElement::copyNonAttributePropertiesFromElement(const Element& source)
    945 {
    946     const HTMLInputElement& sourceElement = static_cast<const HTMLInputElement&>(source);
    947 
    948     m_valueIfDirty = sourceElement.m_valueIfDirty;
    949     m_wasModifiedByUser = false;
    950     setChecked(sourceElement.m_isChecked);
    951     m_reflectsCheckedAttribute = sourceElement.m_reflectsCheckedAttribute;
    952     m_isIndeterminate = sourceElement.m_isIndeterminate;
    953 
    954     HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source);
    955 
    956     setFormControlValueMatchesRenderer(false);
    957     m_inputType->updateInnerTextValue();
    958 }
    959 
    960 String HTMLInputElement::value() const
    961 {
    962     String value;
    963     if (m_inputType->getTypeSpecificValue(value))
    964         return value;
    965 
    966     value = m_valueIfDirty;
    967     if (!value.isNull())
    968         return value;
    969 
    970     AtomicString valueString = fastGetAttribute(valueAttr);
    971     value = sanitizeValue(valueString);
    972     if (!value.isNull())
    973         return value;
    974 
    975     return m_inputType->fallbackValue();
    976 }
    977 
    978 String HTMLInputElement::valueWithDefault() const
    979 {
    980     String value = this->value();
    981     if (!value.isNull())
    982         return value;
    983 
    984     return m_inputType->defaultValue();
    985 }
    986 
    987 void HTMLInputElement::setValueForUser(const String& value)
    988 {
    989     // Call setValue and make it send a change event.
    990     setValue(value, DispatchChangeEvent);
    991 }
    992 
    993 const String& HTMLInputElement::suggestedValue() const
    994 {
    995     return m_suggestedValue;
    996 }
    997 
    998 void HTMLInputElement::setSuggestedValue(const String& value)
    999 {
   1000     if (!m_inputType->canSetSuggestedValue())
   1001         return;
   1002     setFormControlValueMatchesRenderer(false);
   1003     m_suggestedValue = sanitizeValue(value);
   1004     setNeedsStyleRecalc();
   1005     m_inputType->updateInnerTextValue();
   1006 }
   1007 
   1008 void HTMLInputElement::setEditingValue(const String& value)
   1009 {
   1010     if (!renderer() || !isTextField())
   1011         return;
   1012     setInnerTextValue(value);
   1013     subtreeHasChanged();
   1014 
   1015     unsigned max = value.length();
   1016     if (focused())
   1017         setSelectionRange(max, max);
   1018     else
   1019         cacheSelectionInResponseToSetValue(max);
   1020 
   1021     dispatchInputEvent();
   1022 }
   1023 
   1024 void HTMLInputElement::setValue(const String& value, ExceptionState& es, TextFieldEventBehavior eventBehavior)
   1025 {
   1026     if (isFileUpload() && !value.isEmpty()) {
   1027         es.throwDOMException(InvalidStateError);
   1028         return;
   1029     }
   1030     setValue(value, eventBehavior);
   1031 }
   1032 
   1033 void HTMLInputElement::setValue(const String& value, TextFieldEventBehavior eventBehavior)
   1034 {
   1035     if (!m_inputType->canSetValue(value))
   1036         return;
   1037 
   1038     RefPtr<HTMLInputElement> protector(this);
   1039     EventQueueScope scope;
   1040     String sanitizedValue = sanitizeValue(value);
   1041     bool valueChanged = sanitizedValue != this->value();
   1042 
   1043     setLastChangeWasNotUserEdit();
   1044     setFormControlValueMatchesRenderer(false);
   1045     m_suggestedValue = String(); // Prevent TextFieldInputType::setValue from using the suggested value.
   1046     m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior);
   1047 
   1048     if (!valueChanged)
   1049         return;
   1050 
   1051     notifyFormStateChanged();
   1052 }
   1053 
   1054 void HTMLInputElement::setValueInternal(const String& sanitizedValue, TextFieldEventBehavior eventBehavior)
   1055 {
   1056     m_valueIfDirty = sanitizedValue;
   1057     m_wasModifiedByUser = eventBehavior != DispatchNoEvent;
   1058     setNeedsValidityCheck();
   1059 }
   1060 
   1061 double HTMLInputElement::valueAsDate() const
   1062 {
   1063     return m_inputType->valueAsDate();
   1064 }
   1065 
   1066 void HTMLInputElement::setValueAsDate(double value, ExceptionState& es)
   1067 {
   1068     m_inputType->setValueAsDate(value, es);
   1069 }
   1070 
   1071 double HTMLInputElement::valueAsNumber() const
   1072 {
   1073     return m_inputType->valueAsDouble();
   1074 }
   1075 
   1076 void HTMLInputElement::setValueAsNumber(double newValue, ExceptionState& es, TextFieldEventBehavior eventBehavior)
   1077 {
   1078     if (!std::isfinite(newValue)) {
   1079         es.throwDOMException(NotSupportedError);
   1080         return;
   1081     }
   1082     m_inputType->setValueAsDouble(newValue, eventBehavior, es);
   1083 }
   1084 
   1085 void HTMLInputElement::setValueFromRenderer(const String& value)
   1086 {
   1087     // File upload controls will never use this.
   1088     ASSERT(!isFileUpload());
   1089 
   1090     m_suggestedValue = String();
   1091 
   1092     // Renderer and our event handler are responsible for sanitizing values.
   1093     ASSERT(value == sanitizeValue(value) || sanitizeValue(value).isEmpty());
   1094 
   1095     m_valueIfDirty = value;
   1096 
   1097     setFormControlValueMatchesRenderer(true);
   1098     m_wasModifiedByUser = true;
   1099 
   1100     // Input event is fired by the Node::defaultEventHandler for editable controls.
   1101     if (!isTextField())
   1102         dispatchInputEvent();
   1103     notifyFormStateChanged();
   1104 
   1105     setNeedsValidityCheck();
   1106 
   1107     // Clear autofill flag (and yellow background) on user edit.
   1108     setAutofilled(false);
   1109 }
   1110 
   1111 void* HTMLInputElement::preDispatchEventHandler(Event* event)
   1112 {
   1113     if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
   1114         event->stopPropagation();
   1115         return 0;
   1116     }
   1117     if (event->type() != eventNames().clickEvent)
   1118         return 0;
   1119     if (!event->isMouseEvent() || toMouseEvent(event)->button() != LeftButton)
   1120         return 0;
   1121     // FIXME: Check whether there are any cases where this actually ends up leaking.
   1122     return m_inputType->willDispatchClick().leakPtr();
   1123 }
   1124 
   1125 void HTMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
   1126 {
   1127     OwnPtr<ClickHandlingState> state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch));
   1128     if (!state)
   1129         return;
   1130     m_inputType->didDispatchClick(event, *state);
   1131 }
   1132 
   1133 void HTMLInputElement::defaultEventHandler(Event* evt)
   1134 {
   1135     if (evt->isMouseEvent() && evt->type() == eventNames().clickEvent && toMouseEvent(evt)->button() == LeftButton) {
   1136         m_inputType->handleClickEvent(toMouseEvent(evt));
   1137         if (evt->defaultHandled())
   1138             return;
   1139     }
   1140 
   1141     if (evt->isTouchEvent()) {
   1142         m_inputType->handleTouchEvent(static_cast<TouchEvent*>(evt));
   1143         if (evt->defaultHandled())
   1144             return;
   1145     }
   1146 
   1147     if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
   1148         m_inputType->handleKeydownEvent(toKeyboardEvent(evt));
   1149         if (evt->defaultHandled())
   1150             return;
   1151     }
   1152 
   1153     // Call the base event handler before any of our own event handling for almost all events in text fields.
   1154     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
   1155     bool callBaseClassEarly = isTextField() && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
   1156     if (callBaseClassEarly) {
   1157         HTMLTextFormControlElement::defaultEventHandler(evt);
   1158         if (evt->defaultHandled())
   1159             return;
   1160     }
   1161 
   1162     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
   1163     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
   1164     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
   1165     // must dispatch a DOMActivate event - a click event will not do the job.
   1166     if (evt->type() == eventNames().DOMActivateEvent) {
   1167         m_inputType->handleDOMActivateEvent(evt);
   1168         if (evt->defaultHandled())
   1169             return;
   1170     }
   1171 
   1172     // Use key press event here since sending simulated mouse events
   1173     // on key down blocks the proper sending of the key press event.
   1174     if (evt->isKeyboardEvent() && evt->type() == eventNames().keypressEvent) {
   1175         m_inputType->handleKeypressEvent(toKeyboardEvent(evt));
   1176         if (evt->defaultHandled())
   1177             return;
   1178     }
   1179 
   1180     if (evt->isKeyboardEvent() && evt->type() == eventNames().keyupEvent) {
   1181         m_inputType->handleKeyupEvent(toKeyboardEvent(evt));
   1182         if (evt->defaultHandled())
   1183             return;
   1184     }
   1185 
   1186     if (m_inputType->shouldSubmitImplicitly(evt)) {
   1187         if (isSearchField())
   1188             onSearch();
   1189         // Form submission finishes editing, just as loss of focus does.
   1190         // If there was a change, send the event now.
   1191         if (wasChangedSinceLastFormControlChangeEvent())
   1192             dispatchFormControlChangeEvent();
   1193 
   1194         RefPtr<HTMLFormElement> formForSubmission = m_inputType->formForSubmission();
   1195         // Form may never have been present, or may have been destroyed by code responding to the change event.
   1196         if (formForSubmission)
   1197             formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
   1198 
   1199         evt->setDefaultHandled();
   1200         return;
   1201     }
   1202 
   1203     if (evt->isBeforeTextInsertedEvent())
   1204         m_inputType->handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(evt));
   1205 
   1206     if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
   1207         m_inputType->handleMouseDownEvent(toMouseEvent(evt));
   1208         if (evt->defaultHandled())
   1209             return;
   1210     }
   1211 
   1212     m_inputType->forwardEvent(evt);
   1213 
   1214     if (!callBaseClassEarly && !evt->defaultHandled())
   1215         HTMLTextFormControlElement::defaultEventHandler(evt);
   1216 }
   1217 
   1218 bool HTMLInputElement::willRespondToMouseClickEvents()
   1219 {
   1220     // FIXME: Consider implementing willRespondToMouseClickEvents() in InputType if more accurate results are necessary.
   1221     if (!isDisabledFormControl())
   1222         return true;
   1223 
   1224     return HTMLTextFormControlElement::willRespondToMouseClickEvents();
   1225 }
   1226 
   1227 bool HTMLInputElement::isURLAttribute(const Attribute& attribute) const
   1228 {
   1229     return attribute.name() == srcAttr || attribute.name() == formactionAttr || HTMLTextFormControlElement::isURLAttribute(attribute);
   1230 }
   1231 
   1232 String HTMLInputElement::defaultValue() const
   1233 {
   1234     return fastGetAttribute(valueAttr);
   1235 }
   1236 
   1237 void HTMLInputElement::setDefaultValue(const String &value)
   1238 {
   1239     setAttribute(valueAttr, value);
   1240 }
   1241 
   1242 static inline bool isRFC2616TokenCharacter(UChar ch)
   1243 {
   1244     return isASCII(ch) && ch > ' ' && ch != '"' && ch != '(' && ch != ')' && ch != ',' && ch != '/' && (ch < ':' || ch > '@') && (ch < '[' || ch > ']') && ch != '{' && ch != '}' && ch != 0x7f;
   1245 }
   1246 
   1247 static bool isValidMIMEType(const String& type)
   1248 {
   1249     size_t slashPosition = type.find('/');
   1250     if (slashPosition == notFound || !slashPosition || slashPosition == type.length() - 1)
   1251         return false;
   1252     for (size_t i = 0; i < type.length(); ++i) {
   1253         if (!isRFC2616TokenCharacter(type[i]) && i != slashPosition)
   1254             return false;
   1255     }
   1256     return true;
   1257 }
   1258 
   1259 static bool isValidFileExtension(const String& type)
   1260 {
   1261     if (type.length() < 2)
   1262         return false;
   1263     return type[0] == '.';
   1264 }
   1265 
   1266 static Vector<String> parseAcceptAttribute(const String& acceptString, bool (*predicate)(const String&))
   1267 {
   1268     Vector<String> types;
   1269     if (acceptString.isEmpty())
   1270         return types;
   1271 
   1272     Vector<String> splitTypes;
   1273     acceptString.split(',', false, splitTypes);
   1274     for (size_t i = 0; i < splitTypes.size(); ++i) {
   1275         String trimmedType = stripLeadingAndTrailingHTMLSpaces(splitTypes[i]);
   1276         if (trimmedType.isEmpty())
   1277             continue;
   1278         if (!predicate(trimmedType))
   1279             continue;
   1280         types.append(trimmedType.lower());
   1281     }
   1282 
   1283     return types;
   1284 }
   1285 
   1286 Vector<String> HTMLInputElement::acceptMIMETypes()
   1287 {
   1288     return parseAcceptAttribute(fastGetAttribute(acceptAttr), isValidMIMEType);
   1289 }
   1290 
   1291 Vector<String> HTMLInputElement::acceptFileExtensions()
   1292 {
   1293     return parseAcceptAttribute(fastGetAttribute(acceptAttr), isValidFileExtension);
   1294 }
   1295 
   1296 String HTMLInputElement::accept() const
   1297 {
   1298     return fastGetAttribute(acceptAttr);
   1299 }
   1300 
   1301 String HTMLInputElement::alt() const
   1302 {
   1303     return fastGetAttribute(altAttr);
   1304 }
   1305 
   1306 int HTMLInputElement::maxLength() const
   1307 {
   1308     return m_maxLength;
   1309 }
   1310 
   1311 void HTMLInputElement::setMaxLength(int maxLength, ExceptionState& es)
   1312 {
   1313     if (maxLength < 0)
   1314         es.throwDOMException(IndexSizeError);
   1315     else
   1316         setAttribute(maxlengthAttr, String::number(maxLength));
   1317 }
   1318 
   1319 bool HTMLInputElement::multiple() const
   1320 {
   1321     return fastHasAttribute(multipleAttr);
   1322 }
   1323 
   1324 void HTMLInputElement::setSize(unsigned size)
   1325 {
   1326     setAttribute(sizeAttr, String::number(size));
   1327 }
   1328 
   1329 void HTMLInputElement::setSize(unsigned size, ExceptionState& es)
   1330 {
   1331     if (!size)
   1332         es.throwDOMException(IndexSizeError);
   1333     else
   1334         setSize(size);
   1335 }
   1336 
   1337 KURL HTMLInputElement::src() const
   1338 {
   1339     return document()->completeURL(fastGetAttribute(srcAttr));
   1340 }
   1341 
   1342 void HTMLInputElement::setAutofilled(bool autofilled)
   1343 {
   1344     if (autofilled == m_isAutofilled)
   1345         return;
   1346 
   1347     m_isAutofilled = autofilled;
   1348     setNeedsStyleRecalc();
   1349 }
   1350 
   1351 FileList* HTMLInputElement::files()
   1352 {
   1353     return m_inputType->files();
   1354 }
   1355 
   1356 void HTMLInputElement::setFiles(PassRefPtr<FileList> files)
   1357 {
   1358     m_inputType->setFiles(files);
   1359 }
   1360 
   1361 bool HTMLInputElement::receiveDroppedFiles(const DragData* dragData)
   1362 {
   1363     return m_inputType->receiveDroppedFiles(dragData);
   1364 }
   1365 
   1366 String HTMLInputElement::droppedFileSystemId()
   1367 {
   1368     return m_inputType->droppedFileSystemId();
   1369 }
   1370 
   1371 bool HTMLInputElement::canReceiveDroppedFiles() const
   1372 {
   1373     return m_canReceiveDroppedFiles;
   1374 }
   1375 
   1376 void HTMLInputElement::setCanReceiveDroppedFiles(bool canReceiveDroppedFiles)
   1377 {
   1378     if (m_canReceiveDroppedFiles == canReceiveDroppedFiles)
   1379         return;
   1380     m_canReceiveDroppedFiles = canReceiveDroppedFiles;
   1381     if (renderer())
   1382         renderer()->updateFromElement();
   1383 }
   1384 
   1385 String HTMLInputElement::visibleValue() const
   1386 {
   1387     return m_inputType->visibleValue();
   1388 }
   1389 
   1390 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
   1391 {
   1392     if (proposedValue.isNull())
   1393         return proposedValue;
   1394     return m_inputType->sanitizeValue(proposedValue);
   1395 }
   1396 
   1397 String HTMLInputElement::localizeValue(const String& proposedValue) const
   1398 {
   1399     if (proposedValue.isNull())
   1400         return proposedValue;
   1401     return m_inputType->localizeValue(proposedValue);
   1402 }
   1403 
   1404 bool HTMLInputElement::isInRange() const
   1405 {
   1406     return m_inputType->isInRange(value());
   1407 }
   1408 
   1409 bool HTMLInputElement::isOutOfRange() const
   1410 {
   1411     return m_inputType->isOutOfRange(value());
   1412 }
   1413 
   1414 bool HTMLInputElement::isRequiredFormControl() const
   1415 {
   1416     return m_inputType->supportsRequired() && isRequired();
   1417 }
   1418 
   1419 bool HTMLInputElement::matchesReadOnlyPseudoClass() const
   1420 {
   1421     return m_inputType->supportsReadOnly() && isReadOnly();
   1422 }
   1423 
   1424 bool HTMLInputElement::matchesReadWritePseudoClass() const
   1425 {
   1426     return m_inputType->supportsReadOnly() && !isReadOnly();
   1427 }
   1428 
   1429 void HTMLInputElement::onSearch()
   1430 {
   1431     ASSERT(isSearchField());
   1432     if (m_inputType)
   1433         static_cast<SearchInputType*>(m_inputType.get())->stopSearchEventTimer();
   1434     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
   1435 }
   1436 
   1437 void HTMLInputElement::updateClearButtonVisibility()
   1438 {
   1439     m_inputType->updateClearButtonVisibility();
   1440 }
   1441 
   1442 void HTMLInputElement::willChangeForm()
   1443 {
   1444     removeFromRadioButtonGroup();
   1445     HTMLTextFormControlElement::willChangeForm();
   1446 }
   1447 
   1448 void HTMLInputElement::didChangeForm()
   1449 {
   1450     HTMLTextFormControlElement::didChangeForm();
   1451     addToRadioButtonGroup();
   1452 }
   1453 
   1454 Node::InsertionNotificationRequest HTMLInputElement::insertedInto(ContainerNode* insertionPoint)
   1455 {
   1456     HTMLTextFormControlElement::insertedInto(insertionPoint);
   1457     if (insertionPoint->inDocument() && !form())
   1458         addToRadioButtonGroup();
   1459     resetListAttributeTargetObserver();
   1460     return InsertionDone;
   1461 }
   1462 
   1463 void HTMLInputElement::removedFrom(ContainerNode* insertionPoint)
   1464 {
   1465     if (insertionPoint->inDocument() && !form())
   1466         removeFromRadioButtonGroup();
   1467     HTMLTextFormControlElement::removedFrom(insertionPoint);
   1468     ASSERT(!inDocument());
   1469     resetListAttributeTargetObserver();
   1470 }
   1471 
   1472 void HTMLInputElement::didMoveToNewDocument(Document* oldDocument)
   1473 {
   1474     if (hasImageLoader())
   1475         imageLoader()->elementDidMoveToNewDocument();
   1476 
   1477     if (oldDocument) {
   1478         if (isRadioButton())
   1479             oldDocument->formController()->checkedRadioButtons().removeButton(this);
   1480         if (m_hasTouchEventHandler)
   1481             oldDocument->didRemoveEventTargetNode(this);
   1482     }
   1483 
   1484     if (m_hasTouchEventHandler)
   1485         document()->didAddTouchEventHandler(this);
   1486 
   1487     HTMLTextFormControlElement::didMoveToNewDocument(oldDocument);
   1488 }
   1489 
   1490 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
   1491 {
   1492     HTMLTextFormControlElement::addSubresourceAttributeURLs(urls);
   1493 
   1494     addSubresourceURL(urls, src());
   1495 }
   1496 
   1497 bool HTMLInputElement::recalcWillValidate() const
   1498 {
   1499     return m_inputType->supportsValidation() && HTMLTextFormControlElement::recalcWillValidate();
   1500 }
   1501 
   1502 void HTMLInputElement::requiredAttributeChanged()
   1503 {
   1504     HTMLTextFormControlElement::requiredAttributeChanged();
   1505     if (CheckedRadioButtons* buttons = checkedRadioButtons())
   1506         buttons->requiredAttributeChanged(this);
   1507     m_inputType->requiredAttributeChanged();
   1508 }
   1509 
   1510 void HTMLInputElement::selectColorInColorChooser(const Color& color)
   1511 {
   1512     if (!m_inputType->isColorControl())
   1513         return;
   1514     static_cast<ColorInputType*>(m_inputType.get())->didChooseColor(color);
   1515 }
   1516 
   1517 HTMLElement* HTMLInputElement::list() const
   1518 {
   1519     return dataList();
   1520 }
   1521 
   1522 HTMLDataListElement* HTMLInputElement::dataList() const
   1523 {
   1524     if (!m_hasNonEmptyList)
   1525         return 0;
   1526 
   1527     if (!m_inputType->shouldRespectListAttribute())
   1528         return 0;
   1529 
   1530     Element* element = treeScope()->getElementById(fastGetAttribute(listAttr));
   1531     if (!element)
   1532         return 0;
   1533     if (!element->hasTagName(datalistTag))
   1534         return 0;
   1535 
   1536     return static_cast<HTMLDataListElement*>(element);
   1537 }
   1538 
   1539 void HTMLInputElement::resetListAttributeTargetObserver()
   1540 {
   1541     if (inDocument())
   1542         m_listAttributeTargetObserver = ListAttributeTargetObserver::create(fastGetAttribute(listAttr), this);
   1543     else
   1544         m_listAttributeTargetObserver = nullptr;
   1545 }
   1546 
   1547 void HTMLInputElement::listAttributeTargetChanged()
   1548 {
   1549     m_inputType->listAttributeTargetChanged();
   1550 }
   1551 
   1552 bool HTMLInputElement::isSteppable() const
   1553 {
   1554     return m_inputType->isSteppable();
   1555 }
   1556 
   1557 #if ENABLE(INPUT_SPEECH)
   1558 
   1559 bool HTMLInputElement::isSpeechEnabled() const
   1560 {
   1561     // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types.
   1562     return m_inputType->shouldRespectSpeechAttribute() && RuntimeEnabledFeatures::speechInputEnabled() && hasAttribute(webkitspeechAttr);
   1563 }
   1564 
   1565 #endif
   1566 
   1567 bool HTMLInputElement::isTextButton() const
   1568 {
   1569     return m_inputType->isTextButton();
   1570 }
   1571 
   1572 bool HTMLInputElement::isRadioButton() const
   1573 {
   1574     return m_inputType->isRadioButton();
   1575 }
   1576 
   1577 bool HTMLInputElement::isSearchField() const
   1578 {
   1579     return m_inputType->isSearchField();
   1580 }
   1581 
   1582 bool HTMLInputElement::isInputTypeHidden() const
   1583 {
   1584     return m_inputType->isHiddenType();
   1585 }
   1586 
   1587 bool HTMLInputElement::isPasswordField() const
   1588 {
   1589     return m_inputType->isPasswordField();
   1590 }
   1591 
   1592 bool HTMLInputElement::isCheckbox() const
   1593 {
   1594     return m_inputType->isCheckbox();
   1595 }
   1596 
   1597 bool HTMLInputElement::isRangeControl() const
   1598 {
   1599     return m_inputType->isRangeControl();
   1600 }
   1601 
   1602 bool HTMLInputElement::isColorControl() const
   1603 {
   1604     return m_inputType->isColorControl();
   1605 }
   1606 
   1607 bool HTMLInputElement::isText() const
   1608 {
   1609     return m_inputType->isTextType();
   1610 }
   1611 
   1612 bool HTMLInputElement::isEmailField() const
   1613 {
   1614     return m_inputType->isEmailField();
   1615 }
   1616 
   1617 bool HTMLInputElement::isFileUpload() const
   1618 {
   1619     return m_inputType->isFileUpload();
   1620 }
   1621 
   1622 bool HTMLInputElement::isImageButton() const
   1623 {
   1624     return m_inputType->isImageButton();
   1625 }
   1626 
   1627 bool HTMLInputElement::isNumberField() const
   1628 {
   1629     return m_inputType->isNumberField();
   1630 }
   1631 
   1632 bool HTMLInputElement::isSubmitButton() const
   1633 {
   1634     return m_inputType->isSubmitButton();
   1635 }
   1636 
   1637 bool HTMLInputElement::isTelephoneField() const
   1638 {
   1639     return m_inputType->isTelephoneField();
   1640 }
   1641 
   1642 bool HTMLInputElement::isURLField() const
   1643 {
   1644     return m_inputType->isURLField();
   1645 }
   1646 
   1647 bool HTMLInputElement::isDateField() const
   1648 {
   1649     return m_inputType->isDateField();
   1650 }
   1651 
   1652 bool HTMLInputElement::isDateTimeLocalField() const
   1653 {
   1654     return m_inputType->isDateTimeLocalField();
   1655 }
   1656 
   1657 bool HTMLInputElement::isMonthField() const
   1658 {
   1659     return m_inputType->isMonthField();
   1660 }
   1661 
   1662 bool HTMLInputElement::isTimeField() const
   1663 {
   1664     return m_inputType->isTimeField();
   1665 }
   1666 
   1667 bool HTMLInputElement::isWeekField() const
   1668 {
   1669     return m_inputType->isWeekField();
   1670 }
   1671 
   1672 bool HTMLInputElement::isEnumeratable() const
   1673 {
   1674     return m_inputType->isEnumeratable();
   1675 }
   1676 
   1677 bool HTMLInputElement::supportLabels() const
   1678 {
   1679     return m_inputType->supportLabels();
   1680 }
   1681 
   1682 bool HTMLInputElement::shouldAppearChecked() const
   1683 {
   1684     return checked() && m_inputType->isCheckable();
   1685 }
   1686 
   1687 bool HTMLInputElement::supportsPlaceholder() const
   1688 {
   1689     return m_inputType->supportsPlaceholder();
   1690 }
   1691 
   1692 void HTMLInputElement::updatePlaceholderText()
   1693 {
   1694     return m_inputType->updatePlaceholderText();
   1695 }
   1696 
   1697 void HTMLInputElement::parseMaxLengthAttribute(const AtomicString& value)
   1698 {
   1699     int maxLength;
   1700     if (!parseHTMLInteger(value, maxLength))
   1701         maxLength = maximumLength;
   1702     if (maxLength < 0 || maxLength > maximumLength)
   1703         maxLength = maximumLength;
   1704     int oldMaxLength = m_maxLength;
   1705     m_maxLength = maxLength;
   1706     if (oldMaxLength != maxLength)
   1707         updateValueIfNeeded();
   1708     setNeedsStyleRecalc();
   1709     setNeedsValidityCheck();
   1710 }
   1711 
   1712 void HTMLInputElement::updateValueIfNeeded()
   1713 {
   1714     String newValue = sanitizeValue(m_valueIfDirty);
   1715     ASSERT(!m_valueIfDirty.isNull() || newValue.isNull());
   1716     if (newValue != m_valueIfDirty)
   1717         setValue(newValue);
   1718 }
   1719 
   1720 String HTMLInputElement::defaultToolTip() const
   1721 {
   1722     return m_inputType->defaultToolTip();
   1723 }
   1724 
   1725 bool HTMLInputElement::shouldAppearIndeterminate() const
   1726 {
   1727     return m_inputType->supportsIndeterminateAppearance() && indeterminate();
   1728 }
   1729 
   1730 #if ENABLE(MEDIA_CAPTURE)
   1731 bool HTMLInputElement::capture() const
   1732 {
   1733     if (!isFileUpload() || !fastHasAttribute(captureAttr))
   1734         return false;
   1735 
   1736     // As per crbug.com/240252, emit a deprecation warning when the "capture"
   1737     // attribute is used as an enum. The spec has been updated and "capture" is
   1738     // supposed to be used as a boolean.
   1739     bool hasDeprecatedUsage = !fastGetAttribute(captureAttr).isNull();
   1740     if (hasDeprecatedUsage)
   1741         UseCounter::countDeprecation(document(), UseCounter::CaptureAttributeAsEnum);
   1742     else
   1743         UseCounter::count(document(), UseCounter::CaptureAttributeAsEnum);
   1744 
   1745     return true;
   1746 }
   1747 #endif
   1748 
   1749 bool HTMLInputElement::isInRequiredRadioButtonGroup()
   1750 {
   1751     ASSERT(isRadioButton());
   1752     if (CheckedRadioButtons* buttons = checkedRadioButtons())
   1753         return buttons->isInRequiredGroup(this);
   1754     return false;
   1755 }
   1756 
   1757 HTMLInputElement* HTMLInputElement::checkedRadioButtonForGroup() const
   1758 {
   1759     if (CheckedRadioButtons* buttons = checkedRadioButtons())
   1760         return buttons->checkedButtonForGroup(name());
   1761     return 0;
   1762 }
   1763 
   1764 CheckedRadioButtons* HTMLInputElement::checkedRadioButtons() const
   1765 {
   1766     if (!isRadioButton())
   1767         return 0;
   1768     if (HTMLFormElement* formElement = form())
   1769         return &formElement->checkedRadioButtons();
   1770     if (inDocument())
   1771         return &document()->formController()->checkedRadioButtons();
   1772     return 0;
   1773 }
   1774 
   1775 inline void HTMLInputElement::addToRadioButtonGroup()
   1776 {
   1777     if (CheckedRadioButtons* buttons = checkedRadioButtons())
   1778         buttons->addButton(this);
   1779 }
   1780 
   1781 inline void HTMLInputElement::removeFromRadioButtonGroup()
   1782 {
   1783     if (CheckedRadioButtons* buttons = checkedRadioButtons())
   1784         buttons->removeButton(this);
   1785 }
   1786 
   1787 unsigned HTMLInputElement::height() const
   1788 {
   1789     return m_inputType->height();
   1790 }
   1791 
   1792 unsigned HTMLInputElement::width() const
   1793 {
   1794     return m_inputType->width();
   1795 }
   1796 
   1797 void HTMLInputElement::setHeight(unsigned height)
   1798 {
   1799     setAttribute(heightAttr, String::number(height));
   1800 }
   1801 
   1802 void HTMLInputElement::setWidth(unsigned width)
   1803 {
   1804     setAttribute(widthAttr, String::number(width));
   1805 }
   1806 
   1807 PassOwnPtr<ListAttributeTargetObserver> ListAttributeTargetObserver::create(const AtomicString& id, HTMLInputElement* element)
   1808 {
   1809     return adoptPtr(new ListAttributeTargetObserver(id, element));
   1810 }
   1811 
   1812 ListAttributeTargetObserver::ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement* element)
   1813     : IdTargetObserver(element->treeScope()->idTargetObserverRegistry(), id)
   1814     , m_element(element)
   1815 {
   1816 }
   1817 
   1818 void ListAttributeTargetObserver::idTargetChanged()
   1819 {
   1820     m_element->listAttributeTargetChanged();
   1821 }
   1822 
   1823 void HTMLInputElement::setRangeText(const String& replacement, ExceptionState& es)
   1824 {
   1825     if (!m_inputType->supportsSelectionAPI()) {
   1826         es.throwDOMException(InvalidStateError);
   1827         return;
   1828     }
   1829 
   1830     HTMLTextFormControlElement::setRangeText(replacement, es);
   1831 }
   1832 
   1833 void HTMLInputElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& es)
   1834 {
   1835     if (!m_inputType->supportsSelectionAPI()) {
   1836         es.throwDOMException(InvalidStateError);
   1837         return;
   1838     }
   1839 
   1840     HTMLTextFormControlElement::setRangeText(replacement, start, end, selectionMode, es);
   1841 }
   1842 
   1843 bool HTMLInputElement::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
   1844 {
   1845     if (!document()->view())
   1846         return false;
   1847 
   1848     parameters.type = type();
   1849     parameters.minimum = minimum();
   1850     parameters.maximum = maximum();
   1851     parameters.required = isRequired();
   1852     if (!RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
   1853         parameters.locale = defaultLanguage();
   1854     else {
   1855         AtomicString computedLocale = computeInheritedLanguage();
   1856         parameters.locale = computedLocale.isEmpty() ? AtomicString(defaultLanguage()) : computedLocale;
   1857     }
   1858 
   1859     StepRange stepRange = createStepRange(RejectAny);
   1860     if (stepRange.hasStep()) {
   1861         parameters.step = stepRange.step().toDouble();
   1862         parameters.stepBase = stepRange.stepBase().toDouble();
   1863     } else {
   1864         parameters.step = 1.0;
   1865         parameters.stepBase = 0;
   1866     }
   1867 
   1868     parameters.anchorRectInRootView = document()->view()->contentsToRootView(pixelSnappedBoundingBox());
   1869     parameters.currentValue = value();
   1870     parameters.isAnchorElementRTL = computedStyle()->direction() == RTL;
   1871     if (RuntimeEnabledFeatures::dataListElementEnabled()) {
   1872         if (HTMLDataListElement* dataList = this->dataList()) {
   1873             RefPtr<HTMLCollection> options = dataList->options();
   1874             for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); ++i) {
   1875                 if (!isValidValue(option->value()))
   1876                     continue;
   1877                 parameters.suggestionValues.append(sanitizeValue(option->value()));
   1878                 parameters.localizedSuggestionValues.append(localizeValue(option->value()));
   1879                 parameters.suggestionLabels.append(option->value() == option->label() ? String() : option->label());
   1880             }
   1881         }
   1882     }
   1883     return true;
   1884 }
   1885 
   1886 bool HTMLInputElement::supportsInputModeAttribute() const
   1887 {
   1888     return m_inputType->supportsInputModeAttribute();
   1889 }
   1890 
   1891 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
   1892 PassRefPtr<RenderStyle> HTMLInputElement::customStyleForRenderer()
   1893 {
   1894     return m_inputType->customStyleForRenderer(originalStyleForRenderer());
   1895 }
   1896 #endif
   1897 
   1898 } // namespace
   1899