Use a 1-byte enum class for TextDirection
[WebKit-https.git] / Source / WebCore / html / shadow / TextControlInnerElements.cpp
index 05111d1..45c9d34 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2008, 2010, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,8 @@
 #include "config.h"
 #include "TextControlInnerElements.h"
 
+#include "CSSPrimitiveValue.h"
+#include "CSSToLengthConversionData.h"
 #include "Document.h"
 #include "EventNames.h"
 #include "Frame.h"
 #include "StyleResolver.h"
 #include "TextEvent.h"
 #include "TextEventInputType.h"
+#include <wtf/IsoMallocInlines.h>
 #include <wtf/Ref.h>
 
 namespace WebCore {
 
+WTF_MAKE_ISO_ALLOCATED_IMPL(TextControlInnerContainer);
+WTF_MAKE_ISO_ALLOCATED_IMPL(TextControlInnerElement);
+WTF_MAKE_ISO_ALLOCATED_IMPL(TextControlInnerTextElement);
+WTF_MAKE_ISO_ALLOCATED_IMPL(TextControlPlaceholderElement);
+WTF_MAKE_ISO_ALLOCATED_IMPL(SearchFieldResultsButtonElement);
+WTF_MAKE_ISO_ALLOCATED_IMPL(SearchFieldCancelButtonElement);
+
 using namespace HTMLNames;
 
 TextControlInnerContainer::TextControlInnerContainer(Document& document)
     : HTMLDivElement(divTag, document)
 {
+    setHasCustomStyleResolveCallbacks();
 }
 
 Ref<TextControlInnerContainer> TextControlInnerContainer::create(Document& document)
@@ -64,6 +75,22 @@ RenderPtr<RenderElement> TextControlInnerContainer::createElementRenderer(Render
     return createRenderer<RenderTextControlInnerContainer>(*this, WTFMove(style));
 }
 
+static inline bool isStrongPasswordTextField(const Element* element)
+{
+    return is<HTMLInputElement>(element) && downcast<HTMLInputElement>(element)->hasAutoFillStrongPasswordButton();
+}
+
+std::optional<ElementStyle> TextControlInnerContainer::resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle*)
+{
+    auto elementStyle = resolveStyle(&parentStyle);
+    if (isStrongPasswordTextField(shadowHost())) {
+        elementStyle.renderStyle->setFlexWrap(FlexWrap::Wrap);
+        elementStyle.renderStyle->setOverflowX(Overflow::Hidden);
+        elementStyle.renderStyle->setOverflowY(Overflow::Hidden);
+    }
+    return WTFMove(elementStyle);
+}
+
 TextControlInnerElement::TextControlInnerElement(Document& document)
     : HTMLDivElement(divTag, document)
 {
@@ -77,22 +104,33 @@ Ref<TextControlInnerElement> TextControlInnerElement::create(Document& document)
 
 std::optional<ElementStyle> TextControlInnerElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* shadowHostStyle)
 {
-    auto innerContainerStyle = RenderStyle::createPtr();
-    innerContainerStyle->inheritFrom(*shadowHostStyle);
-
-    innerContainerStyle->setFlexGrow(1);
-    // min-width: 0; is needed for correct shrinking.
-    innerContainerStyle->setMinWidth(Length(0, Fixed));
-    innerContainerStyle->setDisplay(BLOCK);
-    innerContainerStyle->setDirection(LTR);
-
-    // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable.
-    innerContainerStyle->setUserModify(READ_ONLY);
+    auto newStyle = RenderStyle::createPtr();
+    newStyle->inheritFrom(*shadowHostStyle);
+    newStyle->setFlexGrow(1);
+    newStyle->setMinWidth(Length { 0, Fixed }); // Needed for correct shrinking.
+    newStyle->setDisplay(DisplayType::Block);
+    newStyle->setDirection(TextDirection::LTR);
+    // We don't want the shadow DOM to be editable, so we set this block to read-only in case the input itself is editable.
+    newStyle->setUserModify(UserModify::ReadOnly);
+
+    if (isStrongPasswordTextField(shadowHost())) {
+        newStyle->setFlexShrink(0);
+        newStyle->setTextOverflow(TextOverflow::Clip);
+        newStyle->setOverflowX(Overflow::Hidden);
+        newStyle->setOverflowY(Overflow::Hidden);
+
+        // Set "flex-basis: 1em". Note that CSSPrimitiveValue::computeLengthInt() only needs the element's
+        // style to calculate em lengths. Since the element might not be in a document, just pass nullptr
+        // for the root element style and the render view.
+        RefPtr<CSSPrimitiveValue> emSize = CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_EMS);
+        int pixels = emSize->computeLength<int>(CSSToLengthConversionData { newStyle.get(), nullptr, nullptr, 1.0, false });
+        newStyle->setFlexBasis(Length { pixels, Fixed });
+    }
 
