Merge "Extract InMemorySecureStore to its own class"
diff --git a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
index 982bd14..842a5b0 100644
--- a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
+++ b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
@@ -24,14 +24,14 @@
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.common.data.LabelType;
+import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.ChangeInput;
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.LabelId;
-import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.reviewdb.client.PatchSetInfo;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
@@ -75,6 +75,7 @@
   @Inject protected ThreadLocalRequestContext requestContext;
   @Inject private ChangeNotes.Factory changeNotesFactory;
   @Inject private ProjectConfig.Factory projectConfigFactory;
+  @Inject private GerritApi gApi;
 
   private LifecycleManager lifecycle;
   private ReviewDb db;
@@ -127,18 +128,14 @@
   }
 
   private void setUpChange() throws Exception {
-    change =
-        new Change(
-            new Change.Key("Iabcd1234abcd1234abcd1234abcd1234abcd1234"),
-            new Change.Id(1),
-            userId,
-            new Branch.NameKey(allProjects, "refs/heads/master"),
-            TimeUtil.nowTs());
-    PatchSetInfo ps = new PatchSetInfo(new PatchSet.Id(change.getId(), 1));
-    ps.setSubject("Test change");
-    change.setCurrentPatchSet(ps);
-    db.changes().insert(ImmutableList.of(change));
-    notes = changeNotesFactory.createChecked(db, change);
+    ChangeInput input = new ChangeInput();
+    input.project = allProjects.get();
+    input.branch = "master";
+    input.newBranch = true;
+    input.subject = "Test change";
+    ChangeInfo info = gApi.changes().create(input).get();
+    notes = changeNotesFactory.createChecked(db, allProjects, new Change.Id(info._number));
+    change = notes.getChange();
   }
 
   @After
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
index af982cf..4266b22 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
@@ -91,7 +91,7 @@
 element. An example of this is in comment threads. A diff view supports actions
 on comment threads, but there may be zero or many comment threads attached at
 any given point. So the shortcut is declared as doc-only by the diff view and
-by gr-app, and actually implemented by gr-diff-comment-thread.
+by gr-app, and actually implemented by gr-comment-thread.
 
 NOTE: doc-only shortcuts will not be customizable in the same way that other
 shortcuts are.
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html
index bf17b911..e6d123c 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html
@@ -74,8 +74,8 @@
             <li>
               <p>
                 Close this dialog and you should be able to see your recently
-                created change in ``Outgoing changes'' section on
-                ``Your changes'' page.
+                created change in the 'Outgoing changes' section on the
+                'Your changes' page.
               </p>
             </li>
           </ol>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
index 42c9e88..67fdff1 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
@@ -219,7 +219,7 @@
         [this.Shortcut.TOGGLE_FILE_REVIEWED]: '_handleToggleFileReviewed',
         [this.Shortcut.TOGGLE_LEFT_PANE]: '_handleToggleLeftPane',
 
-        // Final two are actually handled by gr-diff-comment-thread.
+        // Final two are actually handled by gr-comment-thread.
         [this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
         [this.Shortcut.COLLAPSE_ALL_COMMENT_THREADS]: null,
       };
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.html b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.html
index 2201a9a..4d8e5ae 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.html
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.html
@@ -18,7 +18,7 @@
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
 <link rel="import" href="../../../bower_components/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="../../../styles/shared-styles.html">
-<link rel="import" href="../../diff/gr-diff-comment-thread/gr-diff-comment-thread.html">
+<link rel="import" href="../../shared/gr-comment-thread/gr-comment-thread.html">
 
 <dom-module id="gr-thread-list">
   <template>
@@ -28,7 +28,7 @@
         min-height: 20rem;
         padding: 1rem;
       }
-      gr-diff-comment-thread {
+      gr-comment-thread {
         display: block;
         margin-bottom: .5rem;
         max-width: 80ch;
@@ -54,9 +54,9 @@
         display: flex;
         margin-right: 1rem;
       }
-      .draftsOnly:not(.unresolvedOnly) gr-diff-comment-thread[has-draft],
-      .unresolvedOnly:not(.draftsOnly) gr-diff-comment-thread[unresolved],
-      .draftsOnly.unresolvedOnly gr-diff-comment-thread[has-draft][unresolved] {
+      .draftsOnly:not(.unresolvedOnly) gr-comment-thread[has-draft],
+      .unresolvedOnly:not(.draftsOnly) gr-comment-thread[unresolved],
+      .draftsOnly.unresolvedOnly gr-comment-thread[has-draft][unresolved] {
         display: block
       }
     </style>
@@ -82,7 +82,7 @@
           as="thread"
           initial-count="5"
           target-framerate="60">
-        <gr-diff-comment-thread
+        <gr-comment-thread
             show-file-path
             change-num="[[changeNum]]"
             comments="[[thread.comments]]"
@@ -94,7 +94,7 @@
             path="[[thread.path]]"
             root-id="{{thread.rootId}}"
             on-thread-changed="_handleCommentsChanged"
-            on-thread-discard="_handleThreadDiscard"></gr-diff-comment-thread>
+            on-thread-discard="_handleThreadDiscard"></gr-comment-thread>
       </template>
     </div>
   </template>
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
index 804446a..792644e 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
@@ -171,7 +171,7 @@
       ];
       flushAsynchronousOperations();
       threadElements = Polymer.dom(element.root)
-          .querySelectorAll('gr-diff-comment-thread');
+          .querySelectorAll('gr-comment-thread');
     });
 
     teardown(() => {
@@ -188,7 +188,7 @@
 
     test('there are five threads by default', () => {
       assert.equal(Polymer.dom(element.root)
-          .querySelectorAll('gr-diff-comment-thread').length, 5);
+          .querySelectorAll('gr-comment-thread').length, 5);
     });
 
     test('_computeSortedThreads', () => {
@@ -231,14 +231,14 @@
       MockInteractions.tap(element.$.unresolvedToggle);
       flushAsynchronousOperations();
       assert.equal(Polymer.dom(element.root)
-          .querySelectorAll('gr-diff-comment-thread').length, 3);
+          .querySelectorAll('gr-comment-thread').length, 3);
     });
 
     test('toggle drafts only shows threads with draft comments', () => {
       MockInteractions.tap(element.$.draftToggle);
       flushAsynchronousOperations();
       assert.equal(Polymer.dom(element.root)
-          .querySelectorAll('gr-diff-comment-thread').length, 2);
+          .querySelectorAll('gr-comment-thread').length, 2);
     });
 
     test('toggle drafts and unresolved only shows threads with drafts and ' +
@@ -247,7 +247,7 @@
       MockInteractions.tap(element.$.unresolvedToggle);
       flushAsynchronousOperations();
       assert.equal(Polymer.dom(element.root)
-          .querySelectorAll('gr-diff-comment-thread').length, 2);
+          .querySelectorAll('gr-comment-thread').length, 2);
     });
 
     test('modification events are consumed and displatched', () => {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
index d2731a2..6f5a8d3 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
@@ -20,10 +20,8 @@
   // Prevent redefinition.
   if (window.GrDiffBuilderBinary) { return; }
 
-  function GrDiffBuilderBinary(diff, commentThreadEls, prefs,
-      outputEl) {
-    GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
-        outputEl);
+  function GrDiffBuilderBinary(diff, prefs, outputEl) {
+    GrDiffBuilder.call(this, diff, prefs, outputEl);
   }
 
   GrDiffBuilderBinary.prototype = Object.create(GrDiffBuilder.prototype);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
index f05f4f0..bf543e5 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
@@ -22,10 +22,8 @@
 
   const IMAGE_MIME_PATTERN = /^image\/(bmp|gif|jpeg|jpg|png|tiff|webp)$/;
 
-  function GrDiffBuilderImage(diff, commentThreadEls, prefs,
-      outputEl, baseImage, revisionImage) {
-    GrDiffBuilderSideBySide.call(this, diff, commentThreadEls,
-        prefs, outputEl, []);
+  function GrDiffBuilderImage(diff, prefs, outputEl, baseImage, revisionImage) {
+    GrDiffBuilderSideBySide.call(this, diff, prefs, outputEl, []);
     this._baseImage = baseImage;
     this._revisionImage = revisionImage;
   }
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
index 81cbabb..2cf9782 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
@@ -20,10 +20,8 @@
   // Prevent redefinition.
   if (window.GrDiffBuilderSideBySide) { return; }
 
-  function GrDiffBuilderSideBySide(diff, commentThreadEls,
-      prefs, outputEl, layers) {
-    GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
-        outputEl, layers);
+  function GrDiffBuilderSideBySide(diff, prefs, outputEl, layers) {
+    GrDiffBuilder.call(this, diff, prefs, outputEl, layers);
   }
   GrDiffBuilderSideBySide.prototype = Object.create(GrDiffBuilder.prototype);
   GrDiffBuilderSideBySide.prototype.constructor = GrDiffBuilderSideBySide;
@@ -99,10 +97,6 @@
       row.appendChild(action);
     } else {
       const textEl = this._createTextEl(line, side);
-      const threadGroupEl = this._commentThreadGroupForLine(line, side);
-      if (threadGroupEl) {
-        textEl.appendChild(threadGroupEl);
-      }
       row.appendChild(textEl);
     }
   };
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
index 2dcdee4..6020e19 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
@@ -20,10 +20,8 @@
   // Prevent redefinition.
   if (window.GrDiffBuilderUnified) { return; }
 
-  function GrDiffBuilderUnified(diff, commentThreadEls, prefs,
-      outputEl, layers) {
-    GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
-        outputEl, layers);
+  function GrDiffBuilderUnified(diff, prefs, outputEl, layers) {
+    GrDiffBuilder.call(this, diff, prefs, outputEl, layers);
   }
   GrDiffBuilderUnified.prototype = Object.create(GrDiffBuilder.prototype);
   GrDiffBuilderUnified.prototype.constructor = GrDiffBuilderUnified;
@@ -88,10 +86,6 @@
       row.appendChild(action);
     } else {
       const textEl = this._createTextEl(line);
-      const threadGroupEl = this._commentThreadGroupForLine(line);
-      if (threadGroupEl) {
-        textEl.appendChild(threadGroupEl);
-      }
       row.appendChild(textEl);
     }
     return row;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
