Commit db409e20 authored by James Wallace-Lee's avatar James Wallace-Lee Committed by Commit Bot

Truncate string attributes in the accessibility tree

Adds the helper function
BlinkAXTreeSource::TruncateAndAddStringAttribute, which truncates string
attributes when Blink's tree is serialized for accessibility. String
attributes are truncated at BlinkAXTreeSource::kMaxStringAttributeLength
bytes, currently set to 10000 bytes.

Bug: 644805
Change-Id: Ibd1af03a77814aa524dcb067ad1be3f3f4291c8b
Reviewed-on: https://chromium-review.googlesource.com/1113946Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: James Wallace-Lee <jamwalla@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570818}
parent b050405b
...@@ -1778,6 +1778,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, ...@@ -1778,6 +1778,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("transition.html")); RunHtmlTest(FILE_PATH_LITERAL("transition.html"));
} }
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTruncateLabel) {
RunHtmlTest(FILE_PATH_LITERAL("truncate-label.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) { IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) {
RunHtmlTest(FILE_PATH_LITERAL("ul.html")); RunHtmlTest(FILE_PATH_LITERAL("ul.html"));
} }
......
...@@ -477,7 +477,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -477,7 +477,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
blink::WebString web_name = src.GetName(nameFrom, nameObjects); blink::WebString web_name = src.GetName(nameFrom, nameObjects);
if ((!web_name.IsEmpty() && !web_name.IsNull()) || if ((!web_name.IsEmpty() && !web_name.IsNull()) ||
nameFrom == blink::kWebAXNameFromAttributeExplicitlyEmpty) { nameFrom == blink::kWebAXNameFromAttributeExplicitlyEmpty) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kName, web_name.Utf8()); TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kName,
web_name.Utf8());
dst->SetNameFrom(AXNameFromFromBlink(nameFrom)); dst->SetNameFrom(AXNameFromFromBlink(nameFrom));
AddIntListAttributeFromWebObjects( AddIntListAttributeFromWebObjects(
ax::mojom::IntListAttribute::kLabelledbyIds, nameObjects, dst); ax::mojom::IntListAttribute::kLabelledbyIds, nameObjects, dst);
...@@ -488,8 +489,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -488,8 +489,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
blink::WebString web_description = blink::WebString web_description =
src.Description(nameFrom, descriptionFrom, descriptionObjects); src.Description(nameFrom, descriptionFrom, descriptionObjects);
if (!web_description.IsEmpty()) { if (!web_description.IsEmpty()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kDescription, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDescription,
web_description.Utf8()); web_description.Utf8());
dst->AddIntAttribute( dst->AddIntAttribute(
ax::mojom::IntAttribute::kDescriptionFrom, ax::mojom::IntAttribute::kDescriptionFrom,
static_cast<int32_t>(AXDescriptionFromFromBlink(descriptionFrom))); static_cast<int32_t>(AXDescriptionFromFromBlink(descriptionFrom)));
...@@ -498,11 +499,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -498,11 +499,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (src.ValueDescription().length()) { if (src.ValueDescription().length()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kValue, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue,
src.ValueDescription().Utf8()); src.ValueDescription().Utf8());
} else { } else {
dst->AddStringAttribute(ax::mojom::StringAttribute::kValue, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue,
src.StringValue().Utf8()); src.StringValue().Utf8());
} }
switch (src.Restriction()) { switch (src.Restriction()) {
...@@ -519,8 +520,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -519,8 +520,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (!src.Url().IsEmpty()) if (!src.Url().IsEmpty())
dst->AddStringAttribute(ax::mojom::StringAttribute::kUrl, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kUrl,
src.Url().GetString().Utf8()); src.Url().GetString().Utf8());
// The following set of attributes are only accessed when the accessibility // The following set of attributes are only accessed when the accessibility
// mode is set to screen reader mode, otherwise only the more basic // mode is set to screen reader mode, otherwise only the more basic
...@@ -528,8 +529,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -528,8 +529,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader)) { if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader)) {
blink::WebString web_placeholder = src.Placeholder(nameFrom); blink::WebString web_placeholder = src.Placeholder(nameFrom);
if (!web_placeholder.IsEmpty()) if (!web_placeholder.IsEmpty())
dst->AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder, TruncateAndAddStringAttribute(dst,
web_placeholder.Utf8()); ax::mojom::StringAttribute::kPlaceholder,
web_placeholder.Utf8());
if (dst->role == ax::mojom::Role::kColorWell) if (dst->role == ax::mojom::Role::kColorWell)
dst->AddIntAttribute(ax::mojom::IntAttribute::kColorValue, dst->AddIntAttribute(ax::mojom::IntAttribute::kColorValue,
...@@ -561,8 +563,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -561,8 +563,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
WebAXObject parent = ParentObjectUnignored(src); WebAXObject parent = ParentObjectUnignored(src);
if (src.FontFamily().length()) { if (src.FontFamily().length()) {
if (parent.IsNull() || parent.FontFamily() != src.FontFamily()) if (parent.IsNull() || parent.FontFamily() != src.FontFamily())
dst->AddStringAttribute(ax::mojom::StringAttribute::kFontFamily, TruncateAndAddStringAttribute(dst,
src.FontFamily().Utf8()); ax::mojom::StringAttribute::kFontFamily,
src.FontFamily().Utf8());
} }
// Font size is in pixels. // Font size is in pixels.
...@@ -586,8 +589,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -586,8 +589,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (src.InvalidState() == blink::kWebAXInvalidStateOther && if (src.InvalidState() == blink::kWebAXInvalidStateOther &&
src.AriaInvalidValue().length()) { src.AriaInvalidValue().length()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kAriaInvalidValue, TruncateAndAddStringAttribute(
src.AriaInvalidValue().Utf8()); dst, ax::mojom::StringAttribute::kAriaInvalidValue,
src.AriaInvalidValue().Utf8());
} }
if (src.CheckedState()) { if (src.CheckedState()) {
...@@ -638,13 +642,14 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -638,13 +642,14 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (src.AccessKey().length()) { if (src.AccessKey().length()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kAccessKey, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kAccessKey,
src.AccessKey().Utf8()); src.AccessKey().Utf8());
} }
if (src.AriaAutoComplete().length()) { if (src.AriaAutoComplete().length()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kAutoComplete, TruncateAndAddStringAttribute(dst,
src.AriaAutoComplete().Utf8()); ax::mojom::StringAttribute::kAutoComplete,
src.AriaAutoComplete().Utf8());
} }
if (src.Action() != blink::WebAXDefaultActionVerb::kNone) { if (src.Action() != blink::WebAXDefaultActionVerb::kNone) {
...@@ -652,20 +657,21 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -652,20 +657,21 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (src.HasComputedStyle()) { if (src.HasComputedStyle()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kDisplay, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDisplay,
src.ComputedStyleDisplay().Utf8()); src.ComputedStyleDisplay().Utf8());
} }
if (src.Language().length()) { if (src.Language().length()) {
if (parent.IsNull() || parent.Language() != src.Language()) if (parent.IsNull() || parent.Language() != src.Language())
dst->AddStringAttribute(ax::mojom::StringAttribute::kLanguage, TruncateAndAddStringAttribute(
src.Language().Utf8()); dst, ax::mojom::StringAttribute::kLanguage, src.Language().Utf8());
} }
if (src.KeyboardShortcut().length() && if (src.KeyboardShortcut().length() &&
!dst->HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) { !dst->HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts, TruncateAndAddStringAttribute(dst,
src.KeyboardShortcut().Utf8()); ax::mojom::StringAttribute::kKeyShortcuts,
src.KeyboardShortcut().Utf8());
} }
if (!src.NextOnLine().IsDetached()) { if (!src.NextOnLine().IsDetached()) {
...@@ -735,11 +741,13 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -735,11 +741,13 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
dst->AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, dst->AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic,
src.LiveRegionAtomic()); src.LiveRegionAtomic());
if (!src.LiveRegionStatus().IsEmpty()) { if (!src.LiveRegionStatus().IsEmpty()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus, TruncateAndAddStringAttribute(dst,
src.LiveRegionStatus().Utf8()); ax::mojom::StringAttribute::kLiveStatus,
src.LiveRegionStatus().Utf8());
} }
dst->AddStringAttribute(ax::mojom::StringAttribute::kLiveRelevant, TruncateAndAddStringAttribute(dst,
src.LiveRegionRelevant().Utf8()); ax::mojom::StringAttribute::kLiveRelevant,
src.LiveRegionRelevant().Utf8());
// If we are not at the root of an atomic live region. // If we are not at the root of an atomic live region.
if (src.ContainerLiveRegionAtomic() && if (src.ContainerLiveRegionAtomic() &&
!src.LiveRegionRoot().IsDetached() && !src.LiveRegionAtomic()) { !src.LiveRegionRoot().IsDetached() && !src.LiveRegionAtomic()) {
...@@ -750,10 +758,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -750,10 +758,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
src.ContainerLiveRegionAtomic()); src.ContainerLiveRegionAtomic());
dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveBusy, dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveBusy,
src.ContainerLiveRegionBusy()); src.ContainerLiveRegionBusy());
dst->AddStringAttribute(ax::mojom::StringAttribute::kContainerLiveStatus, TruncateAndAddStringAttribute(
src.ContainerLiveRegionStatus().Utf8()); dst, ax::mojom::StringAttribute::kContainerLiveStatus,
dst->AddStringAttribute( src.ContainerLiveRegionStatus().Utf8());
ax::mojom::StringAttribute::kContainerLiveRelevant, TruncateAndAddStringAttribute(
dst, ax::mojom::StringAttribute::kContainerLiveRelevant,
src.ContainerLiveRegionRelevant().Utf8()); src.ContainerLiveRegionRelevant().Utf8());
} }
...@@ -794,8 +803,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -794,8 +803,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (dst->role == ax::mojom::Role::kRootWebArea) if (dst->role == ax::mojom::Role::kRootWebArea)
dst->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kHtmlTag,
"#document"); "#document");
const bool is_table_like_role = dst->role == ax::mojom::Role::kTable || const bool is_table_like_role = dst->role == ax::mojom::Role::kTable ||
dst->role == ax::mojom::Role::kGrid || dst->role == ax::mojom::Role::kGrid ||
...@@ -893,8 +902,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -893,8 +902,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
// TODO(ctguil): The tagName in WebKit is lower cased but // TODO(ctguil): The tagName in WebKit is lower cased but
// HTMLElement::nodeName calls localNameUpper. Consider adding // HTMLElement::nodeName calls localNameUpper. Consider adding
// a WebElement method that returns the original lower cased tagName. // a WebElement method that returns the original lower cased tagName.
dst->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, TruncateAndAddStringAttribute(
base::ToLowerASCII(element.TagName().Utf8())); dst, ax::mojom::StringAttribute::kHtmlTag,
base::ToLowerASCII(element.TagName().Utf8()));
for (unsigned i = 0; i < element.AttributeCount(); ++i) { for (unsigned i = 0; i < element.AttributeCount(); ++i) {
std::string name = std::string name =
base::ToLowerASCII(element.AttributeLocalName(i).Utf8()); base::ToLowerASCII(element.AttributeLocalName(i).Utf8());
...@@ -906,8 +916,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -906,8 +916,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
// and remove ifdef. // and remove ifdef.
#if defined(OS_WIN) #if defined(OS_WIN)
if (dst->role == ax::mojom::Role::kMath && element.InnerHTML().length()) { if (dst->role == ax::mojom::Role::kMath && element.InnerHTML().length()) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kInnerHtml, TruncateAndAddStringAttribute(dst,
element.InnerHTML().Utf8()); ax::mojom::StringAttribute::kInnerHtml,
element.InnerHTML().Utf8());
} }
#endif #endif
} }
...@@ -927,12 +938,13 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -927,12 +938,13 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
// ARIA role. // ARIA role.
if (element.HasAttribute("role")) { if (element.HasAttribute("role")) {
dst->AddStringAttribute(ax::mojom::StringAttribute::kRole, TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole,
element.GetAttribute("role").Utf8()); element.GetAttribute("role").Utf8());
} else { } else {
std::string role = GetEquivalentAriaRoleString(dst->role); std::string role = GetEquivalentAriaRoleString(dst->role);
if (!role.empty()) if (!role.empty())
dst->AddStringAttribute(ax::mojom::StringAttribute::kRole, role); TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole,
role);
} }
// Browser plugin (used in a <webview>). // Browser plugin (used in a <webview>).
...@@ -987,6 +999,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, ...@@ -987,6 +999,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
} }
if (dst->id == image_data_node_id_) { if (dst->id == image_data_node_id_) {
// In general, string attributes should be truncated using
// TruncateAndAddStringAttribute, but ImageDataUrl contains a data url
// representing an image, so add it directly using AddStringAttribute.
dst->AddStringAttribute(ax::mojom::StringAttribute::kImageDataUrl, dst->AddStringAttribute(ax::mojom::StringAttribute::kImageDataUrl,
src.ImageDataUrl(max_image_data_size_).Utf8()); src.ImageDataUrl(max_image_data_size_).Utf8());
} }
...@@ -1011,4 +1026,18 @@ WebAXObject BlinkAXTreeSource::ComputeRoot() const { ...@@ -1011,4 +1026,18 @@ WebAXObject BlinkAXTreeSource::ComputeRoot() const {
return WebAXObject(); return WebAXObject();
} }
void BlinkAXTreeSource::TruncateAndAddStringAttribute(
AXContentNodeData* dst,
ax::mojom::StringAttribute attribute,
const std::string& value) const {
if (value.size() > BlinkAXTreeSource::kMaxStringAttributeLength) {
std::string truncated;
base::TruncateUTF8ToByteSize(
value, BlinkAXTreeSource::kMaxStringAttributeLength, &truncated);
dst->AddStringAttribute(attribute, truncated);
} else {
dst->AddStringAttribute(attribute, value);
}
}
} // namespace content } // namespace content
...@@ -115,6 +115,11 @@ class BlinkAXTreeSource ...@@ -115,6 +115,11 @@ class BlinkAXTreeSource
blink::WebAXObject ComputeRoot() const; blink::WebAXObject ComputeRoot() const;
uint32_t kMaxStringAttributeLength = 10000;
void TruncateAndAddStringAttribute(AXContentNodeData* dst,
ax::mojom::StringAttribute attribute,
const std::string& value) const;
RenderFrameImpl* render_frame_; RenderFrameImpl* render_frame_;
ui::AXMode accessibility_mode_; ui::AXMode accessibility_mode_;
......
rootWebArea
++genericContainer name='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
<!--
@BLINK-ALLOW:name=*
-->
<!DOCTYPE html>
<html>
<body>
<div id="big"></div>
<script>
var huge = document.getElementById('big');
var count = 1000000;
var bigStr = '';
for (var i = 0; i < count; i++)
bigStr += 'x';
huge.setAttribute('aria-label', bigStr);
</script>
</body>
</html>
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