DevTools: Make CodeMirror accessible

This overrides the default CodeMirror input logic to put more text in
the textarea.

CodeMirror uses an offscreen <textarea> to detect input. Due to
inconsistencies in the many browsers it supports, it simplifies things
by regularly checking if something is in the <textarea>, adding those
characters to the document, and then clearing the <textarea>. This
breaks assistive technology that wants to read from CodeMirror,
because the <textarea> that they interact with is constantly empty.

Because we target up-to-date Chrome, we can guarantee consistent
input events. This lets us leave the current line from the editor in
our <textarea>. CodeMirror still expects a mostly empty <textarea>, so
we pass CodeMirror a fake <textarea> that only contains the user's input.

Change-Id: I025a1937bfd66fa574fd692da079a5888d9cb529
Reviewed-on: https://chromium-review.googlesource.com/1020193
Commit-Queue: Joel Einbinder <[email protected]>
Reviewed-by: Andrey Lushnikov <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#564347}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: d06dd5982b810b4c3576388ef3a31f060685dff7
diff --git a/front_end/externs.js b/front_end/externs.js
index 7f815d3..19bc4f0 100644
--- a/front_end/externs.js
+++ b/front_end/externs.js
@@ -544,7 +544,7 @@
 };
 /** @type {!{cursorDiv: Element, lineSpace: Element}} */
 CodeMirror.prototype.display;
-/** @type {!{mode: string}} */
+/** @type {!{mode: string, lineWrapping: boolean}} */
 CodeMirror.prototype.options;
 /** @type {!Object} */
 CodeMirror.Pass;
@@ -557,6 +557,36 @@
 CodeMirror.defineMode = function(modeName, modeConstructor) {};
 CodeMirror.startState = function(mode) {};
 CodeMirror.copyState = function(mode, state) {};
+CodeMirror.inputStyles = {};
+CodeMirror.inputStyles.textarea = class {
+  constructor() {
+    /** @type {!HTMLTextAreaElement} */
+    this.textarea;
+    this.prevInput = '';
+    this.composing = false;
+    this.contextMenuPending = false;
+    /** @type {!CodeMirror} */
+    this.cm;
+  }
+  /**
+   * @param {!Object} display
+   */
+  init(display) {
+  }
+
+  /**
+   * @param {boolean=} typing
+   */
+  reset(typing) {
+  }
+
+  /**
+   * @return {boolean}
+   */
+  poll() {
+    return false;
+  }
+};
 
 /** @typedef {{canceled: boolean, from: !CodeMirror.Pos, to: !CodeMirror.Pos, text: string, origin: string, cancel: function()}} */
 CodeMirror.BeforeChangeObject;