index 6aea35b..098a4af 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
@@ -18,7 +18,6 @@
 <link rel="import" href="../../core/gr-reporting/gr-reporting.html">
 <link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
 <link rel="import" href="../gr-diff-processor/gr-diff-processor.html">
-<link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
 <link rel="import" href="../gr-ranged-comment-layer/gr-ranged-comment-layer.html">
 <link rel="import" href="../gr-syntax-layer/gr-syntax-layer.html">
 
@@ -121,10 +120,6 @@
           return this.queryEffectiveChildren('#diffTable');
         },
 
-        get _commentThreadElements() {
-          return this.queryAllEffectiveChildren('.comment-thread');
-        },
-
         observers: [
           '_groupsChanged(_groups.splices)',
         ],
@@ -292,20 +287,16 @@
 
           let builder = null;
           if (this.isImageDiff) {
-            builder = new GrDiffBuilderImage(diff,
-              this._commentThreadElements, prefs, this.diffElement,
+            builder = new GrDiffBuilderImage(diff, prefs, this.diffElement,
               this.baseImage, this.revisionImage);
           } else if (diff.binary) {
             // If the diff is binary, but not an image.
-            return new GrDiffBuilderBinary(diff,
-                this._commentThreadElements, prefs, this.diffElement);
+            return new GrDiffBuilderBinary(diff, prefs, this.diffElement);
           } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
-            builder = new GrDiffBuilderSideBySide(diff,
-                this._commentThreadElements, prefs, this.diffElement,
+            builder = new GrDiffBuilderSideBySide(diff, prefs, this.diffElement,
                 this._layers);
           } else if (this.viewMode === DiffViewMode.UNIFIED) {
-            builder = new GrDiffBuilderUnified(diff,
-                this._commentThreadElements, prefs, this.diffElement,
+            builder = new GrDiffBuilderUnified(diff, prefs, this.diffElement,
                 this._layers);
           }
           if (!builder) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
index d428f68..e892605 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
@@ -20,60 +20,6 @@
   // Prevent redefinition.
   if (window.GrDiffBuilder) { return; }
 
-  /** @enum {string} */
-  Gerrit.DiffSide = {
-    LEFT: 'left',
-    RIGHT: 'right',
-    BOTH: 'both',
-  };
-
-  /**
-   * @param {!Array<!HTMLElement>} threadEls
-   * @param {!{beforeNumber: (number|string|undefined),
-   *           afterNumber: (number|string|undefined)}}
-   *     lineInfo
-   * @param {!Gerrit.DiffSide=} side The side (LEFT, RIGHT, BOTH) for
-   *     which to return the threads (default: BOTH).
-   * @return {!Array<!HTMLElement>} The thread elements matching the given
-   *     location.
-   */
-  Gerrit.filterThreadElsForLocation = function(
-      threadEls, lineInfo, side = Gerrit.DiffSide.BOTH) {
-    function matchesLeftLine(threadEl) {
-      return threadEl.getAttribute('comment-side') ==
-          Gerrit.DiffSide.LEFT &&
-          threadEl.getAttribute('line-num') == lineInfo.beforeNumber;
-    }
-    function matchesRightLine(threadEl) {
-      return threadEl.getAttribute('comment-side') ==
-          Gerrit.DiffSide.RIGHT &&
-          threadEl.getAttribute('line-num') == lineInfo.afterNumber;
-    }
-    function matchesFileComment(threadEl) {
-      return (side === Gerrit.DiffSide.BOTH ||
-              threadEl.getAttribute('comment-side') == side) &&
-            // line/range comments have 1-based line set, if line is falsy it's
-            // a file comment
-            !threadEl.getAttribute('line-num');
-    }
-
-    // Select the appropriate matchers for the desired side and line
-    // If side is BOTH, we want both the left and right matcher.
-    const matchers = [];
-    if (side !== Gerrit.DiffSide.RIGHT) {
-      matchers.push(matchesLeftLine);
-    }
-    if (side !== Gerrit.DiffSide.LEFT) {
-      matchers.push(matchesRightLine);
-    }
-    if (lineInfo.afterNumber === 'FILE' ||
-        lineInfo.beforeNumber === 'FILE') {
-      matchers.push(matchesFileComment);
-    }
-    return threadEls.filter(threadEl =>
-        matchers.some(matcher => matcher(threadEl)));
-  };
-
   /**
    * In JS, unicode code points above 0xFFFF occupy two elements of a string.
    * For example '𐀏'.length is 2. An occurence of such a code point is called a
@@ -96,8 +42,7 @@
    */
   const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/;
 
-  function GrDiffBuilder(diff, commentThreadEls, prefs,
-      outputEl, layers) {
+  function GrDiffBuilder(diff, prefs, outputEl, layers) {
     this._diff = diff;
     this._prefs = prefs;
     this._outputEl = outputEl;
@@ -119,8 +64,6 @@
         layer.addListener(this._handleLayerUpdate.bind(this));
       }
     }
-
-    this._threadEls = commentThreadEls;
   }
 
   GrDiffBuilder.GroupType = {
@@ -373,31 +316,6 @@
     return button;
   };
 
-  /**
-   * @param {!GrDiffLine} line
-   * @param {!GrDiffBuilder.Side=} side The side (LEFT, RIGHT, BOTH) for which
-   *     to return the thread group (default: BOTH).
-   * @return {!Object}
-   */
-  GrDiffBuilder.prototype._commentThreadGroupForLine = function(
-      line, commentSide = GrDiffBuilder.Side.BOTH) {
-    const threadElsForGroup =
-        Gerrit.filterThreadElsForLocation(this._threadEls, line, commentSide);
-    if (!threadElsForGroup || threadElsForGroup.length === 0) {
-      return null;
-    }
-
-    const threadGroupEl = document.createElement('div');
-    threadGroupEl.className = 'thread-group';
-    for (const threadEl of threadElsForGroup) {
-      Polymer.dom(threadGroupEl).appendChild(threadEl);
-    }
-    if (commentSide) {
-      threadGroupEl.setAttribute('data-side', commentSide);
-    }
-    return threadGroupEl;
-  };
-
   GrDiffBuilder.prototype._createLineEl = function(
       line, number, type, opt_class) {
     const td = this._createElement('td');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index c7a1140..1b0ba04 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -75,70 +75,11 @@
         show_tabs: true,
         tab_size: 4,
       };
-      builder = new GrDiffBuilder({content: []}, [], prefs);
+      builder = new GrDiffBuilder({content: []}, prefs);
     });
 
     teardown(() => { sandbox.restore(); });
 
