OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All |
7 * rights reserved. | 7 * rights reserved. |
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
9 * (http://www.torchmobile.com/) | 9 * (http://www.torchmobile.com/) |
10 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. | 10 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 // rule (d) above | 368 // rule (d) above |
369 WTF::Unicode::CharDecompositionType decomp_type = | 369 WTF::Unicode::CharDecompositionType decomp_type = |
370 WTF::Unicode::DecompositionType(c); | 370 WTF::Unicode::DecompositionType(c); |
371 if (decomp_type == WTF::Unicode::kDecompositionFont || | 371 if (decomp_type == WTF::Unicode::kDecompositionFont || |
372 decomp_type == WTF::Unicode::kDecompositionCompat) | 372 decomp_type == WTF::Unicode::kDecompositionCompat) |
373 return false; | 373 return false; |
374 | 374 |
375 return true; | 375 return true; |
376 } | 376 } |
377 | 377 |
| 378 // Tests whether |name| is something the HTML parser would accept as a |
| 379 // tag name. |
| 380 template <typename CharType> |
| 381 static inline bool IsValidElementNamePerHTMLParser(const CharType* characters, |
| 382 unsigned length) { |
| 383 CharType c = characters[0] | 0x20; |
| 384 if (!('a' <= c && c < 'z')) |
| 385 return false; |
| 386 |
| 387 for (unsigned i = 1; i < length; ++i) { |
| 388 c = characters[i]; |
| 389 if (c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == ' ' || |
| 390 c == '/' || c == '>') |
| 391 return false; |
| 392 } |
| 393 |
| 394 return true; |
| 395 } |
| 396 |
| 397 static bool IsValidElementNamePerHTMLParser(const String& name) { |
| 398 unsigned length = name.length(); |
| 399 if (!length) |
| 400 return false; |
| 401 |
| 402 if (name.Is8Bit()) { |
| 403 const LChar* characters = name.Characters8(); |
| 404 return IsValidElementNamePerHTMLParser(characters, length); |
| 405 } |
| 406 const UChar* characters = name.Characters16(); |
| 407 return IsValidElementNamePerHTMLParser(characters, length); |
| 408 } |
| 409 |
| 410 // Tests whether |name| is a valid name per DOM spec. Also checks |
| 411 // whether the HTML parser would accept this element name and counts |
| 412 // cases of mismatches. |
| 413 static bool IsValidElementName(const LocalDOMWindow* window, |
| 414 const String& name) { |
| 415 bool is_valid_dom_name = Document::IsValidName(name); |
| 416 bool is_valid_html_name = IsValidElementNamePerHTMLParser(name); |
| 417 if (UNLIKELY(is_valid_html_name != is_valid_dom_name && window)) { |
| 418 UseCounter::Count(window->GetFrame(), |
| 419 is_valid_dom_name |
| 420 ? UseCounter::kElementNameDOMValidHTMLParserInvalid |
| 421 : UseCounter::kElementNameDOMInvalidHTMLParserValid); |
| 422 } |
| 423 return is_valid_dom_name; |
| 424 } |
| 425 |
378 static bool AcceptsEditingFocus(const Element& element) { | 426 static bool AcceptsEditingFocus(const Element& element) { |
379 DCHECK(HasEditableStyle(element)); | 427 DCHECK(HasEditableStyle(element)); |
380 | 428 |
381 return element.GetDocument().GetFrame() && RootEditableElement(element); | 429 return element.GetDocument().GetFrame() && RootEditableElement(element); |
382 } | 430 } |
383 | 431 |
384 uint64_t Document::global_tree_version_ = 0; | 432 uint64_t Document::global_tree_version_ = 0; |
385 | 433 |
386 static bool g_threaded_parsing_enabled_for_testing = true; | 434 static bool g_threaded_parsing_enabled_for_testing = true; |
387 | 435 |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 | 735 |
688 bool Document::IsInMainFrame() const { | 736 bool Document::IsInMainFrame() const { |
689 return GetFrame() && GetFrame()->IsMainFrame(); | 737 return GetFrame() && GetFrame()->IsMainFrame(); |
690 } | 738 } |
691 | 739 |
692 AtomicString Document::ConvertLocalName(const AtomicString& name) { | 740 AtomicString Document::ConvertLocalName(const AtomicString& name) { |
693 return IsHTMLDocument() ? name.LowerASCII() : name; | 741 return IsHTMLDocument() ? name.LowerASCII() : name; |
694 } | 742 } |
695 | 743 |
696 // https://dom.spec.whatwg.org/#dom-document-createelement | 744 // https://dom.spec.whatwg.org/#dom-document-createelement |
697 Element* Document::createElement(const AtomicString& name, | 745 Element* Document::createElement(const LocalDOMWindow* window, |
| 746 const AtomicString& name, |
698 ExceptionState& exception_state) { | 747 ExceptionState& exception_state) { |
699 if (!IsValidName(name)) { | 748 if (!IsValidElementName(window, name)) { |
700 exception_state.ThrowDOMException( | 749 exception_state.ThrowDOMException( |
701 kInvalidCharacterError, | 750 kInvalidCharacterError, |
702 "The tag name provided ('" + name + "') is not a valid name."); | 751 "The tag name provided ('" + name + "') is not a valid name."); |
703 return nullptr; | 752 return nullptr; |
704 } | 753 } |
705 | 754 |
706 if (IsXHTMLDocument() || IsHTMLDocument()) { | 755 if (IsXHTMLDocument() || IsHTMLDocument()) { |
707 // 2. If the context object is an HTML document, let localName be | 756 // 2. If the context object is an HTML document, let localName be |
708 // converted to ASCII lowercase. | 757 // converted to ASCII lowercase. |
709 AtomicString local_name = ConvertLocalName(name); | 758 AtomicString local_name = ConvertLocalName(name); |
(...skipping 29 matching lines...) Expand all Loading... |
739 return g_empty_string; | 788 return g_empty_string; |
740 | 789 |
741 if (impl.hasIs()) | 790 if (impl.hasIs()) |
742 return impl.is(); | 791 return impl.is(); |
743 } | 792 } |
744 | 793 |
745 return g_empty_string; | 794 return g_empty_string; |
746 } | 795 } |
747 | 796 |
748 // https://dom.spec.whatwg.org/#dom-document-createelement | 797 // https://dom.spec.whatwg.org/#dom-document-createelement |
749 Element* Document::createElement(const AtomicString& local_name, | 798 Element* Document::createElement(const LocalDOMWindow* window, |
| 799 const AtomicString& local_name, |
750 const StringOrDictionary& string_or_options, | 800 const StringOrDictionary& string_or_options, |
751 ExceptionState& exception_state) { | 801 ExceptionState& exception_state) { |
752 // 1. If localName does not match Name production, throw InvalidCharacterError | 802 // 1. If localName does not match Name production, throw InvalidCharacterError |
753 if (!IsValidName(local_name)) { | 803 if (!IsValidElementName(window, local_name)) { |
754 exception_state.ThrowDOMException( | 804 exception_state.ThrowDOMException( |
755 kInvalidCharacterError, | 805 kInvalidCharacterError, |
756 "The tag name provided ('" + local_name + "') is not a valid name."); | 806 "The tag name provided ('" + local_name + "') is not a valid name."); |
757 return nullptr; | 807 return nullptr; |
758 } | 808 } |
759 | 809 |
760 // 2. localName converted to ASCII lowercase | 810 // 2. localName converted to ASCII lowercase |
761 const AtomicString& converted_local_name = ConvertLocalName(local_name); | 811 const AtomicString& converted_local_name = ConvertLocalName(local_name); |
762 | 812 |
763 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); | 813 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 | 849 |
800 if (definition) { | 850 if (definition) { |
801 element = CustomElement::CreateCustomElementSync( | 851 element = CustomElement::CreateCustomElementSync( |
802 *this, converted_local_name, definition); | 852 *this, converted_local_name, definition); |
803 } else if (V0CustomElement::IsValidName(local_name) && | 853 } else if (V0CustomElement::IsValidName(local_name) && |
804 RegistrationContext()) { | 854 RegistrationContext()) { |
805 element = RegistrationContext()->CreateCustomTagElement( | 855 element = RegistrationContext()->CreateCustomTagElement( |
806 *this, | 856 *this, |
807 QualifiedName(g_null_atom, converted_local_name, xhtmlNamespaceURI)); | 857 QualifiedName(g_null_atom, converted_local_name, xhtmlNamespaceURI)); |
808 } else { | 858 } else { |
809 element = createElement(local_name, exception_state); | 859 element = createElement(window, local_name, exception_state); |
810 if (exception_state.HadException()) | 860 if (exception_state.HadException()) |
811 return nullptr; | 861 return nullptr; |
812 } | 862 } |
813 | 863 |
814 // 8. If 'is' is non-null, set 'is' attribute | 864 // 8. If 'is' is non-null, set 'is' attribute |
815 if (!is.IsEmpty()) { | 865 if (!is.IsEmpty()) { |
816 if (string_or_options.isString()) { | 866 if (string_or_options.isString()) { |
817 V0CustomElementRegistrationContext::SetIsAttributeAndTypeExtension( | 867 V0CustomElementRegistrationContext::SetIsAttributeAndTypeExtension( |
818 element, is); | 868 element, is); |
819 } else if (string_or_options.isDictionary()) { | 869 } else if (string_or_options.isDictionary()) { |
(...skipping 19 matching lines...) Expand all Loading... |
839 kNamespaceError, | 889 kNamespaceError, |
840 "The namespace URI provided ('" + namespace_uri + | 890 "The namespace URI provided ('" + namespace_uri + |
841 "') is not valid for the qualified name provided ('" + | 891 "') is not valid for the qualified name provided ('" + |
842 qualified_name + "')."); | 892 qualified_name + "')."); |
843 return QualifiedName::Null(); | 893 return QualifiedName::Null(); |
844 } | 894 } |
845 | 895 |
846 return q_name; | 896 return q_name; |
847 } | 897 } |
848 | 898 |
849 Element* Document::createElementNS(const AtomicString& namespace_uri, | 899 Element* Document::createElementNS(const LocalDOMWindow* window, |
| 900 const AtomicString& namespace_uri, |
850 const AtomicString& qualified_name, | 901 const AtomicString& qualified_name, |
851 ExceptionState& exception_state) { | 902 ExceptionState& exception_state) { |
852 QualifiedName q_name( | 903 QualifiedName q_name( |
853 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); | 904 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); |
854 if (q_name == QualifiedName::Null()) | 905 if (q_name == QualifiedName::Null()) |
855 return nullptr; | 906 return nullptr; |
856 | 907 |
857 if (CustomElement::ShouldCreateCustomElement(q_name)) | 908 if (CustomElement::ShouldCreateCustomElement(q_name)) |
858 return CustomElement::CreateCustomElementSync(*this, q_name); | 909 return CustomElement::CreateCustomElementSync(*this, q_name); |
859 return createElement(q_name, kCreatedByCreateElement); | 910 return createElement(q_name, kCreatedByCreateElement); |
860 } | 911 } |
861 | 912 |
862 // https://dom.spec.whatwg.org/#internal-createelementns-steps | 913 // https://dom.spec.whatwg.org/#internal-createelementns-steps |
863 Element* Document::createElementNS(const AtomicString& namespace_uri, | 914 Element* Document::createElementNS(const LocalDOMWindow* window, |
| 915 const AtomicString& namespace_uri, |
864 const AtomicString& qualified_name, | 916 const AtomicString& qualified_name, |
865 const StringOrDictionary& string_or_options, | 917 const StringOrDictionary& string_or_options, |
866 ExceptionState& exception_state) { | 918 ExceptionState& exception_state) { |
867 // 1. Validate and extract | 919 // 1. Validate and extract |
868 QualifiedName q_name( | 920 QualifiedName q_name( |
869 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); | 921 CreateQualifiedName(namespace_uri, qualified_name, exception_state)); |
870 if (q_name == QualifiedName::Null()) | 922 if (q_name == QualifiedName::Null()) |
871 return nullptr; | 923 return nullptr; |
872 | 924 |
873 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); | 925 bool is_v1 = string_or_options.isDictionary() || !RegistrationContext(); |
874 bool create_v1_builtin = | 926 bool create_v1_builtin = |
875 string_or_options.isDictionary() && | 927 string_or_options.isDictionary() && |
876 RuntimeEnabledFeatures::customElementsBuiltinEnabled(); | 928 RuntimeEnabledFeatures::customElementsBuiltinEnabled(); |
877 bool should_create_builtin = | 929 bool should_create_builtin = |
878 create_v1_builtin || string_or_options.isString(); | 930 create_v1_builtin || string_or_options.isString(); |
879 | 931 |
880 // 2. | 932 // 2. |
881 const AtomicString& is = | 933 const AtomicString& is = |
882 AtomicString(GetTypeExtension(this, string_or_options, exception_state)); | 934 AtomicString(GetTypeExtension(this, string_or_options, exception_state)); |
883 const AtomicString& name = should_create_builtin ? is : qualified_name; | 935 const AtomicString& name = should_create_builtin ? is : qualified_name; |
884 | 936 |
885 if (!IsValidName(qualified_name)) { | 937 if (!IsValidElementName(window, qualified_name)) { |
886 exception_state.ThrowDOMException( | 938 exception_state.ThrowDOMException( |
887 kInvalidCharacterError, "The tag name provided ('" + qualified_name + | 939 kInvalidCharacterError, "The tag name provided ('" + qualified_name + |
888 "') is not a valid name."); | 940 "') is not a valid name."); |
889 return nullptr; | 941 return nullptr; |
890 } | 942 } |
891 | 943 |
892 // 3. Let definition be result of lookup up custom element definition | 944 // 3. Let definition be result of lookup up custom element definition |
893 CustomElementDefinition* definition = nullptr; | 945 CustomElementDefinition* definition = nullptr; |
894 if (is_v1) { | 946 if (is_v1) { |
895 const CustomElementDescriptor desc = | 947 const CustomElementDescriptor desc = |
(...skipping 5795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6691 } | 6743 } |
6692 | 6744 |
6693 void showLiveDocumentInstances() { | 6745 void showLiveDocumentInstances() { |
6694 WeakDocumentSet& set = liveDocumentSet(); | 6746 WeakDocumentSet& set = liveDocumentSet(); |
6695 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); | 6747 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); |
6696 for (blink::Document* document : set) | 6748 for (blink::Document* document : set) |
6697 fprintf(stderr, "- Document %p URL: %s\n", document, | 6749 fprintf(stderr, "- Document %p URL: %s\n", document, |
6698 document->Url().GetString().Utf8().data()); | 6750 document->Url().GetString().Utf8().data()); |
6699 } | 6751 } |
6700 #endif | 6752 #endif |
OLD | NEW |