-    return ElementStyle(WTFMove(innerContainerStyle));
+    return ElementStyle { WTFMove(newStyle) };
 }
 
-// ---------------------------
+// MARK: TextControlInnerTextElement
 
 inline TextControlInnerTextElement::TextControlInnerTextElement(Document& document)
     : HTMLDivElement(divTag, document)
@@ -140,30 +178,35 @@ std::optional<ElementStyle> TextControlInnerTextElement::resolveCustomStyle(cons
     return ElementStyle(std::make_unique<RenderStyle>(WTFMove(style)));
 }
 
-// ----------------------------
+// MARK: TextControlPlaceholderElement
 
-TextControlPlaceholderElement::TextControlPlaceholderElement(Document& document)
+inline TextControlPlaceholderElement::TextControlPlaceholderElement(Document& document)
     : HTMLDivElement(divTag, document)
 {
     setPseudo(AtomicString("placeholder", AtomicString::ConstructFromLiteral));
     setHasCustomStyleResolveCallbacks();
 }
 
+Ref<TextControlPlaceholderElement> TextControlPlaceholderElement::create(Document& document)
+{
+    return adoptRef(*new TextControlPlaceholderElement(document));
+}
+
 std::optional<ElementStyle> TextControlPlaceholderElement::resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle* shadowHostStyle)
 {
     auto style = resolveStyle(&parentStyle);
 
     auto& controlElement = downcast<HTMLTextFormControlElement>(*containingShadowRoot()->host());
-    style.renderStyle->setDisplay(controlElement.isPlaceholderVisible() ? BLOCK : NONE);
+    style.renderStyle->setDisplay(controlElement.isPlaceholderVisible() ? DisplayType::Block : DisplayType::None);
 
     if (is<HTMLInputElement>(controlElement)) {
         auto& inputElement = downcast<HTMLInputElement>(controlElement);
-        style.renderStyle->setTextOverflow(inputElement.shouldTruncateText(*shadowHostStyle) ? TextOverflowEllipsis : TextOverflowClip);
+        style.renderStyle->setTextOverflow(inputElement.shouldTruncateText(*shadowHostStyle) ? TextOverflow::Ellipsis : TextOverflow::Clip);
     }
     return WTFMove(style);
 }
 
-// ----------------------------
+// MARK: SearchFieldResultsButtonElement
 
 inline SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document& document)
     : HTMLDivElement(divTag, document)
@@ -178,7 +221,7 @@ Ref<SearchFieldResultsButtonElement> SearchFieldResultsButtonElement::create(Doc
 void SearchFieldResultsButtonElement::defaultEventHandler(Event& event)
 {
     // On mousedown, bring up a menu, if needed
-    auto* input = downcast<HTMLInputElement>(shadowHost());
+    auto input = makeRefPtr(downcast<HTMLInputElement>(shadowHost()));
     if (input && event.type() == eventNames().mousedownEvent && is<MouseEvent>(event) && downcast<MouseEvent>(event).button() == LeftButton) {
         input->focus();
         input->select();
@@ -205,7 +248,7 @@ bool SearchFieldResultsButtonElement::willRespondToMouseClickEvents()
 }
 #endif
 
-// ----------------------------
+// MARK: SearchFieldCancelButtonElement
 
 inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& document)
     : HTMLDivElement(divTag, document)