DevTools: Make Preview Pane Accessible

This is a reland of 58040a832bb68a52529638518de36be17c65547f

The failing aXe tests were removed and will be added again after
invesigation

Original change's description:
> DevTools: Make Preview Pane Accessible
>
> The preview pane previously lacked keyboard controls for navigating
> through the JSON and XML views, the Font view unnecessarily read out the
> content of the view (the alphabet) when accessed via screen reader, and
> the Image view did not allow a screen reader user to access the size and
> mime type of the image.
>
> This patch fixes these issues by making the JSON and XML treeOutlines
> selectable so they can be accessed via keyboard and by displaying
> keyboard focus within the treeOutline. In the Font view, the element
> containing the sample text is marked so that a screen reader will not
> read the contents, but rather will read the source url of the font. In
> the Image view, a tab stop was moved from a parent element to the image
> itself and a label was added that reads the source url of the image.
>
> JSON view before: https://imgur.com/BWczsAL
> JSON view after, without keyboard focus: (same as before)
> JSON view after, with keyboard focus: https://imgur.com/gD0rNSB
>
> XML view before: https://imgur.com/Ec9b5kf
> XML view after, without focus: https://imgur.com/NEqUgpt
> XML view after, with focus: https://imgur.com/0csIpQ3
>
> Change-Id: Id8bacdc593a5b562069fddb70452902ebad934e0
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1551384
> Commit-Queue: Amanda Baker <[email protected]>
> Reviewed-by: Erik Luo <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#663263}

Change-Id: If544cc7a83d031c42cb538f6e89b9df9d3ec1dc0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1633989
Reviewed-by: Erik Luo <[email protected]>
Commit-Queue: Amanda Baker <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#666949}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: ffc8de5717812a6e5803c9f005a4159a58ff0824
diff --git a/front_end/source_frame/FontView.js b/front_end/source_frame/FontView.js
index d9030c6..2278603 100644
--- a/front_end/source_frame/FontView.js
+++ b/front_end/source_frame/FontView.js
@@ -39,6 +39,7 @@
     this.registerRequiredCSS('source_frame/fontView.css');
     this.element.classList.add('font-view');
     this._url = contentProvider.contentURL();
+    UI.ARIAUtils.setAccessibleName(this.element, ls`Preview of font from ${this._url}`);
     this._mimeType = mimeType;
     this._contentProvider = contentProvider;
     this._mimeTypeLabel = new UI.ToolbarText(mimeType);
@@ -79,6 +80,7 @@
       fontPreview.createTextChild(SourceFrame.FontView._fontPreviewLines[i]);
     }
     this.fontPreviewElement = fontPreview.cloneNode(true);
+    UI.ARIAUtils.markAsHidden(this.fontPreviewElement);
     this.fontPreviewElement.style.overflow = 'hidden';
     this.fontPreviewElement.style.setProperty('font-family', uniqueFontName);
     this.fontPreviewElement.style.setProperty('visibility', 'hidden');
diff --git a/front_end/source_frame/ImageView.js b/front_end/source_frame/ImageView.js
index b69709b..c6f5e86 100644
--- a/front_end/source_frame/ImageView.js
+++ b/front_end/source_frame/ImageView.js
@@ -37,6 +37,7 @@
   constructor(mimeType, contentProvider) {
     super(Common.UIString('Image'));
     this.registerRequiredCSS('source_frame/imageView.css');
+    this.element.tabIndex = 0;
     this.element.classList.add('image-view');
     this._url = contentProvider.contentURL();
     this._parsedURL = new Common.ParsedURL(this._url);
@@ -58,6 +59,7 @@
     this._container = this.element.createChild('div', 'image');
     this._imagePreviewElement = this._container.createChild('img', 'resource-image-view');
     this._imagePreviewElement.addEventListener('contextmenu', this._contextMenu.bind(this), true);
+    this._imagePreviewElement.alt = ls`Image from ${this._url}`;
   }
 
   /**
diff --git a/front_end/source_frame/JSONView.js b/front_end/source_frame/JSONView.js
index 7199d3e..53fe818 100644
--- a/front_end/source_frame/JSONView.js
+++ b/front_end/source_frame/JSONView.js
@@ -68,7 +68,6 @@
     searchableView.setPlaceholder(Common.UIString('Find'));
     jsonView._searchableView = searchableView;
     jsonView.show(searchableView.element);
-    jsonView.element.setAttribute('tabIndex', 0);
     return searchableView;
   }
 
@@ -172,6 +171,7 @@
     this._treeOutline.setEditable(false);
     this._treeOutline.expand();
     this.element.appendChild(this._treeOutline.element);
+    this._treeOutline.firstChild().select(true /* omitFocus */, false /* selectedByUser */);
   }
 
   /**
diff --git a/front_end/source_frame/XMLView.js b/front_end/source_frame/XMLView.js
index cc0434b..ad6a40a 100644
--- a/front_end/source_frame/XMLView.js
+++ b/front_end/source_frame/XMLView.js
@@ -27,6 +27,7 @@
     this._searchConfig;
 
     SourceFrame.XMLView.Node.populate(this._treeOutline, parsedXML, this);
+    this._treeOutline.firstChild().select(true /* omitFocus */, false /* selectedByUser */);
   }
 
   /**
@@ -39,7 +40,6 @@
     searchableView.setPlaceholder(Common.UIString('Find'));
     xmlView._searchableView = searchableView;
     xmlView.show(searchableView.element);
-    xmlView.contentElement.setAttribute('tabIndex', 0);
     return searchableView;
   }
 
@@ -223,7 +223,7 @@
     super('', !closeTag && !!node.childElementCount);
     this._node = node;
     this._closeTag = closeTag;
-    this.selectable = false;
+    this.selectable = true;
     /** @type {!Array.<!Object>} */
     this._highlightChanges = [];
     this._xmlView = xmlView;
