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