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