diff --git a/front_end/source_frame/source_frame_strings.grdp b/front_end/source_frame/source_frame_strings.grdp
index a1d41c7..9be107a 100644
--- a/front_end/source_frame/source_frame_strings.grdp
+++ b/front_end/source_frame/source_frame_strings.grdp
@@ -18,12 +18,18 @@
   <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc="">
     Find
   </message>
+  <message name="IDS_DEVTOOLS_53cd8180752335dce4f9b9ed493ef58d" desc="">
+    Image from <ph name="THIS__URL">$1s</ph>
+  </message>
   <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc="">
     Pretty print
   </message>
   <message name="IDS_DEVTOOLS_5ada9c9e1dad2e7e20aaa7688d7bd6c7" desc="">
     Line <ph name="LOCATION_______">$1s</ph>, Column <ph name="LOCATION_______">$2s</ph>
   </message>
+  <message name="IDS_DEVTOOLS_69614e5ef242926a61b58cebd303d4f4" desc="">
+    Preview of font from <ph name="THIS__URL">$1s</ph>
+  </message>
   <message name="IDS_DEVTOOLS_6efb3f8d955fc3395726044acec66129" desc="">
     <ph name="THIS__IMAGEPREVIEWELEMENT_NATURALWIDTH">$1d</ph> × <ph name="THIS__IMAGEPREVIEWELEMENT_NATURALHEIGHT">$2d</ph>
   </message>
diff --git a/front_end/ui/UIUtils.js b/front_end/ui/UIUtils.js
index d2aa44d..03d4a52 100644
--- a/front_end/ui/UIUtils.js
+++ b/front_end/ui/UIUtils.js
@@ -2037,6 +2037,11 @@
  * @return {!DocumentFragment}
  */
 UI.createExpandableText = function(text, maxLength) {
+  const clickHandler = () => {
+    if (expandElement.parentElement)
+      expandElement.parentElement.insertBefore(createTextNode(text.slice(maxLength)), expandElement);
+    expandElement.remove();
+  };
   const fragment = createDocumentFragment();
   fragment.textContent = text.slice(0, maxLength);
   const expandElement = fragment.createChild('span');
@@ -2044,11 +2049,13 @@
   if (text.length < 10000000) {
     expandElement.setAttribute('data-text', ls`Show more (${totalBytes})`);
     expandElement.classList.add('expandable-inline-button');
-    expandElement.addEventListener('click', () => {
-      if (expandElement.parentElement)
-        expandElement.parentElement.insertBefore(createTextNode(text.slice(maxLength)), expandElement);
-      expandElement.remove();
+    expandElement.addEventListener('click', clickHandler);
+    expandElement.addEventListener('keydown', event => {
+      if (event.key === 'Enter' || event.key === ' ')
+        clickHandler();
     });
+    UI.ARIAUtils.markAsButton(expandElement);
+
   } else {
     expandElement.setAttribute('data-text', ls`long text was truncated (${totalBytes})`);
     expandElement.classList.add('undisplayable-text');
@@ -2059,6 +2066,11 @@
   copyButton.addEventListener('click', () => {
     InspectorFrontendHost.copyText(text);
   });
+  copyButton.addEventListener('keydown', event => {
+    if (event.key === 'Enter' || event.key === ' ')
+      InspectorFrontendHost.copyText(text);
+  });
+  UI.ARIAUtils.markAsButton(copyButton);
   return fragment;
 };
 
diff --git a/front_end/ui/inspectorCommon.css b/front_end/ui/inspectorCommon.css
index 525ae58..038351f 100644
--- a/front_end/ui/inspectorCommon.css
+++ b/front_end/ui/inspectorCommon.css
@@ -428,6 +428,10 @@
     background-color: #d5d5d5;
 }
 
+.expandable-inline-button[data-keyboard-focus="true"] {
+    background-color: #bbbbbb;
+}
+
 ::selection {
     background-color: #bbdefb;
 }