21 Commits

Author SHA1 Message Date
Wyatt Allen
bae435c7a6 Introduce diff builder for binary files
Binary files cannot be diffed like text, but for some binary changes,
the diff algorithm does yield binary differences as text. With this
change, the diff builder and processor are taught to render a special
message for (non-image) binary diffs, and will ignore the text
representation of the delta.

Bug: Issue 4031
Change-Id: I2dcdbe9def006de827a37c35c42606bc1c9cf4fc
2017-11-27 11:00:08 -08:00
Becky Siegel
8d92d53db5 Annotation updates
Change-Id: I146f76b9dcc1a92e18acec01481ad280fb431868
2017-08-12 11:49:52 -07:00
Alice Kober-Sotzek
ec44e83877 Highlight hunks which are due to rebase on PolyGerrit
Change-Id: Ifd31c8b2d31d71ff19060da56d81b64954f4fdb7
2017-06-09 13:38:50 +02:00
Alice Kober-Sotzek
1afa2cb52e Copy due_to_rebase to subgroups in gr-diff-processor
We need to preserve the "due_to_rebase" sections to correctly
process the subgroups.

Change-Id: I3d5f8fbd70d50a92e305960cbcecf0d811b4c980
2017-06-09 13:38:50 +02:00
Mike Samuel
e07c4b2ea1 Add polygerrit-ui/app/test/common-test-setup.html
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
2017-06-05 22:10:12 +00:00
Wyatt Allen
c601abccc3 Revert "Polygerrit now loads polymer-resin"
This reverts commit 0895052c01ac5ac657a9763d2ad9967d9ae55c18.

Reason for revert: issue 6387

