1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * (C) 2006 Alexey Proskuryakov (ap (at) nypop.com) 7 * Copyright (C) 2007 Samuel Weinig (sam (at) 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 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 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 116 PassOwnPtr<InputType> InputType::createText(HTMLInputElement* element) 117 { 118 return TextInputType::create(element); 119 } 120 121 InputType::~InputType() 122 { 123 } 124 125 bool InputType::isTextField() const 126 { 127 return false; 128 } 129 130 bool InputType::isTextType() const 131 { 132 return false; 133 } 134 135 bool InputType::isRangeControl() const 136 { 137 return false; 138 } 139 140 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 149 void InputType::restoreFormControlState(const String& state) const 150 { 151 element()->setValue(state); 152 } 153 154 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 160 bool InputType::appendFormData(FormDataList& encoding, bool) const 161 { 162 // Always successful. 163 encoding.appendData(element()->name(), element()->value()); 164 return true; 165 } 166 167 double InputType::valueAsDate() const 168 { 169 return DateComponents::invalidMilliseconds(); 170 } 171 172 void InputType::setValueAsDate(double, ExceptionCode& ec) const 173 { 174 ec = INVALID_STATE_ERR; 175 } 176 177 double InputType::valueAsNumber() const 178 { 179 return numeric_limits<double>::quiet_NaN(); 180 } 181 182 void InputType::setValueAsNumber(double, ExceptionCode& ec) const 183 { 184 ec = INVALID_STATE_ERR; 185 } 186 187 bool InputType::supportsValidation() const 188 { 189 return true; 190 } 191 192 bool InputType::typeMismatchFor(const String&) const 193 { 194 return false; 195 } 196 197 bool InputType::typeMismatch() const 198 { 199 return false; 200 } 201 202 bool InputType::supportsRequired() const 203 { 204 // Almost all validatable types support @required. 205 return supportsValidation(); 206 } 207 208 bool InputType::valueMissing(const String&) const 209 { 210 return false; 211 } 212 213 bool InputType::patternMismatch(const String&) const 214 { 215 return false; 216 } 217 218 bool InputType::rangeUnderflow(const String&) const 219 { 220 return false; 221 } 222 223 bool InputType::rangeOverflow(const String&) const 224 { 225 return false; 226 } 227 228 bool InputType::supportsRangeLimitation() const 229 { 230 return false; 231 } 232 233 double InputType::defaultValueForStepUp() const 234 { 235 return 0; 236 } 237 238 double InputType::minimum() const 239 { 240 ASSERT_NOT_REACHED(); 241 return 0; 242 } 243 244 double InputType::maximum() const 245 { 246 ASSERT_NOT_REACHED(); 247 return 0; 248 } 249 250 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 257 double InputType::stepBase() const 258 { 259 ASSERT_NOT_REACHED(); 260 return 0; 261 } 262 263 double InputType::stepBaseWithDecimalPlaces(unsigned* decimalPlaces) const 264 { 265 if (decimalPlaces) 266 *decimalPlaces = 0; 267 return stepBase(); 268 } 269 270 double InputType::defaultStep() const 271 { 272 return numeric_limits<double>::quiet_NaN(); 273 } 274 275 double InputType::stepScaleFactor() const 276 { 277 return numeric_limits<double>::quiet_NaN(); 278 } 279 280 bool InputType::parsedStepValueShouldBeInteger() const 281 { 282 return false; 283 } 284 285 bool InputType::scaledStepValueShouldBeInteger() const 286 { 287 return false; 288 } 289 290 double InputType::acceptableError(double) const 291 { 292 return 0; 293 } 294 295 String InputType::typeMismatchText() const 296 { 297 return validationMessageTypeMismatchText(); 298 } 299 300 String InputType::valueMissingText() const 301 { 302 return validationMessageValueMissingText(); 303 } 304 305 void InputType::handleClickEvent(MouseEvent*) 306 { 307 } 308 309 void InputType::handleMouseDownEvent(MouseEvent*) 310 { 311 } 312 313 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS) 314 void InputType::handleTouchStartEvent(TouchEvent*) 315 { 316 } 317 #endif 318 319 void InputType::handleDOMActivateEvent(Event*) 320 { 321 } 322 323 void InputType::handleKeydownEvent(KeyboardEvent*) 324 { 325 } 326 327 void InputType::handleKeypressEvent(KeyboardEvent*) 328 { 329 } 330 331 void InputType::handleKeyupEvent(KeyboardEvent*) 332 { 333 } 334 335 void InputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event) 336 { 337 element()->handleBeforeTextInsertedEvent(event); 338 } 339 340 void InputType::handleWheelEvent(WheelEvent*) 341 { 342 } 343 344 void InputType::forwardEvent(Event*) 345 { 346 } 347 348 bool InputType::shouldSubmitImplicitly(Event* event) 349 { 350 return event->isKeyboardEvent() && event->type() == eventNames().keypressEvent && static_cast<KeyboardEvent*>(event)->charCode() == '\r'; 351 } 352 353 PassRefPtr<HTMLFormElement> InputType::formForSubmission() const 354 { 355 return element()->form(); 356 } 357 358 RenderObject* InputType::createRenderer(RenderArena*, RenderStyle* style) const 359 { 360 return RenderObject::createObject(element(), style); 361 } 362 363 void InputType::createShadowSubtree() 364 { 365 } 366 367 void InputType::destroyShadowSubtree() 368 { 369 element()->removeShadowRoot(); 370 } 371 372 double InputType::parseToDouble(const String&, double defaultValue) const 373 { 374 return defaultValue; 375 } 376 377 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 384 bool InputType::parseToDateComponents(const String&, DateComponents*) const 385 { 386 ASSERT_NOT_REACHED(); 387 return false; 388 } 389 390 String InputType::serialize(double) const 391 { 392 ASSERT_NOT_REACHED(); 393 return String(); 394 } 395 396 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const 397 { 398 if (element()->active()) 399 element()->dispatchSimulatedClick(event); 400 event->setDefaultHandled(); 401 } 402 403 bool InputType::canSetStringValue() const 404 { 405 return true; 406 } 407 408 bool InputType::isKeyboardFocusable() const 409 { 410 return true; 411 } 412 413 bool InputType::shouldUseInputMethod() const 414 { 415 return false; 416 } 417 418 void InputType::handleBlurEvent() 419 { 420 } 421 422 void InputType::accessKeyAction(bool) 423 { 424 element()->focus(false); 425 } 426 427 void InputType::attach() 428 { 429 } 430 431 void InputType::altAttributeChanged() 432 { 433 } 434 435 void InputType::srcAttributeChanged() 436 { 437 } 438 439 void InputType::valueChanged() 440 { 441 } 442 443 void InputType::willMoveToNewOwnerDocument() 444 { 445 } 446 447 bool InputType::shouldRespectAlignAttribute() 448 { 449 return false; 450 } 451 452 bool InputType::canChangeFromAnotherType() const 453 { 454 return true; 455 } 456 457 void InputType::minOrMaxAttributeChanged() 458 { 459 } 460 461 bool InputType::canBeSuccessfulSubmitButton() 462 { 463 return false; 464 } 465 466 bool InputType::rendererIsNeeded() 467 { 468 return true; 469 } 470 471 FileList* InputType::files() 472 { 473 return 0; 474 } 475 476 bool InputType::getTypeSpecificValue(String&) 477 { 478 return false; 479 } 480 481 String InputType::fallbackValue() 482 { 483 return String(); 484 } 485 486 String InputType::defaultValue() 487 { 488 return String(); 489 } 490 491 bool InputType::canSetSuggestedValue() 492 { 493 return false; 494 } 495 496 bool InputType::shouldSendChangeEventAfterCheckedChanged() 497 { 498 return true; 499 } 500 501 bool InputType::storesValueSeparateFromAttribute() 502 { 503 return true; 504 } 505 506 bool InputType::canSetValue(const String&) 507 { 508 return true; 509 } 510 511 PassOwnPtr<ClickHandlingState> InputType::willDispatchClick() 512 { 513 return PassOwnPtr<ClickHandlingState>(); 514 } 515 516 void InputType::didDispatchClick(Event*, const ClickHandlingState&) 517 { 518 } 519 520 String InputType::visibleValue() const 521 { 522 return element()->value(); 523 } 524 525 String InputType::convertFromVisibleValue(const String& visibleValue) const 526 { 527 return visibleValue; 528 } 529 530 bool InputType::isAcceptableValue(const String&) 531 { 532 return true; 533 } 534 535 String InputType::sanitizeValue(const String& proposedValue) 536 { 537 return proposedValue; 538 } 539 540 bool InputType::hasUnacceptableValue() 541 { 542 return false; 543 } 544 545 void InputType::setFileList(const Vector<String>&) 546 { 547 ASSERT_NOT_REACHED(); 548 } 549 550 bool InputType::shouldResetOnDocumentActivation() 551 { 552 return false; 553 } 554 555 bool InputType::shouldRespectListAttribute() 556 { 557 return false; 558 } 559 560 bool InputType::shouldRespectSpeechAttribute() 561 { 562 return false; 563 } 564 565 bool InputType::isTextButton() const 566 { 567 return false; 568 } 569 570 bool InputType::isRadioButton() const 571 { 572 return false; 573 } 574 575 bool InputType::isSearchField() const 576 { 577 return false; 578 } 579 580 bool InputType::isHiddenType() const 581 { 582 return false; 583 } 584 585 bool InputType::isPasswordField() const 586 { 587 return false; 588 } 589 590 bool InputType::isCheckbox() const 591 { 592 return false; 593 } 594 595 bool InputType::isEmailField() const 596 { 597 return false; 598 } 599 600 bool InputType::isFileUpload() const 601 { 602 return false; 603 } 604 605 bool InputType::isImageButton() const 606 { 607 return false; 608 } 609 610 bool InputType::isNumberField() const 611 { 612 return false; 613 } 614 615 bool InputType::isSubmitButton() const 616 { 617 return false; 618 } 619 620 bool InputType::isTelephoneField() const 621 { 622 return false; 623 } 624 625 bool InputType::isURLField() const 626 { 627 return false; 628 } 629 630 bool InputType::isEnumeratable() 631 { 632 return true; 633 } 634 635 bool InputType::isCheckable() 636 { 637 return false; 638 } 639 640 bool InputType::hasSpinButton() 641 { 642 return false; 643 } 644 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 655 const AtomicString& button() 656 { 657 DEFINE_STATIC_LOCAL(AtomicString, name, ("button")); 658 return name; 659 } 660 661 const AtomicString& checkbox() 662 { 663 DEFINE_STATIC_LOCAL(AtomicString, name, ("checkbox")); 664 return name; 665 } 666 667 const AtomicString& color() 668 { 669 DEFINE_STATIC_LOCAL(AtomicString, name, ("color")); 670 return name; 671 } 672 673 const AtomicString& date() 674 { 675 DEFINE_STATIC_LOCAL(AtomicString, name, ("date")); 676 return name; 677 } 678 679 const AtomicString& datetime() 680 { 681 DEFINE_STATIC_LOCAL(AtomicString, name, ("datetime")); 682 return name; 683 } 684 685 const AtomicString& datetimelocal() 686 { 687 DEFINE_STATIC_LOCAL(AtomicString, name, ("datetime-local")); 688 return name; 689 } 690 691 const AtomicString& email() 692 { 693 DEFINE_STATIC_LOCAL(AtomicString, name, ("email")); 694 return name; 695 } 696 697 const AtomicString& file() 698 { 699 DEFINE_STATIC_LOCAL(AtomicString, name, ("file")); 700 return name; 701 } 702 703 const AtomicString& hidden() 704 { 705 DEFINE_STATIC_LOCAL(AtomicString, name, ("hidden")); 706 return name; 707 } 708 709 const AtomicString& image() 710 { 711 DEFINE_STATIC_LOCAL(AtomicString, name, ("image")); 712 return name; 713 } 714 715 const AtomicString& isindex() 716 { 717 DEFINE_STATIC_LOCAL(AtomicString, name, ("khtml_isindex")); 718 return name; 719 } 720 721 const AtomicString& month() 722 { 723 DEFINE_STATIC_LOCAL(AtomicString, name, ("month")); 724 return name; 725 } 726 727 const AtomicString& number() 728 { 729 DEFINE_STATIC_LOCAL(AtomicString, name, ("number")); 730 return name; 731 } 732 733 const AtomicString& password() 734 { 735 DEFINE_STATIC_LOCAL(AtomicString, name, ("password")); 736 return name; 737 } 738 739 const AtomicString& radio() 740 { 741 DEFINE_STATIC_LOCAL(AtomicString, name, ("radio")); 742 return name; 743 } 744 745 const AtomicString& range() 746 { 747 DEFINE_STATIC_LOCAL(AtomicString, name, ("range")); 748 return name; 749 } 750 751 const AtomicString& reset() 752 { 753 DEFINE_STATIC_LOCAL(AtomicString, name, ("reset")); 754 return name; 755 } 756 757 const AtomicString& search() 758 { 759 DEFINE_STATIC_LOCAL(AtomicString, name, ("search")); 760 return name; 761 } 762 763 const AtomicString& submit() 764 { 765 DEFINE_STATIC_LOCAL(AtomicString, name, ("submit")); 766 return name; 767 } 768 769 const AtomicString& telephone() 770 { 771 DEFINE_STATIC_LOCAL(AtomicString, name, ("tel")); 772 return name; 773 } 774 775 const AtomicString& text() 776 { 777 DEFINE_STATIC_LOCAL(AtomicString, name, ("text")); 778 return name; 779 } 780 781 const AtomicString& time() 782 { 783 DEFINE_STATIC_LOCAL(AtomicString, name, ("time")); 784 return name; 785 } 786 787 const AtomicString& url() 788 { 789 DEFINE_STATIC_LOCAL(AtomicString, name, ("url")); 790 return name; 791 } 792 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