-    test('filterThreadElsForLocation with no threads', () => {
-      const line = {beforeNumber: 3, afterNumber: 5};
-
-      const threads = [];
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threads, line), []);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threads, line,
-          Gerrit.DiffSide.LEFT), []);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threads, line,
-          Gerrit.DiffSide.RIGHT), []);
-    });
-
-    test('filterThreadElsForLocation for line comments', () => {
-      const line = {beforeNumber: 3, afterNumber: 5};
-
-      const l3 = document.createElement('div');
-      l3.setAttribute('line-num', 3);
-      l3.setAttribute('comment-side', 'left');
-
-      const l5 = document.createElement('div');
-      l5.setAttribute('line-num', 5);
-      l5.setAttribute('comment-side', 'left');
-
-      const r3 = document.createElement('div');
-      r3.setAttribute('line-num', 3);
-      r3.setAttribute('comment-side', 'right');
-
-      const r5 = document.createElement('div');
-      r5.setAttribute('line-num', 5);
-      r5.setAttribute('comment-side', 'right');
-
-      const threadEls = [l3, l5, r3, r5];
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line),
-          [l3, r5]);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
-          Gerrit.DiffSide.LEFT), [l3]);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
-          Gerrit.DiffSide.RIGHT), [r5]);
-    });
-
-    test('filterThreadElsForLocation for file comments', () => {
-      const line = {beforeNumber: 'FILE', afterNumber: 'FILE'};
-
-      const l = document.createElement('div');
-      l.setAttribute('comment-side', 'left');
-
-      const r = document.createElement('div');
-      r.setAttribute('comment-side', 'right');
-
-      const threadEls = [l, r];
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line),
-          [l, r]);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
-          Gerrit.DiffSide.BOTH), [l, r]);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
-          Gerrit.DiffSide.LEFT), [l]);
-      assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
-          Gerrit.DiffSide.RIGHT), [r]);
-    });
-
     test('_createElement classStr applies all classes', () => {
       const node = builder._createElement('div', 'test classes');
       assert.isTrue(node.classList.contains('gr-diff'));
@@ -312,73 +253,6 @@
       }
     });
 
