• 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 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
448     if (newType->isPasswordField() && document()->focusedNode() == this)
449         PlatformBridge::updateTextfield(document()->view(), this, true, String());
450 #endif
451     bool hadType = m_hasType;
452     m_hasType = true;
453     if (m_inputType->formControlType() == newType->formControlType())
454         return;
455 
456     if (hadType && !newType->canChangeFromAnotherType()) {
457         // Set the attribute back to the old value.
458         // Useful in case we were called from inside parseMappedAttribute.
459         setAttribute(typeAttr, type());
460         return;
461     }
462 
463     checkedRadioButtons().removeButton(this);
464 
465     bool wasAttached = attached();
466     if (wasAttached)
467         detach();
468 
469     bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
470     bool neededActivationCallback = needsActivationCallback();
471     bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
472 
473     m_inputType->destroyShadowSubtree();
474     m_inputType = newType.release();
475     m_inputType->createShadowSubtree();
476 
477     setNeedsWillValidateCheck();
478 
479     bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
480 
481     if (didStoreValue && !willStoreValue && !m_data.value().isNull()) {
482         setAttribute(valueAttr, m_data.value());
483         m_data.setValue(String());
484     }
485     if (!didStoreValue && willStoreValue)
486         m_data.setValue(sanitizeValue(fastGetAttribute(valueAttr)));
487     else
488         InputElement::updateValueIfNeeded(m_data, this);
489 
490     if (neededActivationCallback)
491         unregisterForActivationCallbackIfNeeded();
492     else
493         registerForActivationCallbackIfNeeded();
494 
495     if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
496         NamedNodeMap* map = attributeMap();
497         ASSERT(map);
498         if (Attribute* height = map->getAttributeItem(heightAttr))
499             attributeChanged(height, false);
500         if (Attribute* width = map->getAttributeItem(widthAttr))
501             attributeChanged(width, false);
502         if (Attribute* align = map->getAttributeItem(alignAttr))
503             attributeChanged(align, false);
504     }
505 
506     if (wasAttached) {
507         attach();
508         if (document()->focusedNode() == this)
509             updateFocusAppearance(true);
510     }
511 
512     setChangedSinceLastFormControlChangeEvent(false);
513 
514     checkedRadioButtons().addButton(this);
515 
516     setNeedsValidityCheck();
517     InputElement::notifyFormStateChanged(this);
518 }
519 
formControlType() const520 const AtomicString& HTMLInputElement::formControlType() const
521 {
522     return m_inputType->formControlType();
523 }
524 
saveFormControlState(String & result) const525 bool HTMLInputElement::saveFormControlState(String& result) const
526 {
527     return m_inputType->saveFormControlState(result);
528 }
529 
restoreFormControlState(const String & state)530 void HTMLInputElement::restoreFormControlState(const String& state)
531 {
532     m_inputType->restoreFormControlState(state);
533     m_stateRestored = true;
534 }
535 
canStartSelection() const536 bool HTMLInputElement::canStartSelection() const
537 {
538     if (!isTextField())
539         return false;
540     return HTMLFormControlElementWithState::canStartSelection();
541 }
542 
canHaveSelection() const543 bool HTMLInputElement::canHaveSelection() const
544 {
545     return isTextField();
546 }
547 
accessKeyAction(bool sendToAnyElement)548 void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
549 {
550     m_inputType->accessKeyAction(sendToAnyElement);
551 }
552 
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const553 bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
554 {
555     if (((attrName == heightAttr || attrName == widthAttr) && m_inputType->shouldRespectHeightAndWidthAttributes())
556         || attrName == vspaceAttr
557         || attrName == hspaceAttr) {
558         result = eUniversal;
559         return false;
560     }
561 
562     if (attrName == alignAttr && m_inputType->shouldRespectAlignAttribute()) {
563         // Share with <img> since the alignment behavior is the same.
564         result = eReplaced;
565         return false;
566     }
567 
568     return HTMLElement::mapToEntry(attrName, result);
569 }
570 
parseMappedAttribute(Attribute * attr)571 void HTMLInputElement::parseMappedAttribute(Attribute* attr)
572 {
573     if (attr->name() == nameAttr) {
574         checkedRadioButtons().removeButton(this);
575         m_data.setName(attr->value());
576         checkedRadioButtons().addButton(this);
577         HTMLFormControlElementWithState::parseMappedAttribute(attr);
578     } else if (attr->name() == autocompleteAttr) {
579         if (equalIgnoringCase(attr->value(), "off")) {
580             m_autocomplete = Off;
581             registerForActivationCallbackIfNeeded();
582         } else {
583             bool needsToUnregister = m_autocomplete == Off;
584 
585             if (attr->isEmpty())
586                 m_autocomplete = Uninitialized;
587             else
588                 m_autocomplete = On;
589 
590             if (needsToUnregister)
591                 unregisterForActivationCallbackIfNeeded();
592         }
593     } else if (attr->name() == typeAttr) {
594         updateType();
595     } else if (attr->name() == valueAttr) {
596         // We only need to setChanged if the form is looking at the default value right now.
597         if (m_data.value().isNull())
598             setNeedsStyleRecalc();
599         setFormControlValueMatchesRenderer(false);
600         setNeedsValidityCheck();
601     } else if (attr->name() == checkedAttr) {
602         // Another radio button in the same group might be checked by state
603         // restore. We shouldn't call setChecked() even if this has the checked
604         // attribute. So, delay the setChecked() call until
605         // finishParsingChildren() is called if parsing is in progress.
606         if (!m_parsingInProgress && m_reflectsCheckedAttribute) {
607             setChecked(!attr->isNull());
608             m_reflectsCheckedAttribute = true;
609         }
610     } else if (attr->name() == maxlengthAttr) {
611         InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
612         setNeedsValidityCheck();
613     } else if (attr->name() == sizeAttr)
614         InputElement::parseSizeAttribute(m_data, this, attr);
615     else if (attr->name() == altAttr)
616         m_inputType->altAttributeChanged();
617     else if (attr->name() == srcAttr)
618         m_inputType->srcAttributeChanged();
619     else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) {
620         // FIXME: ignore for the moment
621     } else if (attr->name() == vspaceAttr) {
622         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
623         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
624     } else if (attr->name() == hspaceAttr) {
625         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
626         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
627     } else if (attr->name() == alignAttr) {
628         if (m_inputType->shouldRespectAlignAttribute())
629             addHTMLAlignment(attr);
630     } else if (attr->name() == widthAttr) {
631         if (m_inputType->shouldRespectHeightAndWidthAttributes())
632             addCSSLength(attr, CSSPropertyWidth, attr->value());
633     } else if (attr->name() == heightAttr) {
634         if (m_inputType->shouldRespectHeightAndWidthAttributes())
635             addCSSLength(attr, CSSPropertyHeight, attr->value());
636     } else if (attr->name() == onsearchAttr) {
637         // Search field and slider attributes all just cause updateFromElement to be called through style recalcing.
638         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
639     } else if (attr->name() == resultsAttr) {
640         int oldResults = m_maxResults;
641         m_maxResults = !attr->isNull() ? std::min(attr->value().toInt(), maxSavedResults) : -1;
642         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
643         // time to relayout for this change.
644         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
645             detach();
646             attach();
647         }
648         setNeedsStyleRecalc();
649     } else if (attr->name() == autosaveAttr || attr->name() == incrementalAttr)
650         setNeedsStyleRecalc();
651     else if (attr->name() == minAttr || attr->name() == maxAttr) {
652         m_inputType->minOrMaxAttributeChanged();
653         setNeedsValidityCheck();
654     } else if (attr->name() == multipleAttr || attr->name() == patternAttr || attr->name() == precisionAttr || attr->name() == stepAttr)
655         setNeedsValidityCheck();
656 #if ENABLE(DATALIST)
657     else if (attr->name() == listAttr)
658         m_hasNonEmptyList = !attr->isEmpty();
659         // FIXME: we need to tell this change to a renderer if the attribute affects the appearance.
660 #endif
661 #if ENABLE(INPUT_SPEECH)
662     else if (attr->name() == webkitspeechAttr) {
663         if (renderer()) {
664             // This renderer and its children have quite different layouts and styles depending on
665             // whether the speech button is visible or not. So we reset the whole thing and recreate
666             // to get the right styles and layout.
667             detach();
668             attach();
669         }
670         setNeedsStyleRecalc();
671     } else if (attr->name() == onwebkitspeechchangeAttr)
672         setAttributeEventListener(eventNames().webkitspeechchangeEvent, createAttributeEventListener(this, attr));
673 #endif
674     else
675         HTMLTextFormControlElement::parseMappedAttribute(attr);
676 }
677 
finishParsingChildren()678 void HTMLInputElement::finishParsingChildren()
679 {
680     m_parsingInProgress = false;
681     HTMLFormControlElementWithState::finishParsingChildren();
682     if (!m_stateRestored) {
683         bool checked = hasAttribute(checkedAttr);
684         if (checked)
685             setChecked(checked);
686         m_reflectsCheckedAttribute = true;
687     }
688 }
689 
rendererIsNeeded(RenderStyle * style)690 bool HTMLInputElement::rendererIsNeeded(RenderStyle* style)
691 {
692     return m_inputType->rendererIsNeeded() && HTMLFormControlElementWithState::rendererIsNeeded(style);
693 }
694 
createRenderer(RenderArena * arena,RenderStyle * style)695 RenderObject* HTMLInputElement::createRenderer(RenderArena* arena, RenderStyle* style)
696 {
697     return m_inputType->createRenderer(arena, style);
698 }
699 
attach()700 void HTMLInputElement::attach()
701 {
702     suspendPostAttachCallbacks();
703 
704     if (!m_hasType)
705         updateType();
706 
707     HTMLFormControlElementWithState::attach();
708 
709     m_inputType->attach();
710 
711     if (document()->focusedNode() == this)
712         document()->updateFocusAppearanceSoon(true /* restore selection */);
713 
714     resumePostAttachCallbacks();
715 }
716 
detach()717 void HTMLInputElement::detach()
718 {
719     HTMLFormControlElementWithState::detach();
720     setFormControlValueMatchesRenderer(false);
721 }
722 
altText() const723 String HTMLInputElement::altText() const
724 {
725     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
726     // also heavily discussed by Hixie on bugzilla
727     // note this is intentionally different to HTMLImageElement::altText()
728     String alt = fastGetAttribute(altAttr);
729     // fall back to title attribute
730     if (alt.isNull())
731         alt = getAttribute(titleAttr);
732     if (alt.isNull())
733         alt = getAttribute(valueAttr);
734     if (alt.isEmpty())
735         alt = inputElementAltText();
736     return alt;
737 }
738 
isSuccessfulSubmitButton() const739 bool HTMLInputElement::isSuccessfulSubmitButton() const
740 {
741     // HTML spec says that buttons must have names to be considered successful.
742     // However, other browsers do not impose this constraint. So we do not.
743     return !disabled() && m_inputType->canBeSuccessfulSubmitButton();
744 }
745 
isActivatedSubmit() const746 bool HTMLInputElement::isActivatedSubmit() const
747 {
748     return m_isActivatedSubmit;
749 }
750 
setActivatedSubmit(bool flag)751 void HTMLInputElement::setActivatedSubmit(bool flag)
752 {
753     m_isActivatedSubmit = flag;
754 }
755 
appendFormData(FormDataList & encoding,bool multipart)756 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
757 {
758     return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(encoding, multipart);
759 }
760 
reset()761 void HTMLInputElement::reset()
762 {
763     if (m_inputType->storesValueSeparateFromAttribute())
764         setValue(String());
765 
766     setAutofilled(false);
767     setChecked(hasAttribute(checkedAttr));
768     m_reflectsCheckedAttribute = true;
769 }
770 
isTextField() const771 bool HTMLInputElement::isTextField() const
772 {
773     return m_inputType->isTextField();
774 }
775 
isTextType() const776 bool HTMLInputElement::isTextType() const
777 {
778     return m_inputType->isTextType();
779 }
780 
setChecked(bool nowChecked,bool sendChangeEvent)781 void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
782 {
783     if (checked() == nowChecked)
784         return;
785 
786     checkedRadioButtons().removeButton(this);
787 
788     m_reflectsCheckedAttribute = false;
789     m_isChecked = nowChecked;
790     setNeedsStyleRecalc();
791 
792     updateCheckedRadioButtons();
793     setNeedsValidityCheck();
794 
795     // Ideally we'd do this from the render tree (matching
796     // RenderTextView), but it's not possible to do it at the moment
797     // because of the way the code is structured.
798     if (renderer() && AXObjectCache::accessibilityEnabled())
799         renderer()->document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXCheckedStateChanged, true);
800 
801     // Only send a change event for items in the document (avoid firing during
802     // parsing) and don't send a change event for a radio button that's getting
803     // unchecked to match other browsers. DOM is not a useful standard for this
804     // because it says only to fire change events at "lose focus" time, which is
805     // definitely wrong in practice for these types of elements.
806     if (sendChangeEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) {
807         setTextAsOfLastFormControlChangeEvent(String());
808         dispatchFormControlChangeEvent();
809     }
810 }
811 
setIndeterminate(bool newValue)812 void HTMLInputElement::setIndeterminate(bool newValue)
813 {
814     if (!m_inputType->isCheckable() || indeterminate() == newValue)
815         return;
816 
817     m_isIndeterminate = newValue;
818 
819     setNeedsStyleRecalc();
820 
821     if (renderer() && renderer()->style()->hasAppearance())
822         renderer()->theme()->stateChanged(renderer(), CheckedState);
823 }
824 
size() const825 int HTMLInputElement::size() const
826 {
827     return m_data.size();
828 }
829 
copyNonAttributeProperties(const Element * source)830 void HTMLInputElement::copyNonAttributeProperties(const Element* source)
831 {
832     const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
833 
834     m_data.setValue(sourceElement->m_data.value());
835     setChecked(sourceElement->m_isChecked);
836     m_reflectsCheckedAttribute = sourceElement->m_reflectsCheckedAttribute;
837     m_isIndeterminate = sourceElement->m_isIndeterminate;
838 
839     HTMLFormControlElementWithState::copyNonAttributeProperties(source);
840 }
841 
value() const842 String HTMLInputElement::value() const
843 {
844     String value;
845     if (m_inputType->getTypeSpecificValue(value))
846         return value;
847 
848     value = m_data.value();
849     if (!value.isNull())
850         return value;
851 
852     value = sanitizeValue(fastGetAttribute(valueAttr));
853     if (!value.isNull())
854         return value;
855 
856     return m_inputType->fallbackValue();
857 }
858 
valueWithDefault() const859 String HTMLInputElement::valueWithDefault() const
860 {
861     String value = this->value();
862     if (!value.isNull())
863         return value;
864 
865     return m_inputType->defaultValue();
866 }
867 
setValueForUser(const String & value)868 void HTMLInputElement::setValueForUser(const String& value)
869 {
870     // Call setValue and make it send a change event.
871     setValue(value, true);
872 }
873 
suggestedValue() const874 const String& HTMLInputElement::suggestedValue() const
875 {
876     return m_data.suggestedValue();
877 }
878 
setSuggestedValue(const String & value)879 void HTMLInputElement::setSuggestedValue(const String& value)
880 {
881     if (!m_inputType->canSetSuggestedValue())
882         return;
883     setFormControlValueMatchesRenderer(false);
884     m_data.setSuggestedValue(sanitizeValue(value));
885     updatePlaceholderVisibility(false);
886     if (renderer())
887         renderer()->updateFromElement();
888     setNeedsStyleRecalc();
889 }
890 
setValue(const String & value,bool sendChangeEvent)891 void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
892 {
893     if (!m_inputType->canSetValue(value))
894         return;
895 
896     setFormControlValueMatchesRenderer(false);
897     if (m_inputType->storesValueSeparateFromAttribute()) {
898         if (files())
899             files()->clear();
900         else {
901             m_data.setValue(sanitizeValue(value));
902             if (isTextField())
903                 updatePlaceholderVisibility(false);
904         }
905         setNeedsStyleRecalc();
906     } else
907         setAttribute(valueAttr, sanitizeValue(value));
908 
909     setNeedsValidityCheck();
910 
911     if (isTextField()) {
912         unsigned max = m_data.value().length();
913 #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
914         // Make sure our UI side textfield changes to match the RenderTextControl
915         PlatformBridge::updateTextfield(document()->view(), this, false, value);
916 #endif
917         if (document()->focusedNode() == this)
918             InputElement::updateSelectionRange(this, this, max, max);
919         else
920             cacheSelection(max, max);
921         m_data.setSuggestedValue(String());
922     }
923     m_inputType->valueChanged();
924 
925     if (sendChangeEvent) {
926         // If the user is still editing this field, dispatch an input event rather than a change event.
927         // The change event will be dispatched when editing finishes.
928         if (isTextField() && focused())
929             dispatchFormControlInputEvent();
930         else
931             dispatchFormControlChangeEvent();
932     }
933 
934     if (isText() && (!focused() || !sendChangeEvent))
935         setTextAsOfLastFormControlChangeEvent(value);
936 
937     InputElement::notifyFormStateChanged(this);
938 }
939 
valueAsDate() const940 double HTMLInputElement::valueAsDate() const
941 {
942     return m_inputType->valueAsDate();
943 }
944 
setValueAsDate(double value,ExceptionCode & ec)945 void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec)
946 {
947     m_inputType->setValueAsDate(value, ec);
948 }
949 
valueAsNumber() const950 double HTMLInputElement::valueAsNumber() const
951 {
952     return m_inputType->valueAsNumber();
953 }
954 
setValueAsNumber(double newValue,ExceptionCode & ec)955 void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
956 {
957     if (!isfinite(newValue)) {
958         ec = NOT_SUPPORTED_ERR;
959         return;
960     }
961     m_inputType->setValueAsNumber(newValue, ec);
962 }
963 
placeholder() const964 String HTMLInputElement::placeholder() const
965 {
966     return fastGetAttribute(placeholderAttr).string();
967 }
968 
setPlaceholder(const String & value)969 void HTMLInputElement::setPlaceholder(const String& value)
970 {
971     setAttribute(placeholderAttr, value);
972 }
973 
searchEventsShouldBeDispatched() const974 bool HTMLInputElement::searchEventsShouldBeDispatched() const
975 {
976     return hasAttribute(incrementalAttr);
977 }
978 
setValueFromRenderer(const String & value)979 void HTMLInputElement::setValueFromRenderer(const String& value)
980 {
981     // File upload controls will always use setFileListFromRenderer.
982     ASSERT(!isFileUpload());
983 
984     m_data.setSuggestedValue(String());
985     InputElement::setValueFromRenderer(m_data, this, this, value);
986     updatePlaceholderVisibility(false);
987     setNeedsValidityCheck();
988 
989     // Clear autofill flag (and yellow background) on user edit.
990     setAutofilled(false);
991 }
992 
setFileListFromRenderer(const Vector<String> & paths)993 void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
994 {
995     m_inputType->setFileList(paths);
996 
997     setFormControlValueMatchesRenderer(true);
998     InputElement::notifyFormStateChanged(this);
999     setNeedsValidityCheck();
1000 }
1001 
preDispatchEventHandler(Event * event)1002 void* HTMLInputElement::preDispatchEventHandler(Event* event)
1003 {
1004     if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
1005         event->stopPropagation();
1006         return 0;
1007     }
1008     if (event->type() != eventNames().clickEvent)
1009         return 0;
1010     if (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button() != LeftButton)
1011         return 0;
1012     // FIXME: Check whether there are any cases where this actually ends up leaking.
1013     return m_inputType->willDispatchClick().leakPtr();
1014 }
1015 
postDispatchEventHandler(Event * event,void * dataFromPreDispatch)1016 void HTMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
1017 {
1018     OwnPtr<ClickHandlingState> state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch));
1019     if (!state)
1020         return;
1021     m_inputType->didDispatchClick(event, *state);
1022 }
1023 
defaultEventHandler(Event * evt)1024 void HTMLInputElement::defaultEventHandler(Event* evt)
1025 {
1026     if (evt->isMouseEvent() && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1027         m_inputType->handleClickEvent(static_cast<MouseEvent*>(evt));
1028         if (evt->defaultHandled())
1029             return;
1030     }
1031 
1032     if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
1033         m_inputType->handleKeydownEvent(static_cast<KeyboardEvent*>(evt));
1034         if (evt->defaultHandled())
1035             return;
1036     }
1037 
1038     // Call the base event handler before any of our own event handling for almost all events in text fields.
1039     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
1040     bool callBaseClassEarly = isTextField() && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1041     if (callBaseClassEarly) {
1042         HTMLFormControlElementWithState::defaultEventHandler(evt);
1043         if (evt->defaultHandled())
1044             return;
1045     }
1046 
1047     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
1048     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
1049     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
1050     // must dispatch a DOMActivate event - a click event will not do the job.
1051     if (evt->type() == eventNames().DOMActivateEvent) {
1052         m_inputType->handleDOMActivateEvent(evt);
1053         if (evt->defaultHandled())
1054             return;
1055     }
1056 
1057     // Use key press event here since sending simulated mouse events
1058     // on key down blocks the proper sending of the key press event.
1059     if (evt->isKeyboardEvent() && evt->type() == eventNames().keypressEvent) {
1060         m_inputType->handleKeypressEvent(static_cast<KeyboardEvent*>(evt));
1061         if (evt->defaultHandled())
1062             return;
1063     }
1064 
1065     if (evt->isKeyboardEvent() && evt->type() == eventNames().keyupEvent) {
1066         m_inputType->handleKeyupEvent(static_cast<KeyboardEvent*>(evt));
1067         if (evt->defaultHandled())
1068             return;
1069     }
1070 
1071     if (m_inputType->shouldSubmitImplicitly(evt)) {
1072         if (isSearchField()) {
1073             addSearchResult();
1074             onSearch();
1075         }
1076         // Form submission finishes editing, just as loss of focus does.
1077         // If there was a change, send the event now.
1078         if (wasChangedSinceLastFormControlChangeEvent())
1079             dispatchFormControlChangeEvent();
1080 
1081         RefPtr<HTMLFormElement> formForSubmission = m_inputType->formForSubmission();
1082         // Form may never have been present, or may have been destroyed by code responding to the change event.
1083         if (formForSubmission)
1084             formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
1085 
1086         evt->setDefaultHandled();
1087         return;
1088     }
1089 
1090     if (evt->isBeforeTextInsertedEvent())
1091         m_inputType->handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(evt));
1092 
1093     if (evt->isWheelEvent()) {
1094         m_inputType->handleWheelEvent(static_cast<WheelEvent*>(evt));
1095         if (evt->defaultHandled())
1096             return;
1097     }
1098 
1099     if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
1100         m_inputType->handleMouseDownEvent(static_cast<MouseEvent*>(evt));
1101         if (evt->defaultHandled())
1102             return;
1103     }
1104 
1105 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
1106     if (evt->isTouchEvent() && evt->type() == eventNames().touchstartEvent) {
1107         m_inputType->handleTouchStartEvent(static_cast<TouchEvent*>(evt));
1108         if (evt->defaultHandled())
1109             return;
1110     }
1111 #endif
1112 
1113     m_inputType->forwardEvent(evt);
1114 
1115     if (!callBaseClassEarly && !evt->defaultHandled())
1116         HTMLFormControlElementWithState::defaultEventHandler(evt);
1117 }
1118 
isURLAttribute(Attribute * attr) const1119 bool HTMLInputElement::isURLAttribute(Attribute *attr) const
1120 {
1121     return (attr->name() == srcAttr || attr->name() == formactionAttr);
1122 }
1123 
defaultValue() const1124 String HTMLInputElement::defaultValue() const
1125 {
1126     return fastGetAttribute(valueAttr);
1127 }
1128 
setDefaultValue(const String & value)1129 void HTMLInputElement::setDefaultValue(const String &value)
1130 {
1131     setAttribute(valueAttr, value);
1132 }
1133 
setDefaultName(const AtomicString & name)1134 void HTMLInputElement::setDefaultName(const AtomicString& name)
1135 {
1136     m_data.setName(name);
1137 }
1138 
accept() const1139 String HTMLInputElement::accept() const
1140 {
1141     return fastGetAttribute(acceptAttr);
1142 }
1143 
alt() const1144 String HTMLInputElement::alt() const
1145 {
1146     return fastGetAttribute(altAttr);
1147 }
1148 
maxLength() const1149 int HTMLInputElement::maxLength() const
1150 {
1151     return m_data.maxLength();
1152 }
1153 
setMaxLength(int maxLength,ExceptionCode & ec)1154 void HTMLInputElement::setMaxLength(int maxLength, ExceptionCode& ec)
1155 {
1156     if (maxLength < 0)
1157         ec = INDEX_SIZE_ERR;
1158     else
1159         setAttribute(maxlengthAttr, String::number(maxLength));
1160 }
1161 
multiple() const1162 bool HTMLInputElement::multiple() const
1163 {
1164     return fastHasAttribute(multipleAttr);
1165 }
1166 
setSize(unsigned size)1167 void HTMLInputElement::setSize(unsigned size)
1168 {
1169     setAttribute(sizeAttr, String::number(size));
1170 }
1171 
src() const1172 KURL HTMLInputElement::src() const
1173 {
1174     return document()->completeURL(fastGetAttribute(srcAttr));
1175 }
1176 
setAutofilled(bool autofilled)1177 void HTMLInputElement::setAutofilled(bool autofilled)
1178 {
1179     if (autofilled == m_isAutofilled)
1180         return;
1181 
1182     m_isAutofilled = autofilled;
1183     setNeedsStyleRecalc();
1184 }
1185 
files()1186 FileList* HTMLInputElement::files()
1187 {
1188     return m_inputType->files();
1189 }
1190 
visibleValue() const1191 String HTMLInputElement::visibleValue() const
1192 {
1193     return m_inputType->visibleValue();
1194 }
1195 
convertFromVisibleValue(const String & visibleValue) const1196 String HTMLInputElement::convertFromVisibleValue(const String& visibleValue) const
1197 {
1198     return m_inputType->convertFromVisibleValue(visibleValue);
1199 }
1200 
isAcceptableValue(const String & proposedValue) const1201 bool HTMLInputElement::isAcceptableValue(const String& proposedValue) const
1202 {
1203     return m_inputType->isAcceptableValue(proposedValue);
1204 }
1205 
sanitizeValue(const String & proposedValue) const1206 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
1207 {
1208     return m_inputType->sanitizeValue(proposedValue);
1209 }
1210 
hasUnacceptableValue() const1211 bool HTMLInputElement::hasUnacceptableValue() const
1212 {
1213     return m_inputType->hasUnacceptableValue();
1214 }
1215 
isInRange() const1216 bool HTMLInputElement::isInRange() const
1217 {
1218     return m_inputType->supportsRangeLimitation() && !rangeUnderflow(value()) && !rangeOverflow(value());
1219 }
1220 
isOutOfRange() const1221 bool HTMLInputElement::isOutOfRange() const
1222 {
1223     return m_inputType->supportsRangeLimitation() && (rangeUnderflow(value()) || rangeOverflow(value()));
1224 }
1225 
needsActivationCallback()1226 bool HTMLInputElement::needsActivationCallback()
1227 {
1228     return m_autocomplete == Off || m_inputType->shouldResetOnDocumentActivation();
1229 }
1230 
registerForActivationCallbackIfNeeded()1231 void HTMLInputElement::registerForActivationCallbackIfNeeded()
1232 {
1233     if (needsActivationCallback())
1234         document()->registerForDocumentActivationCallbacks(this);
1235 }
1236 
unregisterForActivationCallbackIfNeeded()1237 void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
1238 {
1239     if (!needsActivationCallback())
1240         document()->unregisterForDocumentActivationCallbacks(this);
1241 }
1242 
isRequiredFormControl() const1243 bool HTMLInputElement::isRequiredFormControl() const
1244 {
1245     return m_inputType->supportsRequired() && required();
1246 }
1247 
cacheSelection(int start,int end)1248 void HTMLInputElement::cacheSelection(int start, int end)
1249 {
1250     m_data.setCachedSelectionStart(start);
1251     m_data.setCachedSelectionEnd(end);
1252 }
1253 
addSearchResult()1254 void HTMLInputElement::addSearchResult()
1255 {
1256     ASSERT(isSearchField());
1257     if (renderer())
1258         toRenderTextControlSingleLine(renderer())->addSearchResult();
1259 }
1260 
onSearch()1261 void HTMLInputElement::onSearch()
1262 {
1263     ASSERT(isSearchField());
1264     if (renderer())
1265         toRenderTextControlSingleLine(renderer())->stopSearchEventTimer();
1266     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
1267 }
1268 
documentDidBecomeActive()1269 void HTMLInputElement::documentDidBecomeActive()
1270 {
1271     ASSERT(needsActivationCallback());
1272     reset();
1273 }
1274 
willMoveToNewOwnerDocument()1275 void HTMLInputElement::willMoveToNewOwnerDocument()
1276 {
1277     m_inputType->willMoveToNewOwnerDocument();
1278 
1279     // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
1280     if (needsActivationCallback())
1281         document()->unregisterForDocumentActivationCallbacks(this);
1282 
1283     document()->checkedRadioButtons().removeButton(this);
1284 
1285     HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
1286 }
1287 
didMoveToNewOwnerDocument()1288 void HTMLInputElement::didMoveToNewOwnerDocument()
1289 {
1290     registerForActivationCallbackIfNeeded();
1291 
1292     HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
1293 }
1294 
addSubresourceAttributeURLs(ListHashSet<KURL> & urls) const1295 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
1296 {
1297     HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls);
1298 
1299     addSubresourceURL(urls, src());
1300 }
1301 
recalcWillValidate() const1302 bool HTMLInputElement::recalcWillValidate() const
1303 {
1304     return m_inputType->supportsValidation() && HTMLFormControlElementWithState::recalcWillValidate();
1305 }
1306 
1307 #if ENABLE(DATALIST)
1308 
list() const1309 HTMLElement* HTMLInputElement::list() const
1310 {
1311     return dataList();
1312 }
1313 
dataList() const1314 HTMLDataListElement* HTMLInputElement::dataList() const
1315 {
1316     if (!m_hasNonEmptyList)
1317         return 0;
1318 
1319     if (!m_inputType->shouldRespectListAttribute())
1320         return 0;
1321 
1322     Element* element = document()->getElementById(fastGetAttribute(listAttr));
1323     if (!element)
1324         return 0;
1325     if (!element->hasTagName(datalistTag))
1326         return 0;
1327 
1328     return static_cast<HTMLDataListElement*>(element);
1329 }
1330 
selectedOption() const1331 HTMLOptionElement* HTMLInputElement::selectedOption() const
1332 {
1333     String value = this->value();
1334 
1335     // The empty string never matches to a datalist option because it
1336     // doesn't represent a suggestion according to the standard.
1337     if (value.isEmpty())
1338         return 0;
1339 
1340     HTMLDataListElement* sourceElement = dataList();
1341     if (!sourceElement)
1342         return 0;
1343     RefPtr<HTMLCollection> options = sourceElement->options();
1344     if (!options)
1345         return 0;
1346     unsigned length = options->length();
1347     for (unsigned i = 0; i < length; ++i) {
1348         HTMLOptionElement* option = static_cast<HTMLOptionElement*>(options->item(i));
1349         if (!option->disabled() && value == option->value())
1350             return option;
1351     }
1352     return 0;
1353 }
1354 
1355 #endif // ENABLE(DATALIST)
1356 
stepUpFromRenderer(int n)1357 void HTMLInputElement::stepUpFromRenderer(int n)
1358 {
1359     // The differences from stepUp()/stepDown():
1360     //
1361     // Difference 1: the current value
1362     // If the current value is not a number, including empty, the current value is assumed as 0.
1363     //   * If 0 is in-range, and matches to step value
1364     //     - The value should be the +step if n > 0
1365     //     - The value should be the -step if n < 0
1366     //     If -step or +step is out of range, new value should be 0.
1367     //   * If 0 is smaller than the minimum value
1368     //     - The value should be the minimum value for any n
1369     //   * If 0 is larger than the maximum value
1370     //     - The value should be the maximum value for any n
1371     //   * If 0 is in-range, but not matched to step value
1372     //     - The value should be the larger matched value nearest to 0 if n > 0
1373     //       e.g. <input type=number min=-100 step=3> -> 2
1374     //     - The value should be the smaler matched value nearest to 0 if n < 0
1375     //       e.g. <input type=number min=-100 step=3> -> -1
1376     //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
1377     //   As for datetime type, the current value is assumed as "the current date/time in UTC".
1378     // If the current value is smaller than the minimum value:
1379     //  - The value should be the minimum value if n > 0
1380     //  - Nothing should happen if n < 0
1381     // If the current value is larger than the maximum value:
1382     //  - The value should be the maximum value if n < 0
1383     //  - Nothing should happen if n > 0
1384     //
1385     // Difference 2: clamping steps
1386     // If the current value is not matched to step value:
1387     // - The value should be the larger matched value nearest to 0 if n > 0
1388     //   e.g. <input type=number value=3 min=-100 step=3> -> 5
1389     // - The value should be the smaler matched value nearest to 0 if n < 0
1390     //   e.g. <input type=number value=3 min=-100 step=3> -> 2
1391     //
1392     // n is assumed as -n if step < 0.
1393 
1394     ASSERT(hasSpinButton() || m_inputType->isRangeControl());
1395     if (!hasSpinButton() && !m_inputType->isRangeControl())
1396         return;
1397     ASSERT(n);
1398     if (!n)
1399         return;
1400 
1401     unsigned stepDecimalPlaces, baseDecimalPlaces;
1402     double step, base;
1403     // The value will be the default value after stepping for <input value=(empty/invalid) step="any" />
1404     // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
1405     // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
1406     if (equalIgnoringCase(fastGetAttribute(stepAttr), "any"))
1407         step = 0;
1408     else if (!getAllowedValueStepWithDecimalPlaces(&step, &stepDecimalPlaces))
1409         return;
1410     base = m_inputType->stepBaseWithDecimalPlaces(&baseDecimalPlaces);
1411     baseDecimalPlaces = min(baseDecimalPlaces, 16u);
1412 
1413     int sign;
1414     if (step > 0)
1415         sign = n;
1416     else if (step < 0)
1417         sign = -n;
1418     else
1419         sign = 0;
1420 
1421     const double nan = numeric_limits<double>::quiet_NaN();
1422     String currentStringValue = value();
1423     double current = m_inputType->parseToDouble(currentStringValue, nan);
1424     if (!isfinite(current)) {
1425         ExceptionCode ec;
1426         current = m_inputType->defaultValueForStepUp();
1427         setValueAsNumber(current, ec);
1428     }
1429     if ((sign > 0 && current < m_inputType->minimum()) || (sign < 0 && current > m_inputType->maximum()))
1430         setValue(m_inputType->serialize(sign > 0 ? m_inputType->minimum() : m_inputType->maximum()));
1431     else {
1432         ExceptionCode ec;
1433         if (stepMismatch(currentStringValue)) {
1434             ASSERT(step);
1435             double newValue;
1436             double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces)));
1437 
1438             if (sign < 0)
1439                 newValue = round((base + floor((current - base) / step) * step) * scale) / scale;
1440             else if (sign > 0)
1441                 newValue = round((base + ceil((current - base) / step) * step) * scale) / scale;
1442             else
1443                 newValue = current;
1444 
1445             if (newValue < m_inputType->minimum())
1446                 newValue = m_inputType->minimum();
1447             if (newValue > m_inputType->maximum())
1448                 newValue = m_inputType->maximum();
1449 
1450             setValueAsNumber(newValue, ec);
1451             current = newValue;
1452             if (n > 1)
1453                 applyStep(n - 1, ec);
1454             else if (n < -1)
1455                 applyStep(n + 1, ec);
1456         } else
1457             applyStep(n, ec);
1458     }
1459 
1460     if (currentStringValue != value()) {
1461         if (m_inputType->isRangeControl())
1462             dispatchFormControlChangeEvent();
1463         else
1464             dispatchFormControlInputEvent();
1465     }
1466 }
1467 
1468 #if ENABLE(WCSS)
1469 
setWapInputFormat(String & mask)1470 void HTMLInputElement::setWapInputFormat(String& mask)
1471 {
1472     String validateMask = validateInputMask(m_data, mask);
1473     if (!validateMask.isEmpty())
1474         m_data.setInputFormatMask(validateMask);
1475 }
1476 
1477 #endif
1478 
1479 #if ENABLE(INPUT_SPEECH)
1480 
isSpeechEnabled() const1481 bool HTMLInputElement::isSpeechEnabled() const
1482 {
1483     // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types.
1484     return m_inputType->shouldRespectSpeechAttribute() && RuntimeEnabledFeatures::speechInputEnabled() && hasAttribute(webkitspeechAttr);
1485 }
1486 
1487 #endif
1488 
isTextButton() const1489 bool HTMLInputElement::isTextButton() const
1490 {
1491     return m_inputType->isTextButton();
1492 }
1493 
isRadioButton() const1494 bool HTMLInputElement::isRadioButton() const
1495 {
1496     return m_inputType->isRadioButton();
1497 }
1498 
isSearchField() const1499 bool HTMLInputElement::isSearchField() const
1500 {
1501     return m_inputType->isSearchField();
1502 }
1503 
isInputTypeHidden() const1504 bool HTMLInputElement::isInputTypeHidden() const
1505 {
1506     return m_inputType->isHiddenType();
1507 }
1508 
isPasswordField() const1509 bool HTMLInputElement::isPasswordField() const
1510 {
1511     return m_inputType->isPasswordField();
1512 }
1513 
isCheckbox() const1514 bool HTMLInputElement::isCheckbox() const
1515 {
1516     return m_inputType->isCheckbox();
1517 }
1518 
isText() const1519 bool HTMLInputElement::isText() const
1520 {
1521     return m_inputType->isTextType();
1522 }
1523 
isEmailField() const1524 bool HTMLInputElement::isEmailField() const
1525 {
1526     return m_inputType->isEmailField();
1527 }
1528 
isFileUpload() const1529 bool HTMLInputElement::isFileUpload() const
1530 {
1531     return m_inputType->isFileUpload();
1532 }
1533 
isImageButton() const1534 bool HTMLInputElement::isImageButton() const
1535 {
1536     return m_inputType->isImageButton();
1537 }
1538 
isNumberField() const1539 bool HTMLInputElement::isNumberField() const
1540 {
1541     return m_inputType->isNumberField();
1542 }
1543 
isSubmitButton() const1544 bool HTMLInputElement::isSubmitButton() const
1545 {
1546     return m_inputType->isSubmitButton();
1547 }
1548 
isTelephoneField() const1549 bool HTMLInputElement::isTelephoneField() const
1550 {
1551     return m_inputType->isTelephoneField();
1552 }
1553 
isURLField() const1554 bool HTMLInputElement::isURLField() const
1555 {
1556     return m_inputType->isURLField();
1557 }
1558 
isEnumeratable() const1559 bool HTMLInputElement::isEnumeratable() const
1560 {
1561     return m_inputType->isEnumeratable();
1562 }
1563 
isChecked() const1564 bool HTMLInputElement::isChecked() const
1565 {
1566     return checked() && m_inputType->isCheckable();
1567 }
1568 
hasSpinButton() const1569 bool HTMLInputElement::hasSpinButton() const
1570 {
1571     return m_inputType->hasSpinButton();
1572 }
1573 
supportsPlaceholder() const1574 bool HTMLInputElement::supportsPlaceholder() const
1575 {
1576     return isTextType();
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