When a new comment is being added to a line, Gerrit checks to see if
there is an existing thread on the same line (and same range, if any) so
that the comment can be appended to it if so. Otherwise, a new thread is
created.
However, following I4f7804ac02, the logic to identify the appropriate
thread by range was refactored to not use range location strings, but
use range objects instead. Problematically, there were two flaws in this
code:
1) The range object references were compared rather than their values.
2) Only new threads were being rendered with their corresponding ranges
whereas existing threads were not.
As a result, if the user attempted to add a line comment on a line with
an existing ranged comment, the ranged comment's thread would be
identified as the destination (because the new comment has no range and
the existing thread's range was not being set). Appending the range-less
comment to a ranged thread resulted in incoherent data and the draft
would be unsavable.
With this change, the logic uses value equality to match ranges and the
`gr-diff-comment-thread-group#_getThreads` method is updated to set the
range on existing threads.
Bug: Issue 8410
Change-Id: If34e0d46a5c1af81bec82125217088fb574a2f61
Follow-up to https://gerrit-review.googlesource.com/c/gerrit/+/157590
which no longer used locationRange to group comments together into
threads. However, locationRange was still used for a few other things
including thread removal, which could result in a bug if there were
two threads that had the same locationRange and the wrong one was
found first.
Things included in this change:
1. Determine whether a thread group exists
- This is identified as it was before. The thread group now gets a
commentSide attribute, as it can pass it to all of its children
(the same for all).
2. Determine if a thread exists within the group for a given range in a
group
- The range object is now included as an attribute on the comment
thread instead of the locationRange string.
3. Be able to remove a thread group
- A rootId attribute is now stored on the comment thread, which is
data bound to each comment. When a comment is removed, it finds the
thread with the rootId within the thread group to remove.
- In the event that a thread group only contains a single draft,
there is no roottId.
Change-Id: I4f7804ac02f4259b4964c6333d258f0fc3b29d24
The UI does not allow creating multiple comments at the same diff
location, but instead encourages contributing to the comment threads
already at a location. The uniqueness of thread locations was leveraged
to simplify the collection of comments into threads by mapping their
locations to keys.
However, the REST API does permit multiple threads starting from the
same diff location, so this expectation in the key-based UI threading
logic can be wrong. In such scenarios, an unresolved thread may be
mistakenly inserted into a resolved thread, resulting in a comment that
is not resolvable through the UI.
With this change, the threading logic in gr-diff-comment-thread-group is
updated to associate comments into threads via the `in_reply_to` graph
rather than location map in the same way that the
`unresolved_comment_count` detail property is determined server-side.
Bug: Issue 6779
Change-Id: Ibb29d4ba5c5de9e92dfbfba8ac7ac8037c332028
Formerly, if a formatted text component tried to render without the
project config (used by inner linked text components) it would
temporarily fall-back to rendering the unformatted (and un-linkified)
text via `.textContent` -- mirroring the behavior of gr-linked-text.
The result is formatted text elements (when rendered without a project
config) appear as one long line of text. Unlike linkification, however,
text can be accurately formatted with or without the project config --
so this disruptive, poor UX is unnecessary.
The formatted text component is updated to format text when the project
config has not provided, and to re-render when the config has been
provided.
In order to propagate project config loads to the formatted text
components hosted by diff comments, the REST calls must be made by the
diff thread component. To make this call, the thread must have the
project's name, so gr-diff-builder is updated to provide this name to
thread components.
Bug: Issue 6686
Change-Id: I8d09c740930500e99cb5f87b92f4d72f3f50a9ce
There were a few instances in which classes applied to hide evyerhting
in a dom-repeat were applied to the dom-repeat itself. This throws
and error in Polymer2. Instead, apply it to a (new) tbody element.
Change-Id: Ia4a41574d4b1aea60dc5927e07000317ad71f74d
This is a partial roll-forward of c/106190
This replaces all loads of iron-test-helpers with a load of a file
that wraps it, and adds that file to test files that do not currently
load iron-test-helpers.
A future CL will also install polymer-resin via common-test-helpers.html.
I tested by running
$ WCT_ARGS="-l chrome" ./polygerrit-ui/app/run_test.sh
Change-Id: Ifb3cd2c8db13d724f57e56e7e78045470d103a43
- Create a shared style module that is included in every custom element
- Add the shared style module to each existing element
Change-Id: I1ee382955afe4ff630548a6640e7c4d03688849d
polymer-resin intercepts polymer property assignments
before they reach XSS-vulnerable sinks like `href="..."`
and text nodes in `<script>` elements.
This follows the instructions in WORKSPACE for adding a new bower
dependency with kaspern's tweak to use the dependency in a rule so
that it's found. //lib/js/bower_components.bzl has already been
rolled-back per those instructions.
The license is the polymer license as can be seen at
https://github.com/Polymer/polymer-resin/blob/master/LICENSE though
I'm not sure that //tools/js/bower2bazel.py recognizes it as such.
Docs for the added component are available at
https://github.com/Polymer/polymer-resin/blob/master/README.mdhttps://github.com/Polymer/polymer-resin/blob/master/getting-started.md
With this change, when I introduce an XSS vulnerability as below,
polymer-resin intercepts and stops it.
Patch that introduces a strawman vulnerability.
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
@@ -55,6 +55,10 @@
url: '/q/status:abandoned',
name: 'Abandoned',
},
+ {
+ url: location.hash.replace(/^#/, '') || 'http://example.com/#fragment_echoed_here',
+ name: 'XSS Me',
+ },
],
}];
---
Address kaspern's and paladox's comments.
---
Undo version bumps for bower dependencies.
---
Change Soy index template to parallel app/index.html.
---
update polymer-resin to version 1.1.1-beta
----
Load polymer-resin into polygerrit-ui/**/*_test.html
After this, I ran the tests with
-l chrome
-l firefox
I ran a handful of tests with -p and observed that the
console shows "initResin" is called before test cases start
executing.
These changes were done programmaticly by running the script below
(approximately) thus:
```
gerrit/ $ cd polygerrit-ui/app
app/ $ find . -name \*test.html | xargs perl hack-tests.pl
```
```
use strict;
sub removeResin($) {
my $s = $_[0];
$s =~ s@<link rel="import" href="[^"]*/polymer-resin/[^"]*"[^>]*>\n?@@;
$s =~ s@<script src="[^"]*/polymer-resin/[^"]*"></script>\n?@@;
$s =~ s@<script>\s*security\.polymer_resin.*?</script>\n?@@s;
return $s;
}
for my $f (@ARGV) {
next if $f =~ m@/bower_components/|/node_modules/@;
system('git', 'checkout', $f);
print "$f\n";
my @lines = ();
open(IN, "<$f") or die "$f: $!";
my $maxLineOfMatch = 0;
while (<IN>) {
push(@lines, $_);
# Put a marker after core loading directives.
$maxLineOfMatch = scalar(@lines)
if m@/webcomponentsjs/|/polymer[.]html\b|/browser[.]js@;
}
close(IN) or die "$f: $!";
die "$f missing loading directives" unless $maxLineOfMatch;
# Given ./a/b/c/my_test.html, $pathToRoot is "../../.."
# assuming no non-leading . or .. components in the path from find.
my $pathToRoot = $f;
$pathToRoot =~ s@^\.\/@@;
$pathToRoot =~ s@^(.*?/)?app/@@;
$pathToRoot =~ s@\/[^\/]*$@@;
$pathToRoot =~ s@[^/]+@..@g;
my $nLines = scalar(@lines);
open(OUT, ">$f") or die "$f: $!";
# Output the lines up to the last polymer-resin dependency
# loaded explicitly by this test.
my $before = join '', @lines[0..($maxLineOfMatch - 1)];
$before = removeResin($before);
print OUT "$before";
# Dump out the lines that load polymer-resin and configure it for
# polygerrit.
if (1) {
print OUT qq'<link rel="import" href="$pathToRoot/bower_components/polymer-resin/standalone/polymer-resin-debug.html"/>
<script>
security.polymer_resin.install({allowedIdentifierPrefixes: [\'\']});
</script>
';
}
# Emit any remaining lines.
my $after = join '', @lines[$maxLineOfMatch..$#lines];
$after = removeResin($after);
$after =~ s/^\n*//;
print OUT "$after";
close(OUT) or die "$f: $!";
}
```
---
update polymer-resin to version 1.2.1-beta
---
update Soy index template to new style polymer-resin initialization
----
fix lint warnings
----
Load test/common-test-setup.html into *_test.html
Instead of inserting instructions to load and initialize polymer-resin into
every test file, add a common-test-setup.html that does that and also fold
iron-test-helpers loading into it.
----
imported files do not need to load webcomponentsjs
Change-Id: I71221c36ed8a0fe7f8720c1064a2fcc9555bb8df
Use '__isOnParent' as a boolean in place if 'side' ('PARENT vs
'REVISION'). In doing so, it's necessary to convert to/from 'side'
whenever interacting with the REST API.
Change-Id: Ic023c9be1969597e4b9c73a51cfed9f5eb9bc23e
Previously, there was an issue where if you create a draft comment in
side by side view and switch to unified view, the comment thinks it's in
the later patch set rather than the earlier one and a second copy gets
added to local storage with the later patchset as a component of the
key.
This was because the the thread group assumed all threads inside of it
had the same patch number. This change fixes that, so in the event that
a user switches from side by side to unified, the patch number will get
taken from the comment rather than the thread group.
Bug: Issue 5493
Change-Id: I7f00997bcb2e6f1001a5d58ac206acf5af3367d2
Move all buttons that generate a reply of some sort (done, ack, reply,
quote) to the comment thread instead of the comment [1].
When there is a draft for a particular comment thread, all reply buttons
are hidden [2]. For example, if you click reply, you cannot click done
on the same thread, unless you remove the draft.
Each thread can have up to 1 draft. It's also worth noting that if a
thread has a draft, and the user clicks on the line or 'c' at the same
range, the existing draft will switch to 'editing' form.
[1] With the exception of "please fix" for robot comments.
[2] In this case, The please fix button will be disabled when other
reply buttons are hidden.
Feature: Issue 5410
Change-Id: Id847ee0cba0d0ce4e5b6476f58141866d41ffdad
Goes along with c/95273/. Adds commentSide attribute to comments to see
which side of the diff view they belong on. This is also used as part
of the locationRange for the gr-diff-comment-thread-group, so that two
thread groups can be on the same line or range for the unified group (
one for the right, one for the left).
Note: there is already a 'side' attribute on the gr-diff-comment, which
is confusing. This side actually references 'PARENT' or 'REVISION', to
identify whether the comment belongs to the parent or any revision. On
diffs where two revisions are compared to each other, this cannot be
used to determine left/right. However, because 'side' is part of
the CommentInfo entity[1], it is difficult to change the name and make
more sense out of that.
[1] https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#comment-info
Bug: Issue 5114
Change-Id: I5cc4c17d4bb134e31e5cc07ff9b08ed349488c97
- Add concept of diff comment thread groups, which are all of the
threads at a particular line number.
- The thread group is responsible for breaking up comments into threads
based on the range of the comment.
- Thread groups are ordered by the updated time of the first comment in
the group.
- Thread groups are given a key, based on comment range, which is used
to determine what thread group a new comment should go in (or if it
needs a new one).
Feature: Issue 5292
Change-Id: If544e8bb879262de3ce5397e86124837b66ada04