-    test('comment thread group creation', () => {
-      const l3 = document.createElement('div');
-      l3.className = 'comment-thread';
-      l3.setAttribute('comment-side', 'left');
-      l3.setAttribute('line-num', 3);
-
-      const l5 = document.createElement('div');
-      l5.className = 'comment-thread';
-      l5.setAttribute('comment-side', 'left');
-      l5.setAttribute('line-num', 5);
-
-      const r5 = document.createElement('div');
-      r5.className = 'comment-thread';
-      r5.setAttribute('comment-side', 'right');
-      r5.setAttribute('line-num', 5);
-
-      builder = new GrDiffBuilder({content: []}, [l3, l5, r5], prefs);
-
-      function checkThreadGroupProps(threadGroupEl,
-          expectedThreadEls) {
-        const threadEls = Polymer.dom(threadGroupEl).queryDistributedElements(
-            '.comment-thread');
-        assert.equal(threadEls.length, expectedThreadEls.length);
-        for (let i=0; i<expectedThreadEls.length; i++) {
-          assert.equal(threadEls[i], expectedThreadEls[i]);
-        }
-      }
-
-      let line = new GrDiffLine(GrDiffLine.Type.BOTH);
-      line.beforeNumber = 5;
-      line.afterNumber = 5;
-      let threadGroupEl = builder._commentThreadGroupForLine(line);
-      checkThreadGroupProps(threadGroupEl, [l5, r5]);
-
-      threadGroupEl =
-          builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.RIGHT);
-      checkThreadGroupProps(threadGroupEl, [r5]);
-
-      threadGroupEl =
-          builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.LEFT);
-      checkThreadGroupProps(threadGroupEl, [l5]);
-
-      threadGroupEl = builder._commentThreadGroupForLine(line);
-      checkThreadGroupProps(threadGroupEl, [l5, r5]);
-
-      threadEl =
-          builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.LEFT);
-      checkThreadGroupProps(threadEl, [l5]);
-
-      threadGroupEl =
-          builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.RIGHT);
-      checkThreadGroupProps(threadGroupEl, [r5]);
-
-      line = new GrDiffLine(GrDiffLine.Type.REMOVE);
-      line.beforeNumber = 5;
-      line.afterNumber = 5;
-      threadGroupEl = builder._commentThreadGroupForLine(line);
-      checkThreadGroupProps(threadGroupEl, [l5, r5]);
-
-      line = new GrDiffLine(GrDiffLine.Type.ADD);
-      line.beforeNumber = 3;
-      line.afterNumber = 5;
-      threadGroupEl = builder._commentThreadGroupForLine(line);
-      checkThreadGroupProps(threadGroupEl, [l3, r5]);
-    });
-
-
     test('_handlePreferenceError called with invalid preference', () => {
       sandbox.stub(element, '_handlePreferenceError');
       const prefs = {tab_size: 0};
@@ -913,7 +787,7 @@
         outputEl = element.queryEffectiveChildren('#diffTable');
         keyLocations = {left: {}, right: {}};
         sandbox.stub(element, '_getDiffBuilder', () => {
-          const builder = new GrDiffBuilder({content}, [], prefs, outputEl);
+          const builder = new GrDiffBuilder({content}, prefs, outputEl);
           sandbox.stub(builder, 'addColumns');
           builder.buildSectionElement = function(group) {
             const section = document.createElement('stub');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
index aee7a62..860d900 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
@@ -293,7 +293,7 @@
     },
 
     _rowHasThread(row) {
-      return row.querySelector('gr-diff-comment-thread');
+      return row.querySelector('.comment-thread');
     },
 
     /**
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
index 85ba202..ff00383 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
@@ -37,8 +37,8 @@
     },
 
     listeners: {
-      'comment-mouse-out': '_handleCommentMouseOut',
-      'comment-mouse-over': '_handleCommentMouseOver',
+      'comment-thread-mouseleave': '_handleCommentThreadMouseleave',
+      'comment-thread-mouseenter': '_handleCommentThreadMouseenter',
       'create-range-comment': '_createRangeComment',
     },
 
@@ -74,8 +74,16 @@
       this.debounce('selectionChange', this._handleSelection, 200);
     },
 
-    _handleCommentMouseOver(e) {
-      const threadEl = Polymer.dom(e).localTarget;
+    _getThreadEl(e) {
+      const path = Polymer.dom(e).path || [];
+      for (const pathEl of path) {
+        if (pathEl.classList.contains('comment-thread')) return pathEl;
+      }
+      return null;
+    },
+
+    _handleCommentThreadMouseenter(e) {
+      const threadEl = this._getThreadEl(e);
       const index = this._indexForThreadEl(threadEl);
 
       if (index !== undefined) {
@@ -83,8 +91,8 @@
       }
     },
 
-    _handleCommentMouseOut(e) {
-      const threadEl = Polymer.dom(e).localTarget;
+    _handleCommentThreadMouseleave(e) {
+      const threadEl = this._getThreadEl(e);
       const index = this._indexForThreadEl(threadEl);
 
       if (index !== undefined) {
@@ -248,7 +256,7 @@
         node = contentText;
         column = 0;
       } else {
-        const thread = contentTd.querySelector('gr-diff-comment-thread');
+        const thread = contentTd.querySelector('.comment-thread');
         if (thread && thread.contains(node)) {
           column = this._getLength(contentText);
           node = contentText;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
index 23de407..8e3c7b0 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
@@ -72,9 +72,9 @@
           <tr class="diff-row side-by-side" left-type="remove" right-type="add">
             <td class="left lineNum" data-value="140"></td>
             <!-- Next tag is formatted to eliminate zero-length text nodes. -->
-            <td class="content remove"><div class="contentText">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab-indicator" style="tab-size:8;">	</span></hl>udiam, <hl>quid</hl> sit, <span class="tab-indicator" style="tab-size:8;">	</span>quod <hl>Epicurum</hl></div><gr-diff-comment-thread>
+            <td class="content remove"><div class="contentText">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab-indicator" style="tab-size:8;">	</span></hl>udiam, <hl>quid</hl> sit, <span class="tab-indicator" style="tab-size:8;">	</span>quod <hl>Epicurum</hl></div><div class="comment-thread">
                 [Yet another random diff thread content here]
-              </gr-diff-comment-thread></td>
+            </div></td>
             <td class="right lineNum" data-value="120"></td>
             <!-- Next tag is formatted to eliminate zero-length text nodes. -->
             <td class="content add"><div class="contentText">nacti , <hl>,</hl> sumus <hl><span class="tab-indicator" style="tab-size:8;">	</span></hl> otiosum,  <span class="tab-indicator" style="tab-size:8;">	</span> audiam,  sit, quod</div></td>
@@ -197,22 +197,60 @@
         element._cachedDiffBuilder = builder;
       });
 
-      test('comment-mouse-over from line comments is ignored', () => {
+      test('comment-thread-mouseenter from line comments is ignored', () => {
+        const threadEl = document.createElement('div');
+        threadEl.className = 'comment-thread';
+        threadEl.setAttribute('comment-side', 'right');
+        threadEl.setAttribute('line-num', 3);
+        element.appendChild(threadEl);
+        element.commentRanges = [{side: 'right'}];
+
         sandbox.stub(element, 'set');
-        element.fire('comment-mouse-over', {comment: {}});
+        threadEl.dispatchEvent(
+            new CustomEvent('comment-thread-mouseenter', {bubbles: true}));
         assert.isFalse(element.set.called);
       });
 
-      test('comment-mouse-over from ranged comment causes set', () => {
+      test('comment-thread-mouseenter from ranged comment causes set', () => {
+        const threadEl = document.createElement('div');
+        threadEl.className = 'comment-thread';
+        threadEl.setAttribute('comment-side', 'right');
+        threadEl.setAttribute('line-num', 3);
+        threadEl.setAttribute('range', JSON.stringify({
+          start_line: 3,
+          start_character: 4,
+          end_line: 5,
+          end_character: 6,
+        }));
+        element.appendChild(threadEl);
+        element.commentRanges = [{side: 'right', range: {
+          start_line: 3,
+          start_character: 4,
+          end_line: 5,
+          end_character: 6,
+        }}];
+
         sandbox.stub(element, 'set');
-        sandbox.stub(element, '_indexForThreadEl').returns(0);
-        element.fire('comment-mouse-over', {comment: {range: {}}});
+        threadEl.dispatchEvent(
+            new CustomEvent('comment-thread-mouseenter', {bubbles: true}));
         assert.isTrue(element.set.called);
+        const args = element.set.lastCall.args;
+        assert.deepEqual(args[0], ['commentRanges', 0, 'hovering']);
+        assert.deepEqual(args[1], true);
       });
 
-      test('comment-mouse-out from line comments is ignored', () => {
-        element.fire('comment-mouse-over', {comment: {}});
-        assert.isFalse(builder.getContentsByLineRange.called);
+      test('comment-thread-mouseleave from line comments is ignored', () => {
+        const threadEl = document.createElement('div');
+        threadEl.className = 'comment-thread';
+        threadEl.setAttribute('comment-side', 'right');
+        threadEl.setAttribute('line-num', 3);
+        element.appendChild(threadEl);
+        element.commentRanges = [{side: 'right'}];
+
+        sandbox.stub(element, 'set');
+        threadEl.dispatchEvent(
+            new CustomEvent('comment-thread-mouseleave', {bubbles: true}));
+        assert.isFalse(element.set.called);
       });
 
       test('on create-range-comment action box is removed', () => {
@@ -465,7 +503,7 @@
       test('starts in comment thread element', () => {
         const startContent = stubContent(140, 'left');
         const comment = startContent.parentElement.querySelector(
-            'gr-diff-comment-thread');
+            '.comment-thread');
         const endContent = stubContent(141, 'left');
         emulateSelection(comment.firstChild, 2, endContent.firstChild, 4);
         assert.isTrue(element.isRangeSelected());
@@ -481,7 +519,7 @@
       test('ends in comment thread element', () => {
         const content = stubContent(140, 'left');
         const comment = content.parentElement.querySelector(
-            'gr-diff-comment-thread');
+            '.comment-thread');
         emulateSelection(content.firstChild, 4, comment.firstChild, 1);
         assert.isTrue(element.isRangeSelected());
         assert.deepEqual(getActionRange(), {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html
index 3eb7b37..4c310b9 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html
@@ -19,7 +19,7 @@
 <link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
 <link rel="import" href="../../core/gr-reporting/gr-reporting.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
-<link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
+<link rel="import" href="../../shared/gr-comment-thread/gr-comment-thread.html">
 <link rel="import" href="../gr-diff/gr-diff.html">
 
 <dom-module id="gr-diff-host">
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
index 5839141..8b9d8066 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
@@ -63,6 +63,12 @@
         a.end_character === b.end_character;
   }
 
+  /** @enum {string} */
+  Gerrit.DiffSide = {
+    LEFT: 'left',
+    RIGHT: 'right',
+  };
+
   /**
    * Wrapper around gr-diff.
    *
@@ -196,11 +202,6 @@
         type: Number,
         computed: '_computeParentIndex(patchRange.*)',
       },
-
-      _threadEls: {
-        type: Array,
-        value: () => [],
-      },
     },
 
     behaviors: [
@@ -344,7 +345,7 @@
      * @return {!Array<!HTMLElement>}
      */
     getThreadEls() {
-      return this._threadEls;
+      return Polymer.dom(this.$.diff).querySelectorAll('.comment-thread');
     },
 
     /** @param {HTMLElement} el */
@@ -471,7 +472,6 @@
       return isImageDiff(diff);
     },
 
-
     _commentsChanged(newComments) {
       const allComments = [];
       for (const side of [GrDiffBuilder.Side.LEFT, GrDiffBuilder.Side.RIGHT]) {
@@ -590,21 +590,20 @@
     },
 
     _attachThreadElement(threadEl) {
-      this._threadEls.push(threadEl);
       Polymer.dom(this.$.diff).appendChild(threadEl);
     },
 
     _clearThreads() {
-      for (const threadEl of this._threadEls) {
+      for (const threadEl of this.getThreadEls()) {
         const parent = Polymer.dom(threadEl).parentNode;
         Polymer.dom(parent).removeChild(threadEl);
       }
-      this._threadEls = [];
     },
 
     _createThreadElement(thread) {
-      const threadEl = document.createElement('gr-diff-comment-thread');
+      const threadEl = document.createElement('gr-comment-thread');
       threadEl.className = 'comment-thread';
+      threadEl.slot = `${thread.commentSide}-${thread.lineNum}`;
       threadEl.comments = thread.comments;
       threadEl.commentSide = thread.commentSide;
       threadEl.isOnParent = !!thread.isOnParent;
@@ -625,10 +624,6 @@
         const parent = Polymer.dom(threadEl).parentNode;
         Polymer.dom(parent).removeChild(threadEl);
 
-        const i = this._threadEls.findIndex(
-            threadEl => threadEl.rootId == e.detail.rootId);
-        this._threadEls.splice(i, 1);
-
         threadEl.removeEventListener('root-id-changed', rootIdChangedListener);
         threadEl.removeEventListener('thread-discard', threadDiscardListener);
       };
@@ -660,12 +655,57 @@
         return rangesEqual(threadRange, range);
       }
 
-      const filteredThreadEls = Gerrit.filterThreadElsForLocation(
-          this._threadEls, line, commentSide).filter(matchesRange);
+      const filteredThreadEls = this._filterThreadElsForLocation(
+          this.getThreadEls(), line, commentSide).filter(matchesRange);
       return filteredThreadEls.length ? filteredThreadEls[0] : null;
     },
 
     /**
+     * @param {!Array<!HTMLElement>} threadEls
+     * @param {!{beforeNumber: (number|string|undefined|null),
+     *           afterNumber: (number|string|undefined|null)}}
+     *     lineInfo
+     * @param {!Gerrit.DiffSide=} side The side (LEFT, RIGHT) for
+     *     which to return the threads.
+     * @return {!Array<!HTMLElement>} The thread elements matching the given
+     *     location.
+     */
+    _filterThreadElsForLocation(threadEls, lineInfo, side) {
+      function matchesLeftLine(threadEl) {
+        return threadEl.getAttribute('comment-side') ==
+            Gerrit.DiffSide.LEFT &&
+            threadEl.getAttribute('line-num') == lineInfo.beforeNumber;
+      }
+      function matchesRightLine(threadEl) {
+        return threadEl.getAttribute('comment-side') ==
+            Gerrit.DiffSide.RIGHT &&
+            threadEl.getAttribute('line-num') == lineInfo.afterNumber;
+      }
+      function matchesFileComment(threadEl) {
+        return threadEl.getAttribute('comment-side') == side &&
+              // line/range comments have 1-based line set, if line is falsy it's
+              // a file comment
+              !threadEl.getAttribute('line-num');
+      }
+
+      // Select the appropriate matchers for the desired side and line
+      // If side is BOTH, we want both the left and right matcher.
+      const matchers = [];
+      if (side !== Gerrit.DiffSide.RIGHT) {
+        matchers.push(matchesLeftLine);
+      }
+      if (side !== Gerrit.DiffSide.LEFT) {
+        matchers.push(matchesRightLine);
+      }
+      if (lineInfo.afterNumber === 'FILE' ||
+          lineInfo.beforeNumber === 'FILE') {
+        matchers.push(matchesFileComment);
+      }
+      return threadEls.filter(threadEl =>
+          matchers.some(matcher => matcher(threadEl)));
+    },
+
+    /**
      * Take a diff that was loaded with a ignore-whitespace other than
      * IGNORE_NONE, and convert delta chunks labeled as common into shared
      * chunks.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
index 5344256..ab9daec 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
@@ -256,7 +256,7 @@
       threadEls[0].dispatchEvent(
           new CustomEvent('thread-discard', {detail: {rootId: 4711}}));
       const attachedThreads = element.queryAllEffectiveChildren(
-          'gr-diff-comment-thread');
+          'gr-comment-thread');
       assert.equal(attachedThreads.length, 1);
       assert.equal(attachedThreads[0].rootId, 42);
     });
@@ -769,10 +769,11 @@
       });
     });
 
-    test('getThreadEls() returns _threadEls', () => {
-      const returnValue = [document.createElement('b')];
-      element._threadEls = returnValue;
-      assert.equal(element.getThreadEls(), returnValue);
+    test('getThreadEls() returns .comment-threads', () => {
+      const threadEl = document.createElement('div');
+      threadEl.className = 'comment-thread';
+      Polymer.dom(element.$.diff).appendChild(threadEl);
+      assert.deepEqual(element.getThreadEls(), [threadEl]);
     });
 
     test('delegates addDraftAtLine(el)', () => {
@@ -1129,7 +1130,7 @@
           commentSide, undefined, false));
 
       let threads = Polymer.dom(element.$.diff)
-          .queryDistributedElements('gr-diff-comment-thread');
+          .queryDistributedElements('gr-comment-thread');
 
       assert.equal(threads.length, 1);
       assert.equal(threads[0].commentSide, commentSide);
@@ -1150,7 +1151,7 @@
           '3', 1, commentSide, range, true));
 
       threads = Polymer.dom(element.$.diff)
-          .queryDistributedElements('gr-diff-comment-thread');
+          .queryDistributedElements('gr-comment-thread');
 
       assert.equal(threads.length, 2);
       assert.equal(threads[1].commentSide, commentSide);
@@ -1159,6 +1160,65 @@
       assert.equal(threads[1].patchNum, 3);
     });
 
+    test('_filterThreadElsForLocation with no threads', () => {
+      const line = {beforeNumber: 3, afterNumber: 5};
+
+      const threads = [];
+      assert.deepEqual(element._filterThreadElsForLocation(threads, line), []);
+      assert.deepEqual(element._filterThreadElsForLocation(threads, line,
+          Gerrit.DiffSide.LEFT), []);
+      assert.deepEqual(element._filterThreadElsForLocation(threads, line,
+          Gerrit.DiffSide.RIGHT), []);
+    });
+
+    test('_filterThreadElsForLocation for line comments', () => {
+      const line = {beforeNumber: 3, afterNumber: 5};
+
+      const l3 = document.createElement('div');
+      l3.setAttribute('line-num', 3);
+      l3.setAttribute('comment-side', 'left');
+
+      const l5 = document.createElement('div');
+      l5.setAttribute('line-num', 5);
+      l5.setAttribute('comment-side', 'left');
+
+      const r3 = document.createElement('div');
+      r3.setAttribute('line-num', 3);
+      r3.setAttribute('comment-side', 'right');
+
+      const r5 = document.createElement('div');
+      r5.setAttribute('line-num', 5);
+      r5.setAttribute('comment-side', 'right');
+
+      const threadEls = [l3, l5, r3, r5];
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line),
+          [l3, r5]);
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+          Gerrit.DiffSide.LEFT), [l3]);
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+          Gerrit.DiffSide.RIGHT), [r5]);
+    });
+
+    test('_filterThreadElsForLocation for file comments', () => {
+      const line = {beforeNumber: 'FILE', afterNumber: 'FILE'};
+
+      const l = document.createElement('div');
+      l.setAttribute('comment-side', 'left');
+
+      const r = document.createElement('div');
+      r.setAttribute('comment-side', 'right');
+
+      const threadEls = [l, r];
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line),
+          [l, r]);
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+          Gerrit.DiffSide.BOTH), [l, r]);
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+          Gerrit.DiffSide.LEFT), [l]);
+      assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+          Gerrit.DiffSide.RIGHT), [r]);
+    });
+
     suite('_translateChunksToIgnore', () => {
       let content;
 
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
index 27e467d..6a9d88f 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
@@ -83,7 +83,7 @@
         targetClasses.push(SelectionClass.BLAME);
       } else {
         const commentSelected =
-            this._elementDescendedFromClass(e.target, 'gr-diff-comment');
+            this._elementDescendedFromClass(e.target, 'gr-comment');
         const side = this.diffBuilder.getSideByLineEl(lineEl);
 
         targetClasses.push(side === 'left' ?
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
index f34429b8..469a894 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
@@ -36,7 +36,7 @@
           <td class="content">
             <div class="contentText" data-side="left">ba ba</div>
             <div data-side="left">
-              <div class="gr-diff-comment-thread">
+              <div class="comment-thread">
                 <div class="gr-formatted-text message">
                   <span id="output" class="gr-linked-text">This is a comment</span>
                 </div>
@@ -58,7 +58,7 @@
           <td class="content">
             <div class="contentText" data-side="right">more more more</div>
             <div data-side="right">
-              <div class="gr-diff-comment-thread">
+              <div class="comment-thread">
                 <div class="gr-formatted-text message">
                   <span id="output" class="gr-linked-text">This is a comment on the right</span>
                 </div>
@@ -72,7 +72,7 @@
           <td class="content">
             <div class="contentText" data-side="left">ga ga</div>
             <div data-side="left">
-              <div class="gr-diff-comment-thread">
+              <div class="comment-thread">
                 <div class="gr-formatted-text message">
                   <span id="output" class="gr-linked-text">This is <a>a</a> different comment 💩 unicode is fun</span>
                 </div>
@@ -87,7 +87,7 @@
           <td class="content">
             <div class="contentText" data-side="left">ga ga</div>
             <div data-side="left">
-              <div class="gr-diff-comment-thread">
+              <div class="comment-thread">
                 <textarea data-side="right">test for textarea copying</textarea>
               </div>
             </div>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index 5a56069..dadf8a7 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -221,7 +221,7 @@
         [this.Shortcut.EXPAND_ALL_DIFF_CONTEXT]: '_handleExpandAllDiffContext',
         [this.Shortcut.NEXT_UNREVIEWED_FILE]: '_handleNextUnreviewedFile',
 
-        // Final two are actually handled by gr-diff-comment-thread.
+        // Final two are actually handled by gr-comment-thread.
         [this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
         [this.Shortcut.COLLAPSE_ALL_COMMENT_THREADS]: null,
       };
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index e587953..4ccdf96 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -294,7 +294,6 @@
               is-image-diff="[[isImageDiff]]"
               base-image="[[baseImage]]"
               revision-image="[[revisionImage]]">
-            <slot></slot>
             <table
                 id="diffTable"
                 class$="[[_diffTableClass]]"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index a8cf320..996d484 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -60,6 +60,20 @@
         node.classList.contains('comment-thread');
   }
 
+  /**
+   * Turn a slot element into the corresponding content element.
+   * Slots are only fully supported in Polymer 2 - in Polymer 1, they are
+   * replaced with content elements during template parsing. This conversion is
+   * not applied for imperatively created slot elements, so this method
+   * implements the same behavior as the template parsing for imperative slots.
+   */
+  Gerrit.slotToContent = function(slot) {
+    const content = document.createElement('content');
+    content.name = slot.name;
+    content.setAttribute('select', `[slot='${slot.name}']`);
+    return content;
+  };
+
   Polymer({
     is: 'gr-diff',
 
@@ -250,6 +264,7 @@
         // this situation until it occurs.
         this._updateRanges(addedThreadEls);
         this._updateKeyLocations(addedThreadEls);
+        this._redispatchHoverEvents(addedThreadEls);
       });
     },
 
@@ -274,6 +289,20 @@
       }
     },
 
