Commit 79da0963 authored by Yao Xiao's avatar Yao Xiao Committed by Commit Bot

Move the email regex from HTMLInputElement to DocumentData

This reduces the overall memory. And hopefully it could fix the
regression introduced by
https://chromium-review.googlesource.com/c/chromium/src/+/2324204,
which could allocate a regex for every input element.

Bug: 1116302
Change-Id: I00f1fa7ad07664d5ab799e760483034c1a1594fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2357464
Commit-Queue: Yao Xiao <yaoxia@chromium.org>
Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Cr-Commit-Position: refs/heads/master@{#802754}
parent d3ec1564
...@@ -198,6 +198,7 @@ ...@@ -198,6 +198,7 @@
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h" #include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
#include "third_party/blink/renderer/core/html/document_all_name_collection.h" #include "third_party/blink/renderer/core/html/document_all_name_collection.h"
#include "third_party/blink/renderer/core/html/document_name_collection.h" #include "third_party/blink/renderer/core/html/document_name_collection.h"
#include "third_party/blink/renderer/core/html/forms/email_input_type.h"
#include "third_party/blink/renderer/core/html/forms/form_controller.h" #include "third_party/blink/renderer/core/html/forms/form_controller.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h" #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
...@@ -7301,6 +7302,12 @@ Document::EnsureDocumentExplicitRootIntersectionObserverData() { ...@@ -7301,6 +7302,12 @@ Document::EnsureDocumentExplicitRootIntersectionObserverData() {
return *document_explicit_root_intersection_observer_data_; return *document_explicit_root_intersection_observer_data_;
} }
const ScriptRegexp& Document::EnsureEmailRegexp() const {
if (!data_->email_regexp_)
data_->email_regexp_ = EmailInputType::CreateEmailRegexp();
return *data_->email_regexp_;
}
void Document::AddConsoleMessage(ConsoleMessage* message, void Document::AddConsoleMessage(ConsoleMessage* message,
bool discard_duplicates) const { bool discard_duplicates) const {
// Don't let non-attached Documents spam the console. // Don't let non-attached Documents spam the console.
......
...@@ -188,6 +188,7 @@ class Text; ...@@ -188,6 +188,7 @@ class Text;
class TrustedHTML; class TrustedHTML;
class ScriptElementBase; class ScriptElementBase;
class ScriptPromise; class ScriptPromise;
class ScriptRegexp;
class ScriptRunner; class ScriptRunner;
class ScriptableDocumentParser; class ScriptableDocumentParser;
class ScriptedAnimationController; class ScriptedAnimationController;
...@@ -986,6 +987,8 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -986,6 +987,8 @@ class CORE_EXPORT Document : public ContainerNode,
ElementIntersectionObserverData& ElementIntersectionObserverData&
EnsureDocumentExplicitRootIntersectionObserverData(); EnsureDocumentExplicitRootIntersectionObserverData();
const ScriptRegexp& EnsureEmailRegexp() const;
// Returns the owning element in the parent document. Returns nullptr if // Returns the owning element in the parent document. Returns nullptr if
// this is the top level document or the owner is remote. // this is the top level document or the owner is remote.
HTMLFrameOwnerElement* LocalOwner() const; HTMLFrameOwnerElement* LocalOwner() const;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "services/network/public/mojom/trust_tokens.mojom-blink.h" #include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
namespace blink { namespace blink {
...@@ -19,7 +20,7 @@ namespace blink { ...@@ -19,7 +20,7 @@ namespace blink {
// Other instances should not have strong references to the DocumentData. // Other instances should not have strong references to the DocumentData.
// Lifetime: A DocumentData instance is created on a Document creation, and // Lifetime: A DocumentData instance is created on a Document creation, and
// is never destructed before the Document. // is never destructed before the Document.
class DocumentData : public GarbageCollected<DocumentData> { class DocumentData final : public GarbageCollected<DocumentData> {
public: public:
explicit DocumentData(ExecutionContext* context) explicit DocumentData(ExecutionContext* context)
: permission_service_(context), has_trust_tokens_answerer_(context) {} : permission_service_(context), has_trust_tokens_answerer_(context) {}
...@@ -51,6 +52,9 @@ class DocumentData : public GarbageCollected<DocumentData> { ...@@ -51,6 +52,9 @@ class DocumentData : public GarbageCollected<DocumentData> {
HeapHashSet<Member<ScriptPromiseResolver>> HeapHashSet<Member<ScriptPromiseResolver>>
pending_has_trust_tokens_resolvers_; pending_has_trust_tokens_resolvers_;
// To do email regex checks.
std::unique_ptr<ScriptRegexp> email_regexp_;
friend class Document; friend class Document;
}; };
......
...@@ -175,24 +175,25 @@ const AtomicString& EmailInputType::FormControlType() const { ...@@ -175,24 +175,25 @@ const AtomicString& EmailInputType::FormControlType() const {
return input_type_names::kEmail; return input_type_names::kEmail;
} }
ScriptRegexp& EmailInputType::EnsureEmailRegexp() const {
return GetElement().EnsureEmailRegexp();
}
// The return value is an invalid email address string if the specified string // The return value is an invalid email address string if the specified string
// contains an invalid email address. Otherwise, null string is returned. // contains an invalid email address. Otherwise, an empty string is returned.
// If an empty string is returned, it means empty address is specified. // If an empty string is returned, it means empty address is specified.
// e.g. "foo@example.com,,bar@example.com" for multiple case. // e.g. "foo@example.com,,bar@example.com" for multiple case.
String EmailInputType::FindInvalidAddress(const String& value) const { String EmailInputType::FindInvalidAddress(const String& value) const {
if (value.IsEmpty()) if (value.IsEmpty())
return String(); return String();
if (!GetElement().Multiple()) if (!GetElement().Multiple()) {
return IsValidEmailAddress(EnsureEmailRegexp(), value) ? String() : value; return IsValidEmailAddress(GetElement().GetDocument().EnsureEmailRegexp(),
value)
? String()
: value;
}
Vector<String> addresses; Vector<String> addresses;
value.Split(',', true, addresses); value.Split(',', true, addresses);
for (const auto& address : addresses) { for (const auto& address : addresses) {
String stripped = StripLeadingAndTrailingHTMLSpaces(address); String stripped = StripLeadingAndTrailingHTMLSpaces(address);
if (!IsValidEmailAddress(EnsureEmailRegexp(), stripped)) if (!IsValidEmailAddress(GetElement().GetDocument().EnsureEmailRegexp(),
stripped))
return stripped; return stripped;
} }
return String(); return String();
...@@ -282,8 +283,10 @@ String EmailInputType::SanitizeValue(const String& proposed_value) const { ...@@ -282,8 +283,10 @@ String EmailInputType::SanitizeValue(const String& proposed_value) const {
String EmailInputType::ConvertFromVisibleValue( String EmailInputType::ConvertFromVisibleValue(
const String& visible_value) const { const String& visible_value) const {
String sanitized_value = SanitizeValue(visible_value); String sanitized_value = SanitizeValue(visible_value);
if (!GetElement().Multiple()) if (!GetElement().Multiple()) {
return ConvertEmailAddressToASCII(EnsureEmailRegexp(), sanitized_value); return ConvertEmailAddressToASCII(
GetElement().GetDocument().EnsureEmailRegexp(), sanitized_value);
}
Vector<String> addresses; Vector<String> addresses;
sanitized_value.Split(',', true, addresses); sanitized_value.Split(',', true, addresses);
StringBuilder builder; StringBuilder builder;
...@@ -291,8 +294,8 @@ String EmailInputType::ConvertFromVisibleValue( ...@@ -291,8 +294,8 @@ String EmailInputType::ConvertFromVisibleValue(
for (wtf_size_t i = 0; i < addresses.size(); ++i) { for (wtf_size_t i = 0; i < addresses.size(); ++i) {
if (i > 0) if (i > 0)
builder.Append(','); builder.Append(',');
builder.Append( builder.Append(ConvertEmailAddressToASCII(
ConvertEmailAddressToASCII(EnsureEmailRegexp(), addresses[i])); GetElement().GetDocument().EnsureEmailRegexp(), addresses[i]));
} }
return builder.ToString(); return builder.ToString();
} }
......
...@@ -57,7 +57,6 @@ class EmailInputType final : public BaseTextInputType { ...@@ -57,7 +57,6 @@ class EmailInputType final : public BaseTextInputType {
String ConvertFromVisibleValue(const String&) const override; String ConvertFromVisibleValue(const String&) const override;
String VisibleValue() const override; String VisibleValue() const override;
ScriptRegexp& EnsureEmailRegexp() const;
String ConvertEmailAddressToUnicode(const String&) const; String ConvertEmailAddressToUnicode(const String&) const;
String FindInvalidAddress(const String&) const; String FindInvalidAddress(const String&) const;
}; };
......
...@@ -2030,12 +2030,6 @@ bool HTMLInputElement::IsDraggedSlider() const { ...@@ -2030,12 +2030,6 @@ bool HTMLInputElement::IsDraggedSlider() const {
return input_type_view_->IsDraggedSlider(); return input_type_view_->IsDraggedSlider();
} }
ScriptRegexp& HTMLInputElement::EnsureEmailRegexp() const {
if (!email_regexp_)
email_regexp_ = EmailInputType::CreateEmailRegexp();
return *email_regexp_;
}
void HTMLInputElement::MaybeReportPiiMetrics() { void HTMLInputElement::MaybeReportPiiMetrics() {
// Don't report metrics if the field is empty. // Don't report metrics if the field is empty.
if (value().IsEmpty()) if (value().IsEmpty())
...@@ -2061,7 +2055,8 @@ void HTMLInputElement::MaybeReportPiiMetrics() { ...@@ -2061,7 +2055,8 @@ void HTMLInputElement::MaybeReportPiiMetrics() {
// https://www.rfc-editor.org/errata_search.php?rfc=3696) in addition to // https://www.rfc-editor.org/errata_search.php?rfc=3696) in addition to
// matching with the pattern given by the HTML standard. // matching with the pattern given by the HTML standard.
if (value().length() <= kMaxEmailFieldLength && if (value().length() <= kMaxEmailFieldLength &&
EmailInputType::IsValidEmailAddress(EnsureEmailRegexp(), value())) { EmailInputType::IsValidEmailAddress(GetDocument().EnsureEmailRegexp(),
value())) {
UseCounter::Count(GetDocument(), UseCounter::Count(GetDocument(),
WebFeature::kEmailFieldDetected_PatternMatch); WebFeature::kEmailFieldDetected_PatternMatch);
} }
......
...@@ -347,8 +347,6 @@ class CORE_EXPORT HTMLInputElement ...@@ -347,8 +347,6 @@ class CORE_EXPORT HTMLInputElement
form_element_pii_type_ = form_element_pii_type; form_element_pii_type_ = form_element_pii_type;
} }
ScriptRegexp& EnsureEmailRegexp() const;
protected: protected:
void DefaultEventHandler(Event&) override; void DefaultEventHandler(Event&) override;
void CreateShadowSubtree(); void CreateShadowSubtree();
...@@ -478,7 +476,6 @@ class CORE_EXPORT HTMLInputElement ...@@ -478,7 +476,6 @@ class CORE_EXPORT HTMLInputElement
Member<ListAttributeTargetObserver> list_attribute_target_observer_; Member<ListAttributeTargetObserver> list_attribute_target_observer_;
FormElementPiiType form_element_pii_type_ = FormElementPiiType::kUnknown; FormElementPiiType form_element_pii_type_ = FormElementPiiType::kUnknown;
mutable std::unique_ptr<ScriptRegexp> email_regexp_;
FRIEND_TEST_ALL_PREFIXES(HTMLInputElementTest, RadioKeyDownDCHECKFailure); FRIEND_TEST_ALL_PREFIXES(HTMLInputElementTest, RadioKeyDownDCHECKFailure);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment