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 "InputType.h"
29
30 #include "BeforeTextInsertedEvent.h"
31 #include "ButtonInputType.h"
32 #include "CheckboxInputType.h"
33 #include "ColorInputType.h"
34 #include "DateComponents.h"
35 #include "DateInputType.h"
36 #include "DateTimeInputType.h"
37 #include "DateTimeLocalInputType.h"
38 #include "EmailInputType.h"
39 #include "ExceptionCode.h"
40 #include "FileInputType.h"
41 #include "FormDataList.h"
42 #include "HTMLFormElement.h"
43 #include "HTMLInputElement.h"
44 #include "HiddenInputType.h"
45 #include "ImageInputType.h"
46 #include "IsIndexInputType.h"
47 #include "KeyboardEvent.h"
48 #include "LocalizedStrings.h"
49 #include "MonthInputType.h"
50 #include "NumberInputType.h"
51 #include "PasswordInputType.h"
52 #include "RadioInputType.h"
53 #include "RangeInputType.h"
54 #include "RegularExpression.h"
55 #include "RenderObject.h"
56 #include "ResetInputType.h"
57 #include "SearchInputType.h"
58 #include "ShadowRoot.h"
59 #include "SubmitInputType.h"
60 #include "TelephoneInputType.h"
61 #include "TextInputType.h"
62 #include "TimeInputType.h"
63 #include "URLInputType.h"
64 #include "WeekInputType.h"
65 #include <limits>
66 #include <wtf/Assertions.h>
67 #include <wtf/HashMap.h>
68 #include <wtf/text/StringHash.h>
69
70 namespace WebCore {
71
72 using namespace std;
73
74 typedef PassOwnPtr<InputType> (*InputTypeFactoryFunction)(HTMLInputElement*);
75 typedef HashMap<String, InputTypeFactoryFunction, CaseFoldingHash> InputTypeFactoryMap;
76
createInputTypeFactoryMap()77 static PassOwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
78 {
79 OwnPtr<InputTypeFactoryMap> map = adoptPtr(new InputTypeFactoryMap);
80 map->add(InputTypeNames::button(), ButtonInputType::create);
81 map->add(InputTypeNames::checkbox(), CheckboxInputType::create);
82 map->add(InputTypeNames::color(), ColorInputType::create);
83 map->add(InputTypeNames::date(), DateInputType::create);
84 map->add(InputTypeNames::datetime(), DateTimeInputType::create);
85 map->add(InputTypeNames::datetimelocal(), DateTimeLocalInputType::create);
86 map->add(InputTypeNames::email(), EmailInputType::create);
87 map->add(InputTypeNames::file(), FileInputType::create);
88 map->add(InputTypeNames::hidden(), HiddenInputType::create);
89 map->add(InputTypeNames::image(), ImageInputType::create);
90 map->add(InputTypeNames::isindex(), IsIndexInputType::create);
91 map->add(InputTypeNames::month(), MonthInputType::create);
92 map->add(InputTypeNames::number(), NumberInputType::create);
93 map->add(InputTypeNames::password(), PasswordInputType::create);
94 map->add(InputTypeNames::radio(), RadioInputType::create);
95 map->add(InputTypeNames::range(), RangeInputType::create);
96 map->add(InputTypeNames::reset(), ResetInputType::create);
97 map->add(InputTypeNames::search(), SearchInputType::create);
98 map->add(InputTypeNames::submit(), SubmitInputType::create);
99 map->add(InputTypeNames::telephone(), TelephoneInputType::create);
100 map->add(InputTypeNames::time(), TimeInputType::create);
101 map->add(InputTypeNames::url(), URLInputType::create);
102 map->add(InputTypeNames::week(), WeekInputType::create);
103 // No need to register "text" because it is the default type.
104 return map.release();
105 }
106
create(HTMLInputElement * element,const String & typeName)107 PassOwnPtr<InputType> InputType::create(HTMLInputElement* element, const String& typeName)
108 {
109 static const InputTypeFactoryMap* factoryMap = createInputTypeFactoryMap().leakPtr();
110 PassOwnPtr<InputType> (*factory)(HTMLInputElement*) = typeName.isEmpty() ? 0 : factoryMap->get(typeName);
111 if (!factory)
112 factory = TextInputType::create;
113 return factory(element);
114 }
115
createText(HTMLInputElement * element)116 PassOwnPtr<InputType> InputType::createText(HTMLInputElement* element)
117 {
118 return TextInputType::create(element);
119 }
120
~InputType()121 InputType::~InputType()
122 {
123 }
124
isTextField() const125 bool InputType::isTextField() const
126 {
127 return false;
128 }
129
isTextType() const130 bool InputType::isTextType() const
131 {
132 return false;
133 }
134
isRangeControl() const135 bool InputType::isRangeControl() const
136 {
137 return false;
138 }
139
saveFormControlState(String & result) const140 bool InputType::saveFormControlState(String& result) const
141 {
142 String currentValue = element()->value();
143 if (currentValue == element()->defaultValue())
144 return false;
145 result = currentValue;
146 return true;
147 }
148
restoreFormControlState(const String & state) const149 void InputType::restoreFormControlState(const String& state) const
150 {
151 element()->setValue(state);
152 }
153
isFormDataAppendable() const154 bool InputType::isFormDataAppendable() const
155 {
156 // There is no form data unless there's a name for non-image types.
157 return !element()->name().isEmpty();
158 }
159
appendFormData(FormDataList & encoding,bool) const160 bool InputType::appendFormData(FormDataList& encoding, bool) const
161 {
162 // Always successful.
163 encoding.appendData(element()->name(), element()->value());
164 return true;
165 }
166
valueAsDate() const167 double InputType::valueAsDate() const
168 {
169 return DateComponents::invalidMilliseconds();
170 }
171
setValueAsDate(double,ExceptionCode & ec) const172 void InputType::setValueAsDate(double, ExceptionCode& ec) const
173 {
174 ec = INVALID_STATE_ERR;
175 }
176
valueAsNumber() const177 double InputType::valueAsNumber() const
178 {
179 return numeric_limits<double>::quiet_NaN();
180 }
181
setValueAsNumber(double,ExceptionCode & ec) const182 void InputType::setValueAsNumber(double, ExceptionCode& ec) const
183 {
184 ec = INVALID_STATE_ERR;
185 }
186
supportsValidation() const187 bool InputType::supportsValidation() const
188 {
189 return true;
190 }
191
typeMismatchFor(const String &) const192 bool InputType::typeMismatchFor(const String&) const
193 {
194 return false;
195 }
196
typeMismatch() const197 bool InputType::typeMismatch() const
198 {
199 return false;
200 }
201
supportsRequired() const202 bool InputType::supportsRequired() const
203 {
204 // Almost all validatable types support @required.
205 return supportsValidation();
206 }
207
valueMissing(const String &) const208 bool InputType::valueMissing(const String&) const
209 {
210 return false;
211 }
212
patternMismatch(const String &) const213 bool InputType::patternMismatch(const String&) const
214 {
215 return false;
216 }
217
rangeUnderflow(const String &) const218 bool InputType::rangeUnderflow(const String&) const
219 {
220 return false;
221 }
222
rangeOverflow(const String &) const223 bool InputType::rangeOverflow(const String&) const
224 {
225 return false;
226 }
227
supportsRangeLimitation() const228 bool InputType::supportsRangeLimitation() const
229 {
230 return false;
231 }
232
defaultValueForStepUp() const233 double InputType::defaultValueForStepUp() const
234 {
235 return 0;
236 }
237
minimum() const238 double InputType::minimum() const
239 {
240 ASSERT_NOT_REACHED();
241 return 0;
242 }
243
maximum() const244 double InputType::maximum() const
245 {
246 ASSERT_NOT_REACHED();
247 return 0;
248 }
249
stepMismatch(const String &,double) const250 bool InputType::stepMismatch(const String&, double) const
251 {
252 // Non-supported types should be rejected by HTMLInputElement::getAllowedValueStep().
253 ASSERT_NOT_REACHED();
254 return false;
255 }
256
stepBase() const257 double InputType::stepBase() const
258 {
259 ASSERT_NOT_REACHED();
260 return 0;
261 }
262
stepBaseWithDecimalPlaces(unsigned * decimalPlaces) const263 double InputType::stepBaseWithDecimalPlaces(unsigned* decimalPlaces) const
264 {
265 if (decimalPlaces)
266 *decimalPlaces = 0;
267 return stepBase();
268 }
269
defaultStep() const270 double InputType::defaultStep() const
271 {
272 return numeric_limits<double>::quiet_NaN();
273 }
274
stepScaleFactor() const275 double InputType::stepScaleFactor() const
276 {
277 return numeric_limits<double>::quiet_NaN();
278 }
279
parsedStepValueShouldBeInteger() const280 bool InputType::parsedStepValueShouldBeInteger() const
281 {
282 return false;
283 }
284
scaledStepValueShouldBeInteger() const285 bool InputType::scaledStepValueShouldBeInteger() const
286 {
287 return false;
288 }
289
acceptableError(double) const290 double InputType::acceptableError(double) const
291 {
292 return 0;
293 }
294
typeMismatchText() const295 String InputType::typeMismatchText() const
296 {
297 return validationMessageTypeMismatchText();
298 }
299
valueMissingText() const300 String InputType::valueMissingText() const
301 {
302 return validationMessageValueMissingText();
303 }
304
handleClickEvent(MouseEvent *)305 void InputType::handleClickEvent(MouseEvent*)
306 {
307 }
308
handleMouseDownEvent(MouseEvent *)309 void InputType::handleMouseDownEvent(MouseEvent*)
310 {
311 }
312
313 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
handleTouchStartEvent(TouchEvent *)314 void InputType::handleTouchStartEvent(TouchEvent*)
315 {
316 }
317 #endif
318
handleDOMActivateEvent(Event *)319 void InputType::handleDOMActivateEvent(Event*)
320 {
321 }
322
handleKeydownEvent(KeyboardEvent *)323 void InputType::handleKeydownEvent(KeyboardEvent*)
324 {
325 }
326
handleKeypressEvent(KeyboardEvent *)327 void InputType::handleKeypressEvent(KeyboardEvent*)
328 {
329 }
330
handleKeyupEvent(KeyboardEvent *)331 void InputType::handleKeyupEvent(KeyboardEvent*)
332 {
333 }
334
handleBeforeTextInsertedEvent(BeforeTextInsertedEvent * event)335 void InputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event)
336 {
337 element()->handleBeforeTextInsertedEvent(event);
338 }
339
handleWheelEvent(WheelEvent *)340 void InputType::handleWheelEvent(WheelEvent*)
341 {
342 }
343
forwardEvent(Event *)344 void InputType::forwardEvent(Event*)
345 {
346 }
347
shouldSubmitImplicitly(Event * event)348 bool InputType::shouldSubmitImplicitly(Event* event)
349 {
350 return event->isKeyboardEvent() && event->type() == eventNames().keypressEvent && static_cast<KeyboardEvent*>(event)->charCode() == '\r';
351 }
352
formForSubmission() const353 PassRefPtr<HTMLFormElement> InputType::formForSubmission() const
354 {
355 return element()->form();
356 }
357
createRenderer(RenderArena *,RenderStyle * style) const358 RenderObject* InputType::createRenderer(RenderArena*, RenderStyle* style) const
359 {
360 return RenderObject::createObject(element(), style);
361 }
362
createShadowSubtree()363 void InputType::createShadowSubtree()
364 {
365 }
366
destroyShadowSubtree()367 void InputType::destroyShadowSubtree()
368 {
369 element()->removeShadowRoot();
370 }
371
parseToDouble(const String &,double defaultValue) const372 double InputType::parseToDouble(const String&, double defaultValue) const
373 {
374 return defaultValue;
375 }
376
parseToDoubleWithDecimalPlaces(const String & src,double defaultValue,unsigned * decimalPlaces) const377 double InputType::parseToDoubleWithDecimalPlaces(const String& src, double defaultValue, unsigned *decimalPlaces) const
378 {
379 if (decimalPlaces)
380 *decimalPlaces = 0;
381 return parseToDouble(src, defaultValue);
382 }
383
parseToDateComponents(const String &,DateComponents *) const384 bool InputType::parseToDateComponents(const String&, DateComponents*) const
385 {
386 ASSERT_NOT_REACHED();
387 return false;
388 }
389
serialize(double) const390 String InputType::serialize(double) const
391 {
392 ASSERT_NOT_REACHED();
393 return String();
394 }
395
dispatchSimulatedClickIfActive(KeyboardEvent * event) const396 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const
397 {
398 if (element()->active())
399 element()->dispatchSimulatedClick(event);
400 event->setDefaultHandled();
401 }
402
canSetStringValue() const403 bool InputType::canSetStringValue() const
404 {
405 return true;
406 }
407
isKeyboardFocusable() const408 bool InputType::isKeyboardFocusable() const
409 {
410 return true;
411 }
412
shouldUseInputMethod() const413 bool InputType::shouldUseInputMethod() const
414 {
415 return false;
416 }
417
handleBlurEvent()418 void InputType::handleBlurEvent()
419 {
420 }
421
accessKeyAction(bool)422 void InputType::accessKeyAction(bool)
423 {
424 element()->focus(false);
425 }
426
attach()427 void InputType::attach()
428 {
429 }
430
altAttributeChanged()431 void InputType::altAttributeChanged()
432 {
433 }
434
srcAttributeChanged()435 void InputType::srcAttributeChanged()
436 {
437 }
438
valueChanged()439 void InputType::valueChanged()
440 {
441 }
442
willMoveToNewOwnerDocument()443 void InputType::willMoveToNewOwnerDocument()
444 {
445 }
446
shouldRespectAlignAttribute()447 bool InputType::shouldRespectAlignAttribute()
448 {
449 return false;
450 }
451
canChangeFromAnotherType() const452 bool InputType::canChangeFromAnotherType() const
453 {
454 return true;
455 }
456
minOrMaxAttributeChanged()457 void InputType::minOrMaxAttributeChanged()
458 {
459 }
460
canBeSuccessfulSubmitButton()461 bool InputType::canBeSuccessfulSubmitButton()
462 {
463 return false;
464 }
465
rendererIsNeeded()466 bool InputType::rendererIsNeeded()
467 {
468 return true;
469 }
470
files()471 FileList* InputType::files()
472 {
473 return 0;
474 }
475
getTypeSpecificValue(String &)476 bool InputType::getTypeSpecificValue(String&)
477 {
478 return false;
479 }
480
fallbackValue()481 String InputType::fallbackValue()
482 {
483 return String();
484 }
485
defaultValue()486 String InputType::defaultValue()
487 {
488 return String();
489 }
490
canSetSuggestedValue()491 bool InputType::canSetSuggestedValue()
492 {
493 return false;
494 }
495
shouldSendChangeEventAfterCheckedChanged()496 bool InputType::shouldSendChangeEventAfterCheckedChanged()
497 {
498 return true;
499 }
500
storesValueSeparateFromAttribute()501 bool InputType::storesValueSeparateFromAttribute()
502 {
503 return true;
504 }
505
canSetValue(const String &)506 bool InputType::canSetValue(const String&)
507 {
508 return true;
509 }
510
willDispatchClick()511 PassOwnPtr<ClickHandlingState> InputType::willDispatchClick()
512 {
513 return PassOwnPtr<ClickHandlingState>();
514 }
515
didDispatchClick(Event *,const ClickHandlingState &)516 void InputType::didDispatchClick(Event*, const ClickHandlingState&)
517 {
518 }
519
visibleValue() const520 String InputType::visibleValue() const
521 {
522 return element()->value();
523 }
524
convertFromVisibleValue(const String & visibleValue) const525 String InputType::convertFromVisibleValue(const String& visibleValue) const
526 {
527 return visibleValue;
528 }
529
isAcceptableValue(const String &)530 bool InputType::isAcceptableValue(const String&)
531 {
532 return true;
533 }
534
sanitizeValue(const String & proposedValue)535 String InputType::sanitizeValue(const String& proposedValue)
536 {
537 return proposedValue;
538 }
539
hasUnacceptableValue()540 bool InputType::hasUnacceptableValue()
541 {
542 return false;
543 }
544
setFileList(const Vector<String> &)545 void InputType::setFileList(const Vector<String>&)
546 {
547 ASSERT_NOT_REACHED();
548 }
549
shouldResetOnDocumentActivation()550 bool InputType::shouldResetOnDocumentActivation()
551 {
552 return false;
553 }
554
shouldRespectListAttribute()555 bool InputType::shouldRespectListAttribute()
556 {
557 return false;
558 }
559
shouldRespectSpeechAttribute()560 bool InputType::shouldRespectSpeechAttribute()
561 {
562 return false;
563 }
564
isTextButton() const565 bool InputType::isTextButton() const
566 {
567 return false;
568 }
569
isRadioButton() const570 bool InputType::isRadioButton() const
571 {
572 return false;
573 }
574
isSearchField() const575 bool InputType::isSearchField() const
576 {
577 return false;
578 }
579
isHiddenType() const580 bool InputType::isHiddenType() const
581 {
582 return false;
583 }
584
isPasswordField() const585 bool InputType::isPasswordField() const
586 {
587 return false;
588 }
589
isCheckbox() const590 bool InputType::isCheckbox() const
591 {
592 return false;
593 }
594
isEmailField() const595 bool InputType::isEmailField() const
596 {
597 return false;
598 }
599
isFileUpload() const600 bool InputType::isFileUpload() const
601 {
602 return false;
603 }
604
isImageButton() const605 bool InputType::isImageButton() const
606 {
607 return false;
608 }
609
isNumberField() const610 bool InputType::isNumberField() const
611 {
612 return false;
613 }
614
isSubmitButton() const615 bool InputType::isSubmitButton() const
616 {
617 return false;
618 }
619
isTelephoneField() const620 bool InputType::isTelephoneField() const
621 {
622 return false;
623 }
624
isURLField() const625 bool InputType::isURLField() const
626 {
627 return false;
628 }
629
isEnumeratable()630 bool InputType::isEnumeratable()
631 {
632 return true;
633 }
634
isCheckable()635 bool InputType::isCheckable()
636 {
637 return false;
638 }
639
hasSpinButton()640 bool InputType::hasSpinButton()
641 {
642 return false;
643 }
644
shouldRespectHeightAndWidthAttributes()645 bool InputType::shouldRespectHeightAndWidthAttributes()
646 {
647 return false;
648 }
649
650 namespace InputTypeNames {
651
652 // The type names must be lowercased because they will be the return values of
653 // input.type and input.type must be lowercase according to DOM Level 2.
654
button()655 const AtomicString& button()
656 {
657 DEFINE_STATIC_LOCAL(AtomicString, name, ("button"));
658 return name;
659 }
660
checkbox()661 const AtomicString& checkbox()
662 {
663 DEFINE_STATIC_LOCAL(AtomicString, name, ("checkbox"));
664 return name;
665 }
666
color()667 const AtomicString& color()
668 {
669 DEFINE_STATIC_LOCAL(AtomicString, name, ("color"));
670 return name;
671 }
672
date()673 const AtomicString& date()
674 {
675 DEFINE_STATIC_LOCAL(AtomicString, name, ("date"));
676 return name;
677 }
678
datetime()679 const AtomicString& datetime()
680 {
681 DEFINE_STATIC_LOCAL(AtomicString, name, ("datetime"));
682 return name;
683 }
684
datetimelocal()685 const AtomicString& datetimelocal()
686 {
687 DEFINE_STATIC_LOCAL(AtomicString, name, ("datetime-local"));
688 return name;
689 }
690
email()691 const AtomicString& email()
692 {
693 DEFINE_STATIC_LOCAL(AtomicString, name, ("email"));
694 return name;
695 }
696
file()697 const AtomicString& file()
698 {
699 DEFINE_STATIC_LOCAL(AtomicString, name, ("file"));
700 return name;
701 }
702
hidden()703 const AtomicString& hidden()
704 {
705 DEFINE_STATIC_LOCAL(AtomicString, name, ("hidden"));
706 return name;
707 }
708
image()709 const AtomicString& image()
710 {
711 DEFINE_STATIC_LOCAL(AtomicString, name, ("image"));
712 return name;
713 }
714
isindex()715 const AtomicString& isindex()
716 {
717 DEFINE_STATIC_LOCAL(AtomicString, name, ("khtml_isindex"));
718 return name;
719 }
720
month()721 const AtomicString& month()
722 {
723 DEFINE_STATIC_LOCAL(AtomicString, name, ("month"));
724 return name;
725 }
726
number()727 const AtomicString& number()
728 {
729 DEFINE_STATIC_LOCAL(AtomicString, name, ("number"));
730 return name;
731 }
732
password()733 const AtomicString& password()
734 {
735 DEFINE_STATIC_LOCAL(AtomicString, name, ("password"));
736 return name;
737 }
738
radio()739 const AtomicString& radio()
740 {
741 DEFINE_STATIC_LOCAL(AtomicString, name, ("radio"));
742 return name;
743 }
744
range()745 const AtomicString& range()
746 {
747 DEFINE_STATIC_LOCAL(AtomicString, name, ("range"));
748 return name;
749 }
750
reset()751 const AtomicString& reset()
752 {
753 DEFINE_STATIC_LOCAL(AtomicString, name, ("reset"));
754 return name;
755 }
756
search()757 const AtomicString& search()
758 {
759 DEFINE_STATIC_LOCAL(AtomicString, name, ("search"));
760 return name;
761 }
762
submit()763 const AtomicString& submit()
764 {
765 DEFINE_STATIC_LOCAL(AtomicString, name, ("submit"));
766 return name;
767 }
768
telephone()769 const AtomicString& telephone()
770 {
771 DEFINE_STATIC_LOCAL(AtomicString, name, ("tel"));
772 return name;
773 }
774
text()775 const AtomicString& text()
776 {
777 DEFINE_STATIC_LOCAL(AtomicString, name, ("text"));
778 return name;
779 }
780
time()781 const AtomicString& time()
782 {
783 DEFINE_STATIC_LOCAL(AtomicString, name, ("time"));
784 return name;
785 }
786
url()787 const AtomicString& url()
788 {
789 DEFINE_STATIC_LOCAL(AtomicString, name, ("url"));
790 return name;
791 }
792
week()793 const AtomicString& week()
794 {
795 DEFINE_STATIC_LOCAL(AtomicString, name, ("week"));
796 return name;
797 }
798
799 } // namespace WebCore::InputTypeNames
800
801 } // namespace WebCore
802