• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  *
25  */
26 
27 #include "config.h"
28 #include "HTMLInputElement.h"
29 
30 #include "AXObjectCache.h"
31 #include "Attribute.h"
32 #include "BeforeTextInsertedEvent.h"
33 #include "CSSPropertyNames.h"
34 #include "Document.h"
35 #include "EventNames.h"
36 #include "ExceptionCode.h"
37 #include "FileList.h"
38 #include "HTMLCollection.h"
39 #include "HTMLDataListElement.h"
40 #include "HTMLFormElement.h"
41 #include "HTMLNames.h"
42 #include "HTMLOptionElement.h"
43 #include "HTMLParserIdioms.h"
44 #include "InputType.h"
45 #include "KeyboardEvent.h"
46 #include "LocalizedStrings.h"
47 #include "MouseEvent.h"
48 #include "PlatformMouseEvent.h"
49 #include "RenderTextControlSingleLine.h"
50 #include "RenderTheme.h"
51 #include "RuntimeEnabledFeatures.h"
52 #include "ScriptEventListener.h"
53 #include "WheelEvent.h"
54 #include <wtf/MathExtras.h>
55 #include <wtf/StdLibExtras.h>
56 
57 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
58 #include "PlatformBridge.h"
59 #endif
60 
61 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
62 #include "TouchEvent.h"
63 #endif
64 
65 using namespace std;
66 
67 namespace WebCore {
68 
69 using namespace HTMLNames;
70 
71 const int maxSavedResults = 256;
72 
HTMLInputElement(const QualifiedName & tagName,Document * document,HTMLFormElement * form,bool createdByParser)73 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
74     : HTMLTextFormControlElement(tagName, document, form)
75     , m_maxResults(-1)
76     , m_isChecked(false)
77     , m_reflectsCheckedAttribute(true)
78     , m_isIndeterminate(false)
79     , m_hasType(false)
80     , m_isActivatedSubmit(false)
81     , m_autocomplete(Uninitialized)
82     , m_isAutofilled(false)
83     , m_stateRestored(false)
84     , m_parsingInProgress(createdByParser)
85     , m_inputType(InputType::createText(this))
86 {
87     ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
88 }
89 
create(const QualifiedName & tagName,Document * document,HTMLFormElement * form,bool createdByParser)90 PassRefPtr<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
91 {
92     return adoptRef(new HTMLInputElement(tagName, document, form, createdByParser));
93 }
94 
~HTMLInputElement()95 HTMLInputElement::~HTMLInputElement()
96 {
97     if (needsActivationCallback())
98         document()->unregisterForDocumentActivationCallbacks(this);
99 
100     document()->checkedRadioButtons().removeButton(this);
101 
102     // Need to remove this from the form while it is still an HTMLInputElement,
103     // so can't wait for the base class's destructor to do it.
104     removeFromForm();
105 }
106 
formControlName() const107 const AtomicString& HTMLInputElement::formControlName() const
108 {
109     return m_data.name();
110 }
111 
autoComplete() const112 bool HTMLInputElement::autoComplete() const
113 {
114     if (m_autocomplete != Uninitialized)
115         return m_autocomplete == On;
116     return HTMLTextFormControlElement::autoComplete();
117 }
118 
updateCheckedRadioButtons()119 void HTMLInputElement::updateCheckedRadioButtons()
120 {
121     if (attached() && checked())
122         checkedRadioButtons().addButton(this);
123 
124     if (form()) {
125         const Vector<FormAssociatedElement*>& controls = form()->associatedElements();
126         for (unsigned i = 0; i < controls.size(); ++i) {
127             if (!controls[i]->isFormControlElement())
128                 continue;
129             HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(controls[i]);
130             if (control->name() != name())
131                 continue;
132             if (control->type() != type())
133                 continue;
134             control->setNeedsValidityCheck();
135         }
136     } else {
137         // FIXME: Traversing the document is inefficient.
138         for (Node* node = document()->body(); node; node = node->traverseNextNode()) {
139             if (!node->isElementNode())
140                 continue;
141             Element* element = static_cast<Element*>(node);
142             if (element->formControlName() != name())
143                 continue;
144             if (element->formControlType() != type())
145                 continue;
146             HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(element);
147             if (control->form())
148                 continue;
149             control->setNeedsValidityCheck();
150         }
151     }
152 
153     if (renderer() && renderer()->style()->hasAppearance())
154         renderer()->theme()->stateChanged(renderer(), CheckedState);
155 }
156 
lastChangeWasUserEdit() const157 bool HTMLInputElement::lastChangeWasUserEdit() const
158 {
159     if (!isTextField())
160         return false;
161 
162     if (!renderer())
163         return false;
164 
165     return toRenderTextControl(renderer())->lastChangeWasUserEdit();
166 }
167 
isValidValue(const String & value) const168 bool HTMLInputElement::isValidValue(const String& value) const
169 {
170     if (!m_inputType->canSetStringValue()) {
171         ASSERT_NOT_REACHED();
172         return false;
173     }
174     return !m_inputType->typeMismatchFor(value)
175         && !stepMismatch(value)
176         && !rangeUnderflow(value)
177         && !rangeOverflow(value)
178         && !tooLong(value, IgnoreDirtyFlag)
179         && !patternMismatch(value)
180         && !valueMissing(value);
181 }
182 
typeMismatch() const183 bool HTMLInputElement::typeMismatch() const
184 {
185     return m_inputType->typeMismatch();
186 }
187 
valueMissing(const String & value) const188 bool HTMLInputElement::valueMissing(const String& value) const
189 {
190     if (!isRequiredFormControl() || readOnly() || disabled())
191         return false;
192     return m_inputType->valueMissing(value);
193 }
194 
patternMismatch(const String & value) const195 bool HTMLInputElement::patternMismatch(const String& value) const
196 {
197     return m_inputType->patternMismatch(value);
198 }
199 
tooLong(const String & value,NeedsToCheckDirtyFlag check) const200 bool HTMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
201 {
202     // We use isTextType() instead of supportsMaxLength() because of the
203     // 'virtual' overhead.
204     if (!isTextType())
205         return false;
206     int max = maxLength();
207     if (max < 0)
208         return false;
209     if (check == CheckDirtyFlag) {
210         // Return false for the default value even if it is longer than maxLength.
211         bool userEdited = !m_data.value().isNull();
212         if (!userEdited)
213             return false;
214     }
215     return numGraphemeClusters(value) > static_cast<unsigned>(max);
216 }
217 
rangeUnderflow(const String & value) const218 bool HTMLInputElement::rangeUnderflow(const String& value) const
219 {
220     return m_inputType->rangeUnderflow(value);
221 }
222 
rangeOverflow(const String & value) const223 bool HTMLInputElement::rangeOverflow(const String& value) const
224 {
225     return m_inputType->rangeOverflow(value);
226 }
227 
minimum() const228 double HTMLInputElement::minimum() const
229 {
230     return m_inputType->minimum();
231 }
232 
maximum() const233 double HTMLInputElement::maximum() const
234 {
235     return m_inputType->maximum();
236 }
237 
stepMismatch(const String & value) const238 bool HTMLInputElement::stepMismatch(const String& value) const
239 {
240     double step;
241     if (!getAllowedValueStep(&step))
242         return false;
243     return m_inputType->stepMismatch(value, step);
244 }
245 
minimumString() const246 String HTMLInputElement::minimumString() const
247 {
248     return m_inputType->serialize(minimum());
249 }
250 
maximumString() const251 String HTMLInputElement::maximumString() const
252 {
253     return m_inputType->serialize(maximum());
254 }
255 
stepBaseString() const256 String HTMLInputElement::stepBaseString() const
257 {
258     return m_inputType->serialize(m_inputType->stepBase());
259 }
260 
stepString() const261 String HTMLInputElement::stepString() const
262 {
263     double step;
264     if (!getAllowedValueStep(&step)) {
265         // stepString() should be called only if stepMismatch() can be true.
266         ASSERT_NOT_REACHED();
267         return String();
268     }
269     return serializeForNumberType(step / m_inputType->stepScaleFactor());
270 }
271 
typeMismatchText() const272 String HTMLInputElement::typeMismatchText() const
273 {
274     return m_inputType->typeMismatchText();
275 }
276 
valueMissingText() const277 String HTMLInputElement::valueMissingText() const
278 {
279     return m_inputType->valueMissingText();
280 }
281 
getAllowedValueStep(double * step) const282 bool HTMLInputElement::getAllowedValueStep(double* step) const
283 {
284     return getAllowedValueStepWithDecimalPlaces(step, 0);
285 }
286 
getAllowedValueStepWithDecimalPlaces(double * step,unsigned * decimalPlaces) const287 bool HTMLInputElement::getAllowedValueStepWithDecimalPlaces(double* step, unsigned* decimalPlaces) const
288 {
289     ASSERT(step);
290     double defaultStep = m_inputType->defaultStep();
291     double stepScaleFactor = m_inputType->stepScaleFactor();
292     if (!isfinite(defaultStep) || !isfinite(stepScaleFactor))
293         return false;
294     const AtomicString& stepString = fastGetAttribute(stepAttr);
295     if (stepString.isEmpty()) {
296         *step = defaultStep * stepScaleFactor;
297         if (decimalPlaces)
298             *decimalPlaces = 0;
299         return true;
300     }
301     if (equalIgnoringCase(stepString, "any"))
302         return false;
303     double parsed;
304     if (!decimalPlaces) {
305         if (!parseToDoubleForNumberType(stepString, &parsed) || parsed <= 0.0) {
306             *step = defaultStep * stepScaleFactor;
307             return true;
308         }
309     } else {
310         if (!parseToDoubleForNumberTypeWithDecimalPlaces(stepString, &parsed, decimalPlaces) || parsed <= 0.0) {
311             *step = defaultStep * stepScaleFactor;
312             *decimalPlaces = 0;
313             return true;
314         }
315     }
316     // For date, month, week, the parsed value should be an integer for some types.
317     if (m_inputType->parsedStepValueShouldBeInteger())
318         parsed = max(round(parsed), 1.0);
319     double result = parsed * stepScaleFactor;
320     // For datetime, datetime-local, time, the result should be an integer.
321     if (m_inputType->scaledStepValueShouldBeInteger())
322         result = max(round(result), 1.0);
323     ASSERT(result > 0);
324     *step = result;
325     return true;
326 }
327 
applyStep(double count,ExceptionCode & ec)328 void HTMLInputElement::applyStep(double count, ExceptionCode& ec)
329 {
330     double step;
331     unsigned stepDecimalPlaces, currentDecimalPlaces;
332     if (!getAllowedValueStepWithDecimalPlaces(&step, &stepDecimalPlaces)) {
333         ec = INVALID_STATE_ERR;
334         return;
335     }
336     const double nan = numeric_limits<double>::quiet_NaN();
337     double current = m_inputType->parseToDoubleWithDecimalPlaces(value(), nan, &currentDecimalPlaces);
338     if (!isfinite(current)) {
339         ec = INVALID_STATE_ERR;
340         return;
341     }
342     double newValue = current + step * count;
343     if (isinf(newValue)) {
344         ec = INVALID_STATE_ERR;
345         return;
346     }
347     double acceptableError = m_inputType->acceptableError(step);
348     if (newValue - m_inputType->minimum() < -acceptableError) {
349         ec = INVALID_STATE_ERR;
350         return;
351     }
352     if (newValue < m_inputType->minimum())
353         newValue = m_inputType->minimum();
354     unsigned baseDecimalPlaces;
355     double base = m_inputType->stepBaseWithDecimalPlaces(&baseDecimalPlaces);
356     baseDecimalPlaces = min(baseDecimalPlaces, 16u);
357     if (newValue < pow(10.0, 21.0)) {
358       if (stepMismatch(value())) {
359             double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, currentDecimalPlaces)));
360             newValue = round(newValue * scale) / scale;
361         } else {
362             double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces)));
363             newValue = round((base + round((newValue - base) / step) * step) * scale) / scale;
364         }
365     }
366     if (newValue - m_inputType->maximum() > acceptableError) {
367         ec = INVALID_STATE_ERR;
368         return;
369     }
370     if (newValue > m_inputType->maximum())
371         newValue = m_inputType->maximum();
372     setValueAsNumber(newValue, ec);
373 
374     if (AXObjectCache::accessibilityEnabled())
375          document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
376 }
377 
stepUp(int n,ExceptionCode & ec)378 void HTMLInputElement::stepUp(int n, ExceptionCode& ec)
379 {
380     applyStep(n, ec);
381 }
382 
stepDown(int n,ExceptionCode & ec)383 void HTMLInputElement::stepDown(int n, ExceptionCode& ec)
384 {
385     applyStep(-n, ec);
386 }
387 
isKeyboardFocusable(KeyboardEvent * event) const388 bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
389 {
390     if (isTextField())
391         return HTMLFormControlElementWithState::isFocusable();
392     return HTMLFormControlElementWithState::isKeyboardFocusable(event) && m_inputType->isKeyboardFocusable();
393 }
394 
isMouseFocusable() const395 bool HTMLInputElement::isMouseFocusable() const
396 {
397     if (isTextField())
398         return HTMLFormControlElementWithState::isFocusable();
399     return HTMLFormControlElementWithState::isMouseFocusable();
400 }
401 
updateFocusAppearance(bool restorePreviousSelection)402 void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
403 {
404     if (isTextField())
405         InputElement::updateFocusAppearance(m_data, this, this, restorePreviousSelection);
406     else
407         HTMLFormControlElementWithState::updateFocusAppearance(restorePreviousSelection);
408 }
409 
aboutToUnload()410 void HTMLInputElement::aboutToUnload()
411 {
412     InputElement::aboutToUnload(this, this);
413 }
414 
shouldUseInputMethod() const415 bool HTMLInputElement::shouldUseInputMethod() const
416 {
417     return m_inputType->shouldUseInputMethod();
418 }
419 
handleFocusEvent()420 void HTMLInputElement::handleFocusEvent()
421 {
422     InputElement::dispatchFocusEvent(this, this);
423 }
424 
handleBlurEvent()425 void HTMLInputElement::handleBlurEvent()
426 {
427     m_inputType->handleBlurEvent();
428     InputElement::dispatchBlurEvent(this, this);
429 }
430 
setType(const String & type)431 void HTMLInputElement::setType(const String& type)
432 {
433     // FIXME: This should just call setAttribute. No reason to handle the empty string specially.
434     // We should write a test case to show that setting to the empty string does not remove the
435     // attribute in other browsers and then fix this. Note that setting to null *does* remove
436     // the attribute and setAttribute implements that.
437     if (type.isEmpty()) {
438         ExceptionCode ec;
439         removeAttribute(typeAttr, ec);
440     } else
441         setAttribute(typeAttr, type);
442 }
443 
updateType()444 void HTMLInputElement::updateType()
445 {
446     OwnPtr<InputType> newType = InputType::create(this, fastGetAttribute(typeAttr));
447     bool hadType = m_hasType;
448     m_hasType = true;
449     if (m_inputType->formControlType() == newType->formControlType())
450         return;
451 
452     if (hadType && !newType->canChangeFromAnotherType()) {
453         // Set the attribute back to the old value.
454         // Useful in case we were called from inside parseMappedAttribute.
455         setAttribute(typeAttr, type());
456         return;
457     }
458 
459     checkedRadioButtons().removeButton(this);
460 
461     bool wasAttached = attached();
462     if (wasAttached)
463         detach();
464 
465     bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
466     bool neededActivationCallback = needsActivationCallback();
467     bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
468 
469     m_inputType->destroyShadowSubtree();
470     m_inputType = newType.release();
471     m_inputType->createShadowSubtree();
472 
473     setNeedsWillValidateCheck();
474 
475     bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
476 
477     if (didStoreValue && !willStoreValue && !m_data.value().isNull()) {
478         setAttribute(valueAttr, m_data.value());
479         m_data.setValue(String());
480     }
481     if (!didStoreValue && willStoreValue)
482         m_data.setValue(sanitizeValue(fastGetAttribute(valueAttr)));
483     else
484         InputElement::updateValueIfNeeded(m_data, this);
485 
486     if (neededActivationCallback)
487         unregisterForActivationCallbackIfNeeded();
488     else
489         registerForActivationCallbackIfNeeded();
490 
491     if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
492         NamedNodeMap* map = attributeMap();
493         ASSERT(map);
494         if (Attribute* height = map->getAttributeItem(heightAttr))
495             attributeChanged(height, false);
496         if (Attribute* width = map->getAttributeItem(widthAttr))
497             attributeChanged(width, false);
498         if (Attribute* align = map->getAttributeItem(alignAttr))
499             attributeChanged(align, false);
500     }
501 
502     if (wasAttached) {
503         attach();
504         if (document()->focusedNode() == this)
505             updateFocusAppearance(true);
506     }
507 
508     setChangedSinceLastFormControlChangeEvent(false);
509 
510     checkedRadioButtons().addButton(this);
511 
512     setNeedsValidityCheck();
513     InputElement::notifyFormStateChanged(this);
514 }
515 
formControlType() const516 const AtomicString& HTMLInputElement::formControlType() const
517 {
518     return m_inputType->formControlType();
519 }
520 
saveFormControlState(String & result) const521 bool HTMLInputElement::saveFormControlState(String& result) const
522 {
523     return m_inputType->saveFormControlState(result);
524 }
525 
restoreFormControlState(const String & state)526 void HTMLInputElement::restoreFormControlState(const String& state)
527 {
528     m_inputType->restoreFormControlState(state);
529     m_stateRestored = true;
530 }
531 
canStartSelection() const532 bool HTMLInputElement::canStartSelection() const
533 {
534     if (!isTextField())
535         return false;
536     return HTMLFormControlElementWithState::canStartSelection();
537 }
538 
canHaveSelection() const539 bool HTMLInputElement::canHaveSelection() const
540 {
541     return isTextField();
542 }
543 
accessKeyAction(bool sendToAnyElement)544 void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
545 {
546     m_inputType->accessKeyAction(sendToAnyElement);
547 }
548 
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const549 bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
550 {
551     if (((attrName == heightAttr || attrName == widthAttr) && m_inputType->shouldRespectHeightAndWidthAttributes())
552         || attrName == vspaceAttr
553         || attrName == hspaceAttr) {
554         result = eUniversal;
555         return false;
556     }
557 
558     if (attrName == alignAttr && m_inputType->shouldRespectAlignAttribute()) {
559         // Share with <img> since the alignment behavior is the same.
560         result = eReplaced;
561         return false;
562     }
563 
564     return HTMLElement::mapToEntry(attrName, result);
565 }
566 
parseMappedAttribute(Attribute * attr)567 void HTMLInputElement::parseMappedAttribute(Attribute* attr)
568 {
569     if (attr->name() == nameAttr) {
570         checkedRadioButtons().removeButton(this);
571         m_data.setName(attr->value());
572         checkedRadioButtons().addButton(this);
573         HTMLFormControlElementWithState::parseMappedAttribute(attr);
574     } else if (attr->name() == autocompleteAttr) {
575         if (equalIgnoringCase(attr->value(), "off")) {
576             m_autocomplete = Off;
577             registerForActivationCallbackIfNeeded();
578         } else {
579             bool needsToUnregister = m_autocomplete == Off;
580 
581             if (attr->isEmpty())
582                 m_autocomplete = Uninitialized;
583             else
584                 m_autocomplete = On;
585 
586             if (needsToUnregister)
587                 unregisterForActivationCallbackIfNeeded();
588         }
589     } else if (attr->name() == typeAttr) {
590         updateType();
591     } else if (attr->name() == valueAttr) {
592         // We only need to setChanged if the form is looking at the default value right now.
593         if (m_data.value().isNull())
594             setNeedsStyleRecalc();
595         setFormControlValueMatchesRenderer(false);
596         setNeedsValidityCheck();
597     } else if (attr->name() == checkedAttr) {
598         // Another radio button in the same group might be checked by state
599         // restore. We shouldn't call setChecked() even if this has the checked
600         // attribute. So, delay the setChecked() call until
601         // finishParsingChildren() is called if parsing is in progress.
602         if (!m_parsingInProgress && m_reflectsCheckedAttribute) {
603             setChecked(!attr->isNull());
604             m_reflectsCheckedAttribute = true;
605         }
606     } else if (attr->name() == maxlengthAttr) {
607         InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
608         setNeedsValidityCheck();
609     } else if (attr->name() == sizeAttr)
610         InputElement::parseSizeAttribute(m_data, this, attr);
611     else if (attr->name() == altAttr)
612         m_inputType->altAttributeChanged();
613     else if (attr->name() == srcAttr)
614         m_inputType->srcAttributeChanged();
615     else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) {
616         // FIXME: ignore for the moment
617     } else if (attr->name() == vspaceAttr) {
618         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
619         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
620     } else if (attr->name() == hspaceAttr) {
621         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
622         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
623     } else if (attr->name() == alignAttr) {
624         if (m_inputType->shouldRespectAlignAttribute())
625             addHTMLAlignment(attr);
626     } else if (attr->name() == widthAttr) {
627         if (m_inputType->shouldRespectHeightAndWidthAttributes())
628             addCSSLength(attr, CSSPropertyWidth, attr->value());
629     } else if (attr->name() == heightAttr) {
630         if (m_inputType->shouldRespectHeightAndWidthAttributes())
631             addCSSLength(attr, CSSPropertyHeight, attr->value());
632     } else if (attr->name() == onsearchAttr) {
633         // Search field and slider attributes all just cause updateFromElement to be called through style recalcing.
634         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
635     } else if (attr->name() == resultsAttr) {
636         int oldResults = m_maxResults;
637         m_maxResults = !attr->isNull() ? std::min(attr->value().toInt(), maxSavedResults) : -1;
638         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
639         // time to relayout for this change.
640         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
641             detach();
642             attach();
643         }
644         setNeedsStyleRecalc();
645     } else if (attr->name() == autosaveAttr || attr->name() == incrementalAttr)
646         setNeedsStyleRecalc();
647     else if (attr->name() == minAttr || attr->name() == maxAttr) {
648         m_inputType->minOrMaxAttributeChanged();
649         setNeedsValidityCheck();
650     } else if (attr->name() == multipleAttr || attr->name() == patternAttr || attr->name() == precisionAttr || attr->name() == stepAttr)
651         setNeedsValidityCheck();
652 #if ENABLE(DATALIST)
653     else if (attr->name() == listAttr)
654         m_hasNonEmptyList = !attr->isEmpty();
655         // FIXME: we need to tell this change to a renderer if the attribute affects the appearance.
656 #endif
657 #if ENABLE(INPUT_SPEECH)
658     else if (attr->name() == webkitspeechAttr) {
659         if (renderer()) {
660             // This renderer and its children have quite different layouts and styles depending on
661             // whether the speech button is visible or not. So we reset the whole thing and recreate
662             // to get the right styles and layout.
663             detach();
664             attach();
665         }
666         setNeedsStyleRecalc();
667     } else if (attr->name() == onwebkitspeechchangeAttr)
668         setAttributeEventListener(eventNames().webkitspeechchangeEvent, createAttributeEventListener(this, attr));
669 #endif
670     else
671         HTMLTextFormControlElement::parseMappedAttribute(attr);
672 }
673 
finishParsingChildren()674 void HTMLInputElement::finishParsingChildren()
675 {
676     m_parsingInProgress = false;
677     HTMLFormControlElementWithState::finishParsingChildren();
678     if (!m_stateRestored) {
679         bool checked = hasAttribute(checkedAttr);
680         if (checked)
681             setChecked(checked);
682         m_reflectsCheckedAttribute = true;
683     }
684 }
685 
rendererIsNeeded(RenderStyle * style)686 bool HTMLInputElement::rendererIsNeeded(RenderStyle* style)
687 {
688     return m_inputType->rendererIsNeeded() && HTMLFormControlElementWithState::rendererIsNeeded(style);
689 }
690 
createRenderer(RenderArena * arena,RenderStyle * style)691 RenderObject* HTMLInputElement::createRenderer(RenderArena* arena, RenderStyle* style)
692 {
693     return m_inputType->createRenderer(arena, style);
694 }
695 
attach()696 void HTMLInputElement::attach()
697 {
698     suspendPostAttachCallbacks();
699 
700     if (!m_hasType)
701         updateType();
702 
703     HTMLFormControlElementWithState::attach();
704 
705     m_inputType->attach();
706 
707     if (document()->focusedNode() == this)
708         document()->updateFocusAppearanceSoon(true /* restore selection */);
709 
710     resumePostAttachCallbacks();
711 }
712 
detach()713 void HTMLInputElement::detach()
714 {
715     HTMLFormControlElementWithState::detach();
716     setFormControlValueMatchesRenderer(false);
717 }
718 
altText() const719 String HTMLInputElement::altText() const
720 {
721     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
722     // also heavily discussed by Hixie on bugzilla
723     // note this is intentionally different to HTMLImageElement::altText()
724     String alt = fastGetAttribute(altAttr);
725     // fall back to title attribute
726     if (alt.isNull())
727         alt = getAttribute(titleAttr);
728     if (alt.isNull())
729         alt = getAttribute(valueAttr);
730     if (alt.isEmpty())
731         alt = inputElementAltText();
732     return alt;
733 }
734 
isSuccessfulSubmitButton() const735 bool HTMLInputElement::isSuccessfulSubmitButton() const
736 {
737     // HTML spec says that buttons must have names to be considered successful.
738     // However, other browsers do not impose this constraint. So we do not.
739     return !disabled() && m_inputType->canBeSuccessfulSubmitButton();
740 }
741 
isActivatedSubmit() const742 bool HTMLInputElement::isActivatedSubmit() const
743 {
744     return m_isActivatedSubmit;
745 }
746 
setActivatedSubmit(bool flag)747 void HTMLInputElement::setActivatedSubmit(bool flag)
748 {
749     m_isActivatedSubmit = flag;
750 }
751 
appendFormData(FormDataList & encoding,bool multipart)752 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
753 {
754     return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(encoding, multipart);
755 }
756 
reset()757 void HTMLInputElement::reset()
758 {
759     if (m_inputType->storesValueSeparateFromAttribute())
760         setValue(String());
761 
762     setAutofilled(false);
763     setChecked(hasAttribute(checkedAttr));
764     m_reflectsCheckedAttribute = true;
765 }
766 
isTextField() const767 bool HTMLInputElement::isTextField() const
768 {
769     return m_inputType->isTextField();
770 }
771 
isTextType() const772 bool HTMLInputElement::isTextType() const
773 {
774     return m_inputType->isTextType();
775 }
776 
setChecked(bool nowChecked,bool sendChangeEvent)777 void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
778 {
779     if (checked() == nowChecked)
780         return;
781 
782     checkedRadioButtons().removeButton(this);
783 
784     m_reflectsCheckedAttribute = false;
785     m_isChecked = nowChecked;
786     setNeedsStyleRecalc();
787 
788     updateCheckedRadioButtons();
789     setNeedsValidityCheck();
790 
791     // Ideally we'd do this from the render tree (matching
792     // RenderTextView), but it's not possible to do it at the moment
793     // because of the way the code is structured.
794     if (renderer() && AXObjectCache::accessibilityEnabled())
795         renderer()->document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXCheckedStateChanged, true);
796 
797     // Only send a change event for items in the document (avoid firing during
798     // parsing) and don't send a change event for a radio button that's getting
799     // unchecked to match other browsers. DOM is not a useful standard for this
800     // because it says only to fire change events at "lose focus" time, which is
801     // definitely wrong in practice for these types of elements.
802     if (sendChangeEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) {
803         setTextAsOfLastFormControlChangeEvent(String());
804         dispatchFormControlChangeEvent();
805     }
806 }
807 
setIndeterminate(bool newValue)808 void HTMLInputElement::setIndeterminate(bool newValue)
809 {
810     if (!m_inputType->isCheckable() || indeterminate() == newValue)
811         return;
812 
813     m_isIndeterminate = newValue;
814 
815     setNeedsStyleRecalc();
816 
817     if (renderer() && renderer()->style()->hasAppearance())
818         renderer()->theme()->stateChanged(renderer(), CheckedState);
819 }
820 
size() const821 int HTMLInputElement::size() const
822 {
823     return m_data.size();
824 }
825 
copyNonAttributeProperties(const Element * source)826 void HTMLInputElement::copyNonAttributeProperties(const Element* source)
827 {
828     const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
829 
830     m_data.setValue(sourceElement->m_data.value());
831     setChecked(sourceElement->m_isChecked);
832     m_reflectsCheckedAttribute = sourceElement->m_reflectsCheckedAttribute;
833     m_isIndeterminate = sourceElement->m_isIndeterminate;
834 
835     HTMLFormControlElementWithState::copyNonAttributeProperties(source);
836 }
837 
value() const838 String HTMLInputElement::value() const
839 {
840     String value;
841     if (m_inputType->getTypeSpecificValue(value))
842         return value;
843 
844     value = m_data.value();
845     if (!value.isNull())
846         return value;
847 
848     value = sanitizeValue(fastGetAttribute(valueAttr));
849     if (!value.isNull())
850         return value;
851 
852     return m_inputType->fallbackValue();
853 }
854 
valueWithDefault() const855 String HTMLInputElement::valueWithDefault() const
856 {
857     String value = this->value();
858     if (!value.isNull())
859         return value;
860 
861     return m_inputType->defaultValue();
862 }
863 
setValueForUser(const String & value)864 void HTMLInputElement::setValueForUser(const String& value)
865 {
866     // Call setValue and make it send a change event.
867     setValue(value, true);
868 }
869 
suggestedValue() const870 const String& HTMLInputElement::suggestedValue() const
871 {
872     return m_data.suggestedValue();
873 }
874 
setSuggestedValue(const String & value)875 void HTMLInputElement::setSuggestedValue(const String& value)
876 {
877     if (!m_inputType->canSetSuggestedValue())
878         return;
879     setFormControlValueMatchesRenderer(false);
880     m_data.setSuggestedValue(sanitizeValue(value));
881     updatePlaceholderVisibility(false);
882     if (renderer())
883         renderer()->updateFromElement();
884     setNeedsStyleRecalc();
885 }
886 
setValue(const String & value,bool sendChangeEvent)887 void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
888 {
889     if (!m_inputType->canSetValue(value))
890         return;
891 
892     setFormControlValueMatchesRenderer(false);
893     if (m_inputType->storesValueSeparateFromAttribute()) {
894         if (files())
895             files()->clear();
896         else {
897             m_data.setValue(sanitizeValue(value));
898             if (isTextField())
899                 updatePlaceholderVisibility(false);
900         }
901         setNeedsStyleRecalc();
902     } else
903         setAttribute(valueAttr, sanitizeValue(value));
904 
905     setNeedsValidityCheck();
906 
907     if (isTextField()) {
908         unsigned max = m_data.value().length();
909 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
910         // Make sure our UI side textfield changes to match the RenderTextControl
911         PlatformBridge::updateTextfield(document()->view(), this, value);
912 #endif
913         if (document()->focusedNode() == this)
914             InputElement::updateSelectionRange(this, this, max, max);
915         else
916             cacheSelection(max, max);
917         m_data.setSuggestedValue(String());
918     }
919     m_inputType->valueChanged();
920 
921     if (sendChangeEvent) {
922         // If the user is still editing this field, dispatch an input event rather than a change event.
923         // The change event will be dispatched when editing finishes.
924         if (isTextField() && focused())
925             dispatchFormControlInputEvent();
926         else
927             dispatchFormControlChangeEvent();
928     }
929 
930     if (isText() && (!focused() || !sendChangeEvent))
931         setTextAsOfLastFormControlChangeEvent(value);
932 
933     InputElement::notifyFormStateChanged(this);
934 }
935 
valueAsDate() const936 double HTMLInputElement::valueAsDate() const
937 {
938     return m_inputType->valueAsDate();
939 }
940 
setValueAsDate(double value,ExceptionCode & ec)941 void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec)
942 {
943     m_inputType->setValueAsDate(value, ec);
944 }
945 
valueAsNumber() const946 double HTMLInputElement::valueAsNumber() const
947 {
948     return m_inputType->valueAsNumber();
949 }
950 
setValueAsNumber(double newValue,ExceptionCode & ec)951 void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
952 {
953     if (!isfinite(newValue)) {
954         ec = NOT_SUPPORTED_ERR;
955         return;
956     }
957     m_inputType->setValueAsNumber(newValue, ec);
958 }
959 
placeholder() const960 String HTMLInputElement::placeholder() const
961 {
962     return fastGetAttribute(placeholderAttr).string();
963 }
964 
setPlaceholder(const String & value)965 void HTMLInputElement::setPlaceholder(const String& value)
966 {
967     setAttribute(placeholderAttr, value);
968 }
969 
searchEventsShouldBeDispatched() const970 bool HTMLInputElement::searchEventsShouldBeDispatched() const
971 {
972     return hasAttribute(incrementalAttr);
973 }
974 
setValueFromRenderer(const String & value)975 void HTMLInputElement::setValueFromRenderer(const String& value)
976 {
977     // File upload controls will always use setFileListFromRenderer.
978     ASSERT(!isFileUpload());
979 
980     m_data.setSuggestedValue(String());
981     InputElement::setValueFromRenderer(m_data, this, this, value);
982     updatePlaceholderVisibility(false);
983     setNeedsValidityCheck();
984 
985     // Clear autofill flag (and yellow background) on user edit.
986     setAutofilled(false);
987 }
988 
setFileListFromRenderer(const Vector<String> & paths)989 void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
990 {
991     m_inputType->setFileList(paths);
992 
993     setFormControlValueMatchesRenderer(true);
994     InputElement::notifyFormStateChanged(this);
995     setNeedsValidityCheck();
996 }
997 
preDispatchEventHandler(Event * event)998 void* HTMLInputElement::preDispatchEventHandler(Event* event)
999 {
1000     if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
1001         event->stopPropagation();
1002         return 0;
1003     }
1004     if (event->type() != eventNames().clickEvent)
1005         return 0;
1006     if (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button() != LeftButton)
1007         return 0;
1008     // FIXME: Check whether there are any cases where this actually ends up leaking.
1009     return m_inputType->willDispatchClick().leakPtr();
1010 }
1011 
postDispatchEventHandler(Event * event,void * dataFromPreDispatch)1012 void HTMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
1013 {
1014     OwnPtr<ClickHandlingState> state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch));
1015     if (!state)
1016         return;
1017     m_inputType->didDispatchClick(event, *state);
1018 }
1019 
defaultEventHandler(Event * evt)1020 void HTMLInputElement::defaultEventHandler(Event* evt)
1021 {
1022     if (evt->isMouseEvent() && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1023         m_inputType->handleClickEvent(static_cast<MouseEvent*>(evt));
1024         if (evt->defaultHandled())
1025             return;
1026     }
1027 
1028     if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
1029         m_inputType->handleKeydownEvent(static_cast<KeyboardEvent*>(evt));
1030         if (evt->defaultHandled())
1031             return;
1032     }
1033 
1034     // Call the base event handler before any of our own event handling for almost all events in text fields.
1035     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
1036     bool callBaseClassEarly = isTextField() && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1037     if (callBaseClassEarly) {
1038         HTMLFormControlElementWithState::defaultEventHandler(evt);
1039         if (evt->defaultHandled())
1040             return;
1041     }
1042 
1043     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
1044     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
1045     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
1046     // must dispatch a DOMActivate event - a click event will not do the job.
1047     if (evt->type() == eventNames().DOMActivateEvent) {
1048         m_inputType->handleDOMActivateEvent(evt);
1049         if (evt->defaultHandled())
1050             return;
1051     }
1052 
1053     // Use key press event here since sending simulated mouse events
1054     // on key down blocks the proper sending of the key press event.
1055     if (evt->isKeyboardEvent() && evt->type() == eventNames().keypressEvent) {
1056         m_inputType->handleKeypressEvent(static_cast<KeyboardEvent*>(evt));
1057         if (evt->defaultHandled())
1058             return;
1059     }
1060 
1061     if (evt->isKeyboardEvent() && evt->type() == eventNames().keyupEvent) {
1062         m_inputType->handleKeyupEvent(static_cast<KeyboardEvent*>(evt));
1063         if (evt->defaultHandled())
1064             return;
1065     }
1066 
1067     if (m_inputType->shouldSubmitImplicitly(evt)) {
1068         if (isSearchField()) {
1069             addSearchResult();
1070             onSearch();
1071         }
1072         // Form submission finishes editing, just as loss of focus does.
1073         // If there was a change, send the event now.
1074         if (wasChangedSinceLastFormControlChangeEvent())
1075             dispatchFormControlChangeEvent();
1076 
1077         RefPtr<HTMLFormElement> formForSubmission = m_inputType->formForSubmission();
1078         // Form may never have been present, or may have been destroyed by code responding to the change event.
1079         if (formForSubmission)
1080             formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
1081 
1082         evt->setDefaultHandled();
1083         return;
1084     }
1085 
1086     if (evt->isBeforeTextInsertedEvent())
1087         m_inputType->handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(evt));
1088 
1089     if (evt->isWheelEvent()) {
1090         m_inputType->handleWheelEvent(static_cast<WheelEvent*>(evt));
1091         if (evt->defaultHandled())
1092             return;
1093     }
1094 
1095     if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
1096         m_inputType->handleMouseDownEvent(static_cast<MouseEvent*>(evt));
1097         if (evt->defaultHandled())
1098             return;
1099     }
1100 
1101 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
1102     if (evt->isTouchEvent() && evt->type() == eventNames().touchstartEvent) {
1103         m_inputType->handleTouchStartEvent(static_cast<TouchEvent*>(evt));
1104         if (evt->defaultHandled())
1105             return;
1106     }
1107 #endif
1108 
1109     m_inputType->forwardEvent(evt);
1110 
1111     if (!callBaseClassEarly && !evt->defaultHandled())
1112         HTMLFormControlElementWithState::defaultEventHandler(evt);
1113 }
1114 
isURLAttribute(Attribute * attr) const1115 bool HTMLInputElement::isURLAttribute(Attribute *attr) const
1116 {
1117     return (attr->name() == srcAttr || attr->name() == formactionAttr);
1118 }
1119 
defaultValue() const1120 String HTMLInputElement::defaultValue() const
1121 {
1122     return fastGetAttribute(valueAttr);
1123 }
1124 
setDefaultValue(const String & value)1125 void HTMLInputElement::setDefaultValue(const String &value)
1126 {
1127     setAttribute(valueAttr, value);
1128 }
1129 
setDefaultName(const AtomicString & name)1130 void HTMLInputElement::setDefaultName(const AtomicString& name)
1131 {
1132     m_data.setName(name);
1133 }
1134 
accept() const1135 String HTMLInputElement::accept() const
1136 {
1137     return fastGetAttribute(acceptAttr);
1138 }
1139 
alt() const1140 String HTMLInputElement::alt() const
1141 {
1142     return fastGetAttribute(altAttr);
1143 }
1144 
maxLength() const1145 int HTMLInputElement::maxLength() const
1146 {
1147     return m_data.maxLength();
1148 }
1149 
setMaxLength(int maxLength,ExceptionCode & ec)1150 void HTMLInputElement::setMaxLength(int maxLength, ExceptionCode& ec)
1151 {
1152     if (maxLength < 0)
1153         ec = INDEX_SIZE_ERR;
1154     else
1155         setAttribute(maxlengthAttr, String::number(maxLength));
1156 }
1157 
multiple() const1158 bool HTMLInputElement::multiple() const
1159 {
1160     return fastHasAttribute(multipleAttr);
1161 }
1162 
setSize(unsigned size)1163 void HTMLInputElement::setSize(unsigned size)
1164 {
1165     setAttribute(sizeAttr, String::number(size));
1166 }
1167 
src() const1168 KURL HTMLInputElement::src() const
1169 {
1170     return document()->completeURL(fastGetAttribute(srcAttr));
1171 }
1172 
setAutofilled(bool autofilled)1173 void HTMLInputElement::setAutofilled(bool autofilled)
1174 {
1175     if (autofilled == m_isAutofilled)
1176         return;
1177 
1178     m_isAutofilled = autofilled;
1179     setNeedsStyleRecalc();
1180 }
1181 
files()1182 FileList* HTMLInputElement::files()
1183 {
1184     return m_inputType->files();
1185 }
1186 
visibleValue() const1187 String HTMLInputElement::visibleValue() const
1188 {
1189     return m_inputType->visibleValue();
1190 }
1191 
convertFromVisibleValue(const String & visibleValue) const1192 String HTMLInputElement::convertFromVisibleValue(const String& visibleValue) const
1193 {
1194     return m_inputType->convertFromVisibleValue(visibleValue);
1195 }
1196 
isAcceptableValue(const String & proposedValue) const1197 bool HTMLInputElement::isAcceptableValue(const String& proposedValue) const
1198 {
1199     return m_inputType->isAcceptableValue(proposedValue);
1200 }
1201 
sanitizeValue(const String & proposedValue) const1202 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
1203 {
1204     return m_inputType->sanitizeValue(proposedValue);
1205 }
1206 
hasUnacceptableValue() const1207 bool HTMLInputElement::hasUnacceptableValue() const
1208 {
1209     return m_inputType->hasUnacceptableValue();
1210 }
1211 
isInRange() const1212 bool HTMLInputElement::isInRange() const
1213 {
1214     return m_inputType->supportsRangeLimitation() && !rangeUnderflow(value()) && !rangeOverflow(value());
1215 }
1216 
isOutOfRange() const1217 bool HTMLInputElement::isOutOfRange() const
1218 {
1219     return m_inputType->supportsRangeLimitation() && (rangeUnderflow(value()) || rangeOverflow(value()));
1220 }
1221 
needsActivationCallback()1222 bool HTMLInputElement::needsActivationCallback()
1223 {
1224     return m_autocomplete == Off || m_inputType->shouldResetOnDocumentActivation();
1225 }
1226 
registerForActivationCallbackIfNeeded()1227 void HTMLInputElement::registerForActivationCallbackIfNeeded()
1228 {
1229     if (needsActivationCallback())
1230         document()->registerForDocumentActivationCallbacks(this);
1231 }
1232 
unregisterForActivationCallbackIfNeeded()1233 void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
1234 {
1235     if (!needsActivationCallback())
1236         document()->unregisterForDocumentActivationCallbacks(this);
1237 }
1238 
isRequiredFormControl() const1239 bool HTMLInputElement::isRequiredFormControl() const
1240 {
1241     return m_inputType->supportsRequired() && required();
1242 }
1243 
cacheSelection(int start,int end)1244 void HTMLInputElement::cacheSelection(int start, int end)
1245 {
1246     m_data.setCachedSelectionStart(start);
1247     m_data.setCachedSelectionEnd(end);
1248 }
1249 
addSearchResult()1250 void HTMLInputElement::addSearchResult()
1251 {
1252     ASSERT(isSearchField());
1253     if (renderer())
1254         toRenderTextControlSingleLine(renderer())->addSearchResult();
1255 }
1256 
onSearch()1257 void HTMLInputElement::onSearch()
1258 {
1259     ASSERT(isSearchField());
1260     if (renderer())
1261         toRenderTextControlSingleLine(renderer())->stopSearchEventTimer();
1262     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
1263 }
1264 
documentDidBecomeActive()1265 void HTMLInputElement::documentDidBecomeActive()
1266 {
1267     ASSERT(needsActivationCallback());
1268     reset();
1269 }
1270 
willMoveToNewOwnerDocument()1271 void HTMLInputElement::willMoveToNewOwnerDocument()
1272 {
1273     m_inputType->willMoveToNewOwnerDocument();
1274 
1275     // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
1276     if (needsActivationCallback())
1277         document()->unregisterForDocumentActivationCallbacks(this);
1278 
1279     document()->checkedRadioButtons().removeButton(this);
1280 
1281     HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
1282 }
1283 
didMoveToNewOwnerDocument()1284 void HTMLInputElement::didMoveToNewOwnerDocument()
1285 {
1286     registerForActivationCallbackIfNeeded();
1287 
1288     HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
1289 }
1290 
addSubresourceAttributeURLs(ListHashSet<KURL> & urls) const1291 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
1292 {
1293     HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls);
1294 
1295     addSubresourceURL(urls, src());
1296 }
1297 
recalcWillValidate() const1298 bool HTMLInputElement::recalcWillValidate() const
1299 {
1300     return m_inputType->supportsValidation() && HTMLFormControlElementWithState::recalcWillValidate();
1301 }
1302 
1303 #if ENABLE(DATALIST)
1304 
list() const1305 HTMLElement* HTMLInputElement::list() const
1306 {
1307     return dataList();
1308 }
1309 
dataList() const1310 HTMLDataListElement* HTMLInputElement::dataList() const
1311 {
1312     if (!m_hasNonEmptyList)
1313         return 0;
1314 
1315     if (!m_inputType->shouldRespectListAttribute())
1316         return 0;
1317 
1318     Element* element = document()->getElementById(fastGetAttribute(listAttr));
1319     if (!element)
1320         return 0;
1321     if (!element->hasTagName(datalistTag))
1322         return 0;
1323 
1324     return static_cast<HTMLDataListElement*>(element);
1325 }
1326 
selectedOption() const1327 HTMLOptionElement* HTMLInputElement::selectedOption() const
1328 {
1329     String value = this->value();
1330 
1331     // The empty string never matches to a datalist option because it
1332     // doesn't represent a suggestion according to the standard.
1333     if (value.isEmpty())
1334         return 0;
1335 
1336     HTMLDataListElement* sourceElement = dataList();
1337     if (!sourceElement)
1338         return 0;
1339     RefPtr<HTMLCollection> options = sourceElement->options();
1340     if (!options)
1341         return 0;
1342     unsigned length = options->length();
1343     for (unsigned i = 0; i < length; ++i) {
1344         HTMLOptionElement* option = static_cast<HTMLOptionElement*>(options->item(i));
1345         if (!option->disabled() && value == option->value())
1346             return option;
1347     }
1348     return 0;
1349 }
1350 
1351 #endif // ENABLE(DATALIST)
1352 
stepUpFromRenderer(int n)1353 void HTMLInputElement::stepUpFromRenderer(int n)
1354 {
1355     // The differences from stepUp()/stepDown():
1356     //
1357     // Difference 1: the current value
1358     // If the current value is not a number, including empty, the current value is assumed as 0.
1359     //   * If 0 is in-range, and matches to step value
1360     //     - The value should be the +step if n > 0
1361     //     - The value should be the -step if n < 0
1362     //     If -step or +step is out of range, new value should be 0.
1363     //   * If 0 is smaller than the minimum value
1364     //     - The value should be the minimum value for any n
1365     //   * If 0 is larger than the maximum value
1366     //     - The value should be the maximum value for any n
1367     //   * If 0 is in-range, but not matched to step value
1368     //     - The value should be the larger matched value nearest to 0 if n > 0
1369     //       e.g. <input type=number min=-100 step=3> -> 2
1370     //     - The value should be the smaler matched value nearest to 0 if n < 0
1371     //       e.g. <input type=number min=-100 step=3> -> -1
1372     //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
1373     //   As for datetime type, the current value is assumed as "the current date/time in UTC".
1374     // If the current value is smaller than the minimum value:
1375     //  - The value should be the minimum value if n > 0
1376     //  - Nothing should happen if n < 0
1377     // If the current value is larger than the maximum value:
1378     //  - The value should be the maximum value if n < 0
1379     //  - Nothing should happen if n > 0
1380     //
1381     // Difference 2: clamping steps
1382     // If the current value is not matched to step value:
1383     // - The value should be the larger matched value nearest to 0 if n > 0
1384     //   e.g. <input type=number value=3 min=-100 step=3> -> 5
1385     // - The value should be the smaler matched value nearest to 0 if n < 0
1386     //   e.g. <input type=number value=3 min=-100 step=3> -> 2
1387     //
1388     // n is assumed as -n if step < 0.
1389 
1390     ASSERT(hasSpinButton() || m_inputType->isRangeControl());
1391     if (!hasSpinButton() && !m_inputType->isRangeControl())
1392         return;
1393     ASSERT(n);
1394     if (!n)
1395         return;
1396 
1397     unsigned stepDecimalPlaces, baseDecimalPlaces;
1398     double step, base;
1399     // The value will be the default value after stepping for <input value=(empty/invalid) step="any" />
1400     // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
1401     // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
1402     if (equalIgnoringCase(fastGetAttribute(stepAttr), "any"))
1403         step = 0;
1404     else if (!getAllowedValueStepWithDecimalPlaces(&step, &stepDecimalPlaces))
1405         return;
1406     base = m_inputType->stepBaseWithDecimalPlaces(&baseDecimalPlaces);
1407     baseDecimalPlaces = min(baseDecimalPlaces, 16u);
1408 
1409     int sign;
1410     if (step > 0)
1411         sign = n;
1412     else if (step < 0)
1413         sign = -n;
1414     else
1415         sign = 0;
1416 
1417     const double nan = numeric_limits<double>::quiet_NaN();
1418     String currentStringValue = value();
1419     double current = m_inputType->parseToDouble(currentStringValue, nan);
1420     if (!isfinite(current)) {
1421         ExceptionCode ec;
1422         current = m_inputType->defaultValueForStepUp();
1423         setValueAsNumber(current, ec);
1424     }
1425     if ((sign > 0 && current < m_inputType->minimum()) || (sign < 0 && current > m_inputType->maximum()))
1426         setValue(m_inputType->serialize(sign > 0 ? m_inputType->minimum() : m_inputType->maximum()));
1427     else {
1428         ExceptionCode ec;
1429         if (stepMismatch(currentStringValue)) {
1430             ASSERT(step);
1431             double newValue;
1432             double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces)));
1433 
1434             if (sign < 0)
1435                 newValue = round((base + floor((current - base) / step) * step) * scale) / scale;
1436             else if (sign > 0)
1437                 newValue = round((base + ceil((current - base) / step) * step) * scale) / scale;
1438             else
1439                 newValue = current;
1440 
1441             if (newValue < m_inputType->minimum())
1442                 newValue = m_inputType->minimum();
1443             if (newValue > m_inputType->maximum())
1444                 newValue = m_inputType->maximum();
1445 
1446             setValueAsNumber(newValue, ec);
1447             current = newValue;
1448             if (n > 1)
1449                 applyStep(n - 1, ec);
1450             else if (n < -1)
1451                 applyStep(n + 1, ec);
1452         } else
1453             applyStep(n, ec);
1454     }
1455 
1456     if (currentStringValue != value()) {
1457         if (m_inputType->isRangeControl())
1458             dispatchFormControlChangeEvent();
1459         else
1460             dispatchFormControlInputEvent();
1461     }
1462 }
1463 
1464 #if ENABLE(WCSS)
1465 
setWapInputFormat(String & mask)1466 void HTMLInputElement::setWapInputFormat(String& mask)
1467 {
1468     String validateMask = validateInputMask(m_data, mask);
1469     if (!validateMask.isEmpty())
1470         m_data.setInputFormatMask(validateMask);
1471 }
1472 
1473 #endif
1474 
1475 #if ENABLE(INPUT_SPEECH)
1476 
isSpeechEnabled() const1477 bool HTMLInputElement::isSpeechEnabled() const
1478 {
1479     // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types.
1480     return m_inputType->shouldRespectSpeechAttribute() && RuntimeEnabledFeatures::speechInputEnabled() && hasAttribute(webkitspeechAttr);
1481 }
1482 
1483 #endif
1484 
isTextButton() const1485 bool HTMLInputElement::isTextButton() const
1486 {
1487     return m_inputType->isTextButton();
1488 }
1489 
isRadioButton() const1490 bool HTMLInputElement::isRadioButton() const
1491 {
1492     return m_inputType->isRadioButton();
1493 }
1494 
isSearchField() const1495 bool HTMLInputElement::isSearchField() const
1496 {
1497     return m_inputType->isSearchField();
1498 }
1499 
isInputTypeHidden() const1500 bool HTMLInputElement::isInputTypeHidden() const
1501 {
1502     return m_inputType->isHiddenType();
1503 }
1504 
isPasswordField() const1505 bool HTMLInputElement::isPasswordField() const
1506 {
1507     return m_inputType->isPasswordField();
1508 }
1509 
isCheckbox() const1510 bool HTMLInputElement::isCheckbox() const
1511 {
1512     return m_inputType->isCheckbox();
1513 }
1514 
isText() const1515 bool HTMLInputElement::isText() const
1516 {
1517     return m_inputType->isTextType();
1518 }
1519 
isEmailField() const1520 bool HTMLInputElement::isEmailField() const
1521 {
1522     return m_inputType->isEmailField();
1523 }
1524 
isFileUpload() const1525 bool HTMLInputElement::isFileUpload() const
1526 {
1527     return m_inputType->isFileUpload();
1528 }
1529 
isImageButton() const1530 bool HTMLInputElement::isImageButton() const
1531 {
1532     return m_inputType->isImageButton();
1533 }
1534 
isNumberField() const1535 bool HTMLInputElement::isNumberField() const
1536 {
1537     return m_inputType->isNumberField();
1538 }
1539 
isSubmitButton() const1540 bool HTMLInputElement::isSubmitButton() const
1541 {
1542     return m_inputType->isSubmitButton();
1543 }
1544 
isTelephoneField() const1545 bool HTMLInputElement::isTelephoneField() const
1546 {
1547     return m_inputType->isTelephoneField();
1548 }
1549 
isURLField() const1550 bool HTMLInputElement::isURLField() const
1551 {
1552     return m_inputType->isURLField();
1553 }
1554 
isEnumeratable() const1555 bool HTMLInputElement::isEnumeratable() const
1556 {
1557     return m_inputType->isEnumeratable();
1558 }
1559 
isChecked() const1560 bool HTMLInputElement::isChecked() const
1561 {
1562     return checked() && m_inputType->isCheckable();
1563 }
1564 
hasSpinButton() const1565 bool HTMLInputElement::hasSpinButton() const
1566 {
1567     return m_inputType->hasSpinButton();
1568 }
1569 
supportsPlaceholder() const1570 bool HTMLInputElement::supportsPlaceholder() const
1571 {
1572 #if PLATFORM(ANDROID)
1573     return isTextType() || isNumberField();
1574 #else
1575     return isTextType();
1576 #endif
1577 }
1578 
checkedRadioButtons() const1579 CheckedRadioButtons& HTMLInputElement::checkedRadioButtons() const
1580 {
1581     if (HTMLFormElement* formElement = form())
1582         return formElement->checkedRadioButtons();
1583     return document()->checkedRadioButtons();
1584 }
1585 
handleBeforeTextInsertedEvent(Event * event)1586 void HTMLInputElement::handleBeforeTextInsertedEvent(Event* event)
1587 {
1588     InputElement::handleBeforeTextInsertedEvent(m_data, this, this, event);
1589 }
1590 
1591 #if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE)
capture() const1592 String HTMLInputElement::capture() const
1593 {
1594     if (!isFileUpload()) {
1595         // capture has no meaning on anything other than file pickers.
1596         return String();
1597     }
1598 
1599     String capture = fastGetAttribute(captureAttr).lower();
1600     if (capture == "camera"
1601         || capture == "camcorder"
1602         || capture == "microphone"
1603         || capture == "filesystem")
1604         return capture;
1605     // According to the HTML Media Capture specification, the invalid and
1606     // missing default value is filesystem.
1607     return "filesystem";
1608 }
1609 #endif
1610 
1611 } // namespace
1612