+    // Dispatch events that are handled by the gr-diff-highlight.
+    _redispatchHoverEvents(addedThreadEls) {
+      for (const threadEl of addedThreadEls) {
+        threadEl.addEventListener('mouseenter', () => {
+          threadEl.dispatchEvent(
+              new CustomEvent('comment-thread-mouseenter', {bubbles: true}));
+        });
+        threadEl.addEventListener('mouseleave', () => {
+          threadEl.dispatchEvent(
+              new CustomEvent('comment-thread-mouseleave', {bubbles: true}));
+        });
+      }
+    },
+
     /** Cancel any remaining diff builder rendering work. */
     cancel() {
       this.$.diffBuilder.cancel();
@@ -440,14 +469,16 @@
      * Gets or creates a comment thread group for a specific line and side on a
      * diff.
      * @param {!Object} contentEl
+     * @param {!Gerrit.DiffSide} commentSide
      * @return {!Node}
      */
-    _getOrCreateThreadGroup(contentEl) {
+    _getOrCreateThreadGroup(contentEl, commentSide) {
       // Check if thread group exists.
       let threadGroupEl = this._getThreadGroupForLine(contentEl);
       if (!threadGroupEl) {
         threadGroupEl = document.createElement('div');
         threadGroupEl.className = 'thread-group';
+        threadGroupEl.setAttribute('data-side', commentSide);
         contentEl.appendChild(threadGroupEl);
       }
       return threadGroupEl;
@@ -609,8 +640,17 @@
               lineNumString, commentSide);
           const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
           const contentEl = contentText.parentElement;
-          const threadGroupEl = this._getOrCreateThreadGroup(contentEl);
-          Polymer.dom(threadGroupEl).appendChild(threadEl);
+          const threadGroupEl = this._getOrCreateThreadGroup(
+              contentEl, commentSide);
+          // Create a slot for the thread and attach it to the thread group.
+          // The Polyfill has some bugs and this only works if the slot is
+          // attached to the group after the group is attached to the DOM.
+          // The thread group may already have a slot with the right name, but
+          // that is okay because the first matching slot is used and the rest
+          // are ignored.
+          const slot = document.createElement('slot');
+          slot.name = threadEl.slot;
+          Polymer.dom(threadGroupEl).appendChild(Gerrit.slotToContent(slot));
         }
       });
     },
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
index fa488f0..8cee1f4 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
@@ -167,6 +167,9 @@
       const ranges = this.get(['_rangesMap', side, lineNum]) || [];
       return ranges
           .map(range => {
+            // Make a copy, so that the normalization below does not mess with
+            // our map.
+            range = Object.assign({}, range);
             range.end = range.end === -1 ? line.text.length : range.end;
 
             // Normalize invalid ranges where the start is after the end but the
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
similarity index 95%
rename from polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.html
rename to polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
index c3a1de4..8c80b37 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
@@ -22,9 +22,9 @@
 <link rel="import" href="../../core/gr-reporting/gr-reporting.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 <link rel="import" href="../../shared/gr-storage/gr-storage.html">
-<link rel="import" href="../gr-diff-comment/gr-diff-comment.html">
+<link rel="import" href="../gr-comment/gr-comment.html">
 
-<dom-module id="gr-diff-comment-thread">
+<dom-module id="gr-comment-thread">
   <template>
     <style include="shared-styles">
       gr-button {
@@ -72,7 +72,7 @@
     <div id="container" class$="[[_computeHostClass(unresolved)]]">
       <template id="commentList" is="dom-repeat" items="[[_orderedComments]]"
           as="comment">
-        <gr-diff-comment
+        <gr-comment
             comment="{{comment}}"
             robot-button-disabled="[[_hideActions(_showActions, _lastComment)]]"
             change-num="[[changeNum]]"
@@ -85,7 +85,7 @@
             project-config="[[_projectConfig]]"
             on-create-fix-comment="_handleCommentFix"
             on-comment-discard="_handleCommentDiscard"
-            on-comment-save="_handleCommentSavedOrDiscarded"></gr-diff-comment>
+            on-comment-save="_handleCommentSavedOrDiscarded"></gr-comment>
       </template>
       <div id="commentInfoContainer"
           hidden$="[[_hideActions(_showActions, _lastComment)]]">
@@ -122,5 +122,5 @@
     <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
     <gr-storage id="storage"></gr-storage>
   </template>
-  <script src="gr-diff-comment-thread.js"></script>
+  <script src="gr-comment-thread.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
similarity index 96%
rename from polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
rename to polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
index a2439d7..11fce6d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
@@ -21,7 +21,7 @@
   const NEWLINE_PATTERN = /\n/g;
 
   Polymer({
-    is: 'gr-diff-comment-thread',
+    is: 'gr-comment-thread',
 
     /**
      * Fired when the thread should be discarded.
@@ -36,7 +36,7 @@
      */
 
      /**
-      * gr-diff-comment-thread exposes the following attributes that allow a
+      * gr-comment-thread exposes the following attributes that allow a
       * diff widget like gr-diff to show the thread in the right location:
       *
       * line-num:
@@ -219,7 +219,7 @@
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
 
       // Don’t preventDefault in this case because it will render the event
-      // useless for other handlers (other gr-diff-comment-thread elements).
+      // useless for other handlers (other gr-comment-thread elements).
       if (e.detail.keyboardEvent.shiftKey) {
         this._expandCollapseComments(true);
       } else {
@@ -230,7 +230,7 @@
 
     _expandCollapseComments(actionIsCollapse) {
       const comments =
-          Polymer.dom(this.root).querySelectorAll('gr-diff-comment');
+          Polymer.dom(this.root).querySelectorAll('gr-comment');
       for (const comment of comments) {
         comment.collapsed = actionIsCollapse;
       }
@@ -283,7 +283,7 @@
           parent.range);
 
       // If there is currently a comment in an editing state, add an attribute
-      // so that the gr-diff-comment knows not to populate the draft text.
+      // so that the gr-comment knows not to populate the draft text.
       for (let i = 0; i < this.comments.length; i++) {
         if (this.comments[i].__editing) {
           reply.__otherEditing = true;
@@ -350,7 +350,7 @@
     },
 
     _commentElWithDraftID(id) {
-      const els = Polymer.dom(this.root).querySelectorAll('gr-diff-comment');
+      const els = Polymer.dom(this.root).querySelectorAll('gr-comment');
       for (const el of els) {
         if (el.comment.id === id || el.comment.__draftID === id) {
           return el;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
similarity index 95%
rename from polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html
rename to polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
index 1881497..2e1b3bd 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
@@ -17,31 +17,31 @@
 -->
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-diff-comment-thread</title>
+<title>gr-comment-thread</title>
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
 <link rel="import" href="../../../test/common-test-setup.html"/>
 <script src="../../../scripts/util.js"></script>
 
-<link rel="import" href="gr-diff-comment-thread.html">
+<link rel="import" href="gr-comment-thread.html">
 
 <script>void(0);</script>
 
 <test-fixture id="basic">
   <template>
-    <gr-diff-comment-thread></gr-diff-comment-thread>
+    <gr-comment-thread></gr-comment-thread>
   </template>
 </test-fixture>
 
 <test-fixture id="withComment">
   <template>
-    <gr-diff-comment-thread></gr-diff-comment-thread>
+    <gr-comment-thread></gr-comment-thread>
   </template>
 </test-fixture>
 
 <script>
-  suite('gr-diff-comment-thread tests', () => {
+  suite('gr-comment-thread tests', () => {
     let element;
     let sandbox;
 
@@ -248,7 +248,7 @@
     });
 
     test('reply', () => {
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       const reportStub = sandbox.stub(element.$.reporting,
           'recordDraftInteraction');
       assert.ok(commentEl);
@@ -267,7 +267,7 @@
     });
 
     test('quote reply', () => {
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       const reportStub = sandbox.stub(element.$.reporting,
           'recordDraftInteraction');
       assert.ok(commentEl);
@@ -300,7 +300,7 @@
       }];
       flushAsynchronousOperations();
 
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       assert.ok(commentEl);
 
       const quoteBtn = element.$.quoteBtn;
@@ -323,7 +323,7 @@
       element.changeNum = '42';
       element.patchNum = '1';
 
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       assert.ok(commentEl);
 
       const ackBtn = element.$.ackBtn;
@@ -346,7 +346,7 @@
           'recordDraftInteraction');
       element.changeNum = '42';
       element.patchNum = '1';
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       assert.ok(commentEl);
 
       const doneBtn = element.$.doneBtn;
@@ -368,12 +368,12 @@
       element.changeNum = '42';
       element.patchNum = '1';
       element.path = '/path/to/file.txt';
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       assert.ok(commentEl);
 
       const saveOrDiscardStub = sandbox.stub();
       element.addEventListener('thread-changed', saveOrDiscardStub);
-      element.$$('gr-diff-comment')._fireSave();
+      element.$$('gr-comment')._fireSave();
 
       flush(() => {
         assert.isTrue(saveOrDiscardStub.called);
@@ -389,7 +389,7 @@
     test('please fix', done => {
       element.changeNum = '42';
       element.patchNum = '1';
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       assert.ok(commentEl);
       commentEl.addEventListener('create-fix-comment', () => {
         const drafts = element._orderedComments.filter(c => {
@@ -420,7 +420,7 @@
       const saveOrDiscardStub = sandbox.stub();
       element.addEventListener('thread-changed', saveOrDiscardStub);
       const draftEl =
-          Polymer.dom(element.root).querySelectorAll('gr-diff-comment')[1];
+          Polymer.dom(element.root).querySelectorAll('gr-comment')[1];
       assert.ok(draftEl);
       draftEl.addEventListener('comment-discard', () => {
         const drafts = element.comments.filter(c => {
@@ -452,7 +452,7 @@
           const saveOrDiscardStub = sandbox.stub();
           element.addEventListener('thread-changed', saveOrDiscardStub);
           const draftEl =
-          Polymer.dom(element.root).querySelectorAll('gr-diff-comment')[0];
+          Polymer.dom(element.root).querySelectorAll('gr-comment')[0];
           assert.ok(draftEl);
           draftEl.addEventListener('comment-discard', () => {
             assert.equal(element.comments.length, 0);
@@ -534,7 +534,7 @@
       flushAsynchronousOperations();
 
       const draftEl =
-      Polymer.dom(element.root).querySelectorAll('gr-diff-comment')[1];
+      Polymer.dom(element.root).querySelectorAll('gr-comment')[1];
       assert.ok(draftEl);
       draftEl.addEventListener('comment-discard', () => {
         assert.isFalse(storageStub.called);
@@ -546,7 +546,7 @@
     });
 
     test('comment-update', () => {
-      const commentEl = element.$$('gr-diff-comment');
+      const commentEl = element.$$('gr-comment');
       const updatedComment = {
         id: element.comments[0].id,
         foo: 'bar',
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
similarity index 97%
rename from polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html
rename to polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
index 72c7285..a470285 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
@@ -35,7 +35,7 @@
 <link rel="import" href="../gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.html">
 <script src="../../../scripts/rootElement.js"></script>
 
-<dom-module id="gr-diff-comment">
+<dom-module id="gr-comment">
   <template>
     <style include="shared-styles">
       :host {
@@ -232,10 +232,7 @@
         display: block;
       }
     </style>
-    <div id="container"
-        class="container"
-        on-mouseenter="_handleMouseEnter"
-        on-mouseleave="_handleMouseLeave">
+    <div id="container" class="container">
       <div class="header" id="header" on-tap="_handleToggleCollapsed">
         <div class="headerLeft">
           <span class="authorName">[[comment.author.name]]</span>
@@ -387,5 +384,5 @@
     <gr-storage id="storage"></gr-storage>
     <gr-reporting id="reporting"></gr-reporting>
   </template>
-  <script src="gr-diff-comment.js"></script>
+  <script src="gr-comment.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
similarity index 97%
rename from polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
rename to polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
index 5165db0..a576583 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
@@ -32,7 +32,7 @@
   const FILE = 'FILE';
 
   Polymer({
-    is: 'gr-diff-comment',
+    is: 'gr-comment',
 
     /**
      * Fired when the create fix comment action is triggered.
@@ -59,14 +59,6 @@
      */
 
     /**
-     * @event comment-mouse-over
-     */
-
-    /**
-     * @event comment-mouse-out
-     */
-
-    /**
      * Fired when the comment's timestamp is tapped.
      *
      * @event comment-anchor-tap
@@ -610,14 +602,6 @@
       }
     },
 
-    _handleMouseEnter(e) {
-      this.fire('comment-mouse-over', this._getEventPayload());
-    },
-
-    _handleMouseLeave(e) {
-      this.fire('comment-mouse-out', this._getEventPayload());
-    },
-
     _handleToggleResolved() {
       this.$.reporting.recordDraftInteraction();
       this.resolved = !this.resolved;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
similarity index 98%
rename from polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
rename to polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
index 912e615..7ca5242 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
@@ -17,7 +17,7 @@
 -->
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
-<title>gr-diff-comment</title>
+<title>gr-comment</title>
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
@@ -25,19 +25,19 @@
 <script src="../../../bower_components/page/page.js"></script>
 <script src="../../../scripts/util.js"></script>
 
-<link rel="import" href="gr-diff-comment.html">
+<link rel="import" href="gr-comment.html">
 
 <script>void(0);</script>
 
 <test-fixture id="basic">
   <template>
-    <gr-diff-comment></gr-diff-comment>
+    <gr-comment></gr-comment>
   </template>
 </test-fixture>
 
 <test-fixture id="draft">
   <template>
-    <gr-diff-comment draft="true"></gr-diff-comment>
+    <gr-comment draft="true"></gr-comment>
   </template>
 </test-fixture>
 
@@ -48,7 +48,7 @@
     return getComputedStyle(el).getPropertyValue('display') !== 'none';
   }
 
-  suite('gr-diff-comment tests', () => {
+  suite('gr-comment tests', () => {
     let element;
     let sandbox;
     setup(() => {
@@ -343,7 +343,7 @@
     });
   });
 
-  suite('gr-diff-comment draft tests', () => {
+  suite('gr-comment draft tests', () => {
     let element;
     let sandbox;
 
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index 20a4a1e..3b91650 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -103,8 +103,6 @@
     'core/gr-smart-search/gr-smart-search_test.html',
     'diff/gr-comment-api/gr-comment-api_test.html',
     'diff/gr-diff-builder/gr-diff-builder_test.html',
-    'diff/gr-diff-comment-thread/gr-diff-comment-thread_test.html',
-    'diff/gr-diff-comment/gr-diff-comment_test.html',
     'diff/gr-diff-cursor/gr-diff-cursor_test.html',
     'diff/gr-diff-highlight/gr-annotation_test.html',
     'diff/gr-diff-highlight/gr-diff-highlight_test.html',
@@ -157,6 +155,8 @@
     'shared/gr-button/gr-button_test.html',
     'shared/gr-change-star/gr-change-star_test.html',
     'shared/gr-change-status/gr-change-status_test.html',
+    'shared/gr-comment-thread/gr-comment-thread_test.html',
+    'shared/gr-comment/gr-comment_test.html',
     'shared/gr-copy-clipboard/gr-copy-clipboard_test.html',
     'shared/gr-cursor-manager/gr-cursor-manager_test.html',
     'shared/gr-date-formatter/gr-date-formatter_test.html',