Change-Id: I14e00addeab53606952aa3ea2d45a74eac7a9d8a
2017-06-02 09:37:37 -07:00
Mike Samuel
0895052c01 Polygerrit now loads polymer-resin
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.md
https://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
2017-05-30 23:16:09 -04:00
Kasper Nilsson
98501986a8 ES6ify /gr-diff-processor/*
Prior change was reverted due to incorrect modification of lint config.

Bug: Issue 6179
Change-Id: Ieb795403ffa86752d41ae39a4b963e7a1b42b573
2017-05-17 15:33:02 -07:00
Wyatt Allen
d71f6c54df Improved shared group decomposition
Shared groups were broken down in I8018535ee7 to improve perceived
performance using a diff of Go's go_spec.html as a benchmark. However,
the total render time became slower with this change because the
decomposed groups thrashed the layout.

With this change, shared groups are decomposed into two groups to
achieve the same perceived responsiveness, but balance that with total
render time and avoid needless layouts.

The Maximum group size in increased to 120 to further reduce the number
of groups.

Some performance numbers for the go_spec.html benchmark diff and the
config_dump.json diff indicated in the linked issue.

                        +------------------+--------------+
                        | config_dump.json | go_spec.html |
+-----------------------+------------------+--------------+
| Content Render Before |       83877.2 ms |    7815.2 ms |
+-----------------------+------------------+--------------+
|  Content Render After |       17492.0 ms |    3363.4 ms |
+-----------------------+------------------+--------------+
|        Speedup Factor |          ~4.8    |      ~2.3    |
+-----------------------+------------------+--------------+

Further performance improvements to follow.

Bug: Issue 5778
Change-Id: I97751b7b78b821a794374cbfeecb16d59d5e1c4c
2017-05-04 10:26:08 -07:00
Becky Siegel
7fe6a3b4cc Don't show binary image content & fix image label
Previously there were times when binary data from an image diff would
display. This change adds a check in the diff processor for image diffs
and does not display anything other than the file line in that case.

This change also addresses an issue where the label is calculated too
soon. The image size (if it exists) is supposed to be included as part
of the label, but often this was calculated before the image was done
rendering, so it didn't display.

Bug: Issue 5887
Change-Id: I9cd1ad0c3f2603492d7d84892147bd6852bbae29
2017-03-31 10:11:16 -07:00
Viktar Donich
29e1ce5e84 Collection of prospective test flake fixes
Potentially related:
https://github.com/Polymer/web-component-tester/issues/505

Bug: Issue 5792
Change-Id: I9ab6e8e40d9811dd52906335426764c052907609
2017-03-30 13:46:58 -07:00
Wyatt Allen
1ce7fadaef Incremental rendering for large shared groups under full-context
Formerly, incremental rendering had not been applied to shared chunks
because it would break context-grouping logic. However, when the context
is set to the whole file, this problem is averted because the
context-groups are not created. Apply incremental rendering to shared
chunks only when the context is set to whole file.

Change-Id: I8018535ee72e5d4ef499628181298a13e8b20d06
2017-03-13 14:37:30 -07:00
Wyatt Allen
9d8649bfa1 Prevent single-line collapsed common groups
When the diff processor collapses shared groups based on the user
context preference, it would sometimes collapse a single line, resulting
in a common group labeled "Show 1 common line" which takes up exactly
as much space in the diff view as the line itself. Moreover, the GWT UI
does not collapse single line common sections in this way (but does when
there are two or more lines).

Sets the threshold to collapse at least two lines and encodes this in a
test.

Bug: Issue 4721
Change-Id: I8a3a8556fd66a313eacc361379612c700d7ae070
2016-10-12 10:50:03 -07:00
Wyatt Allen
b539c90d02 Cancel diff processing when the diff processor is detached
Bug: Issue 4730
Change-Id: I50cae3c2c59b447befdccde3fcb4bf4a7dadcae8
2016-10-07 17:09:03 -07:00
Viktar Donich
a55f6e1214 Pause diff rendering on window scroll
Bug: Issue 4364
Change-Id: If1bc1560fa98b170e776fd0afd9782d8ca38e769
2016-08-23 10:27:33 -07:00
Wyatt Allen
32b03fc76f Applies optimizations to diff comment DOM attachment
A source of latency when creating diff comments in large diffs is the
work needed to reflow the diff DOM to make room for the new comment.
This is particularly evident when adding comments to new files because
the diff is built as an addition group representing the entire file, so
the comment causes a reflow on every subsequent line.

This change optimizes this process in three ways.

* **Limit the size of ADD & REMOVE groups:** The diff processor will now
  break an add or a remove chunk into a series of smaller chunks of the
  same kind. This is controlled by the MAX_GROUP_SIZE constant. In this
  way the number of nodes that need to be reflowed when a comment is
  added to an add or remove group is limited to the number of subsequent
  lines in that group plus the subsequent number of groups.
* **GPU optimize group in general:** Adds CSS properties to diff TBODY
  elements (which correspond to groups, for the most part) that trigger
  GPU acceleration when available.
* **Apply `table-layout: fixed;`** This style speeds up table reflow in
  general.

Change-Id: Ie0e3665b7752fec67f7123cfae70ae99e6f67521
2016-08-11 12:35:31 -07:00
Urs Wolfer
33df005810 Fix issues detected by 'JSHint' and 'JSCS'
Change-Id: Ic1437333fcf82473ac57f8bdea25ee8188ddbfee
2016-07-15 20:32:27 +02:00
Wyatt Allen
0f0c94189f Process/render diff groups in synchronous batches based on size
Previously each group was rendered asynchronously, i.e. deferring
control between each group render. This caused the total render time to
be ~10x slower than totally synchronous. But the advantage of this
approach was that the content at the start of the diff would be visible
as soon as possible.

This change finds a compromise by combining processing/rendering the
diff groups in larger synchronous batches which are based on the number
of lines in the groups.

Change-Id: I5d42700962f51bea0dedb05763a1d8eb1c32bfd1
2016-07-12 22:13:13 -07:00
Wyatt Allen
db881fa0ad Asynchronous diff rendering
Building on existing support for asynchronous diff processing, the
rendering stage is now also asynchronous. The `emitGroup` method of
gr-diff-builder (which constructs a DOM fragment and attaches it to the
document) is now called whenever the processor emits a new group, rather
than waiting for all groups to be available and looping over them.

Adds support for canceling the processor, and removes a behavior where
the diff was being re-rendered needlessly, causing visible flicker.
Updates a test that broke when rendering became asynchronous.

Change-Id: I37fcd65efc8c901b85fc93e91611c022edc10dc4
2016-06-30 10:09:19 -07:00
Wyatt Allen
8e20db3119 Refactor gr-diff-processor to use an asynchronous loop
Modifies the `process` method of gr-diff-processor to traverse diff
content using an asynchronous recursive loop rather than a blocking
for-loop. The async version maintains the promise interface already
established.

Refactored to constrain side-effects to the `process` method. Whereas,
formerly, helper methods in gr-diff-processor both read and wrote the
component's internal state, they are rewritten to be more pure, making
them simpler to understand, test, and invoke asynchronously.

Documentation is added throughout as well as tests for helper functions.

Note that this change only makes the processing step asynchronous.
Upgrading the diff-rendering stage to be non-blocking will come in a
later change.

Change-Id: Ifd50eeb75797b173937890caacc92cad5675fc20
2016-06-29 10:36:41 -07:00
Wyatt Allen
7f2bd97901 Separates diff processing from diff building
Moves the diff-processing functionality of the gr-diff-builder component
into a new gr-diff-processor component which exposes a promise-based
interface. This is step one of creating an asynchronous (non-blocking)
diff rendering system.

As much as possible, this change is a transfer of code (with tests) from
one component to another, making it easier to verify that functionality
has not changed. Cleanup of the code, and refactoring it into a
more-testable form will come with later changes.

Feature: Issue 3916
Change-Id: I875b03b20bf953b128cbe3c5001ba1f8eba12c61
2016-06-27 16:44:19 -07:00