Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / html / HTMLFormControlElement.cpp
index 6217fbd..00ea1f0 100644 (file)
@@ -39,6 +39,7 @@
 #include "RenderBox.h"
 #include "RenderTheme.h"
 #include "ValidationMessage.h"
+#include <wtf/NeverDestroyed.h>
 #include <wtf/Ref.h>
 #include <wtf/Vector.h>
 
@@ -48,6 +49,7 @@ using namespace HTMLNames;
 
 HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
     : LabelableElement(tagName, document)
+    , FormAssociatedElement(form)
     , m_disabled(false)
     , m_isReadOnly(false)
     , m_isRequired(false)
@@ -60,7 +62,6 @@ HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Doc
     , m_wasChangedSinceLastFormControlChangeEvent(false)
     , m_hasAutofocused(false)
 {
-    setForm(form);
     setHasCustomStyleResolveCallbacks();
 }
 
@@ -532,7 +533,7 @@ bool HTMLFormControlElement::validationMessageShadowTreeContains(const Node& nod
 
 void HTMLFormControlElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
 {
-    HTMLElement::dispatchBlurEvent(WTF::move(newFocusedElement));
+    HTMLElement::dispatchBlurEvent(WTFMove(newFocusedElement));
     hideVisibleValidationMessage();
 }
 
@@ -594,4 +595,163 @@ HTMLFormControlElement* HTMLFormControlElement::enclosingFormControlElement(Node
     return nullptr;
 }
 
+static inline bool isContactToken(const AtomicString& token)
+{
+    return token == "home" || token == "work" || token == "mobile" || token == "fax" || token == "pager";
+}
+
+enum class AutofillCategory {
+    Invalid,
+    Off,
+    Automatic,
+    Normal,
+    Contact,
+};
+
+static inline AutofillCategory categoryForAutofillFieldToken(const AtomicString& token)
+{
+    static NeverDestroyed<HashMap<AtomicString, AutofillCategory>> map;
+    if (map.get().isEmpty()) {
+        map.get().add(AtomicString("off", AtomicString::ConstructFromLiteral), AutofillCategory::Off);
+        map.get().add(AtomicString("on", AtomicString::ConstructFromLiteral), AutofillCategory::Automatic);
+
+        map.get().add(AtomicString("name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("honorific-prefix", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("given-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("additional-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("family-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("honorific-suffix", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("nickname", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("username", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("new-password", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("current-password", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("organization-title", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("organization", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("street-address", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-line1", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-line2", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-line3", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-level4", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-level3", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-level2", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("address-level1", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("country", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("country-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("postal-code", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-given-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-additional-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-family-name", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-number", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-exp", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-exp-month", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-exp-year", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-csc", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("cc-type", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("transaction-currency", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("transaction-amount", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("language", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("bday", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("bday-day", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("bday-month", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("bday-year", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("sex", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("url", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+        map.get().add(AtomicString("photo", AtomicString::ConstructFromLiteral), AutofillCategory::Normal);
+
+        map.get().add(AtomicString("tel", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-country-code", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-national", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-area-code", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-local", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-local-prefix", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-local-suffix", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("tel-extension", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("email", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+        map.get().add(AtomicString("impp", AtomicString::ConstructFromLiteral), AutofillCategory::Contact);
+    }
+
+    return map.get().get(token);
+}
+
+static inline unsigned maxTokensForAutofillFieldCategory(AutofillCategory category)
+{
+    switch (category) {
+    case AutofillCategory::Invalid:
+        return 0;
+
+    case AutofillCategory::Automatic:
+    case AutofillCategory::Off:
+        return 1;
+
+    case AutofillCategory::Normal:
+        return 3;
+
+    case AutofillCategory::Contact:
+        return 4;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+// https://html.spec.whatwg.org/multipage/forms.html#processing-model-3
+String HTMLFormControlElement::autocomplete() const
+{
+    const AtomicString& attributeValue = fastGetAttribute(autocompleteAttr);
+    SpaceSplitString tokens(attributeValue, true);
+    if (tokens.isEmpty())
+        return String();
+
+    size_t currentTokenIndex = tokens.size() - 1;
+    const auto& fieldToken = tokens[currentTokenIndex];
+    auto category = categoryForAutofillFieldToken(fieldToken);
+    if (category == AutofillCategory::Invalid)
+        return String();
+
+    if (tokens.size() > maxTokensForAutofillFieldCategory(category))
+        return String();
+
+    bool wearingAutofillAnchorMantle = is<HTMLInputElement>(*this) && downcast<HTMLInputElement>(this)->isInputTypeHidden();
+    if ((category == AutofillCategory::Off || category == AutofillCategory::Automatic) && wearingAutofillAnchorMantle)
+        return String();
+
+    if (category == AutofillCategory::Off)
+        return ASCIILiteral("off");
+
+    if (category == AutofillCategory::Automatic)
+        return ASCIILiteral("on");
+
+    String result = fieldToken;
+    if (!currentTokenIndex--)
+        return result;
+
+    const auto& contactToken = tokens[currentTokenIndex];
+    if (category == AutofillCategory::Contact && isContactToken(contactToken)) {
+        result = contactToken + " " + result;
+        if (!currentTokenIndex--)
+            return result;
+    }
+
+    const auto& modeToken = tokens[currentTokenIndex];
+    if (modeToken == "shipping" || modeToken == "billing") {
+        result = modeToken + " " + result;
+        if (!currentTokenIndex--)
+            return result;
+    }
+
+    if (currentTokenIndex)
+        return String();
+
+    const auto& sectionToken = tokens[currentTokenIndex];
+    if (!sectionToken.startsWith("section-"))
+        return String();
+
+    return sectionToken + " " + result;
+}
+
+void HTMLFormControlElement::setAutocomplete(const String& value)
+{
+    setAttribute(autocompleteAttr, value);
+}
+
 } // namespace Webcore