diff --git a/Userland/Libraries/LibWeb/DOM/Text.h b/Userland/Libraries/LibWeb/DOM/Text.h index 6f22fbaf47..4c5a56f6ac 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.h +++ b/Userland/Libraries/LibWeb/DOM/Text.h @@ -31,6 +31,9 @@ public: WebIDL::ExceptionOr> split_text(size_t offset); + bool is_password_input() const { return m_is_password_input; } + void set_is_password_input(Badge, bool b) { m_is_password_input = b; } + protected: Text(Document&, String const&); Text(Document&, NodeType, String const&); @@ -41,6 +44,7 @@ private: JS::GCPtr m_owner_input_element; bool m_always_editable { false }; + bool m_is_password_input { false }; }; template<> diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 6466577c50..f71ecea17a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -344,6 +344,10 @@ void HTMLInputElement::create_shadow_tree_if_needed() m_text_node = heap().allocate(realm(), document(), initial_value); m_text_node->set_always_editable(m_type != TypeAttributeState::FileUpload); m_text_node->set_owner_input_element({}, *this); + + if (m_type == TypeAttributeState::Password) + m_text_node->set_is_password_input({}, true); + MUST(element->append_child(*m_text_node)); MUST(shadow_root->append_child(move(element))); set_shadow_root(move(shadow_root)); diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.cpp b/Userland/Libraries/LibWeb/Layout/TextNode.cpp index bee02d93ad..db141cab9c 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Userland/Libraries/LibWeb/Layout/TextNode.cpp @@ -35,6 +35,12 @@ static bool is_all_whitespace(StringView string) void TextNode::compute_text_for_rendering(bool collapse) { auto& data = dom_node().data(); + + if (dom_node().is_password_input()) { + m_text_for_rendering = String::repeated('*', data.length()); + return; + } + if (!collapse || data.is_empty()) { m_text_for_rendering = data; return;