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