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